mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-10 04:37:55 +08:00
build: restructure cmake (#8210)
Co-authored-by: Erik Tagirov <erik.tagirov@edgemtech.ch>
This commit is contained in:
@@ -335,13 +335,14 @@ def write_c_array_file(
|
||||
header = f'''
|
||||
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
|
||||
#include "lvgl.h"
|
||||
#elif defined(LV_LVGL_H_INCLUDE_SYSTEM)
|
||||
#include <lvgl.h>
|
||||
#elif defined(LV_BUILD_TEST)
|
||||
#include "../lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@ fi
|
||||
cd ..
|
||||
|
||||
# Generate lv_conf
|
||||
LV_CONF_PATH=lvgl/configs/ci/docs/lv_conf_docs.h
|
||||
LV_CONF_PATH=`pwd`/lvgl/configs/ci/docs/lv_conf_docs.h
|
||||
|
||||
cp lvgl/lv_conf_template.h $LV_CONF_PATH
|
||||
python ./lvgl/scripts/generate_lv_conf.py \
|
||||
@@ -38,7 +38,7 @@ python ./lvgl/scripts/generate_lv_conf.py \
|
||||
|
||||
mkdir cmbuild
|
||||
cd cmbuild
|
||||
emcmake cmake .. -DLV_CONF_PATH=$LV_CONF_PATH -DLVGL_CHOSEN_DEMO=lv_example_noop -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
emcmake cmake .. -DLV_BUILD_CONF_PATH=$LV_CONF_PATH -DLVGL_CHOSEN_DEMO=lv_example_noop -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
emmake make -j$(nproc)
|
||||
rm -rf CMakeFiles
|
||||
cd ../..
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# Generate the cmake variables CONFIG_LV_USE_* from the
|
||||
# Generate the cmake variables CONFIG_LV_USE_* or CONFIG_LV_BUILD_* from the
|
||||
# preprocessed lv_conf_internal.h
|
||||
#
|
||||
# Author: David TRUAN (david.truan@edgemtech.ch)
|
||||
@@ -20,7 +20,7 @@ def fatal(msg):
|
||||
def get_args():
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description=""
|
||||
"Convert the expanded lv_conf_internal.h to cmake variables."
|
||||
"It converts all LV_USE_* configurations."
|
||||
"It converts all LV_USE_*, LV_BUILD_* configurations."
|
||||
)
|
||||
|
||||
parser.add_argument('--input', type=str, required=True, nargs='?',
|
||||
@@ -55,13 +55,14 @@ def generate_cmake_variables(path_input: str, path_output: str, kconfig: bool, d
|
||||
fin = open(path_input)
|
||||
fout = open(path_output, "w", newline='')
|
||||
|
||||
# If we use Kconfig, we must check the CONFIG_LV_USE_* defines
|
||||
# If we use Kconfig, we must check the CONFIG_LV_USE_* and
|
||||
# CONFIG_LV_BUILD_* defines
|
||||
if kconfig:
|
||||
CONFIG_PATTERN="#define CONFIG_LV_USE"
|
||||
CONFIG_PATTERN="^#define +(CONFIG_LV_USE|CONFIG_LV_BUILD)"
|
||||
CONFIG_PREFIX=""
|
||||
# Otherwise check the LV_USE_* defines
|
||||
# Otherwise check the LV_USE_* and LV_BUILD_* defines
|
||||
else:
|
||||
CONFIG_PATTERN="#define LV_USE"
|
||||
CONFIG_PATTERN="^#define +(LV_USE|LV_BUILD)"
|
||||
CONFIG_PREFIX="CONFIG_"
|
||||
|
||||
|
||||
@@ -71,7 +72,7 @@ def generate_cmake_variables(path_input: str, path_output: str, kconfig: bool, d
|
||||
|
||||
# Treat the LV_USE_STDLIB_* configs in a special way, as we need
|
||||
# to convert the define to full config with 1 value when enabled
|
||||
if line.startswith(f'{CONFIG_PATTERN}_STDLIB'):
|
||||
if re.search(f'{CONFIG_PATTERN}_STDLIB', line):
|
||||
|
||||
parts = line.split()
|
||||
if len(parts) < 3:
|
||||
@@ -88,7 +89,7 @@ def generate_cmake_variables(path_input: str, path_output: str, kconfig: bool, d
|
||||
|
||||
# Treat the LV_USE_OS config in a special way, as we need
|
||||
# to convert the define to full config with 1 value when enabled
|
||||
if line.startswith(f'{CONFIG_PATTERN}_OS'):
|
||||
if re.search(f'{CONFIG_PATTERN}_OS', line):
|
||||
|
||||
parts = line.split()
|
||||
if len(parts) < 3:
|
||||
@@ -104,7 +105,8 @@ def generate_cmake_variables(path_input: str, path_output: str, kconfig: bool, d
|
||||
write_set_cmd(fout, f'{CONFIG_PREFIX}{name} 1', is_parent_scope)
|
||||
|
||||
# For the rest of the configs, simply add CONFIG_ and write the name of the define
|
||||
# all LV_USE_* configs where the value is 0 or 1, as these are the one needed in cmake
|
||||
# all LV_USE_* or LV_BUILD_* configs where the value is 0 or 1,
|
||||
# as these are the ones that are needed in cmake
|
||||
# To detect the configuration of LVGL to perform conditional compilation/linking
|
||||
elif re.search(f'{CONFIG_PATTERN}.* +[01] *$', line):
|
||||
|
||||
|
||||
@@ -214,6 +214,22 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#define LV_USE_MEM_MONITOR 0
|
||||
#endif /*LV_USE_SYSMON*/
|
||||
|
||||
#if LV_BUILD_DEMOS == 0
|
||||
#define LV_USE_DEMO_WIDGETS 0
|
||||
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
|
||||
#define LV_USE_DEMO_BENCHMARK 0
|
||||
#define LV_USE_DEMO_RENDER 0
|
||||
#define LV_USE_DEMO_STRESS 0
|
||||
#define LV_USE_DEMO_MUSIC 0
|
||||
#define LV_USE_DEMO_VECTOR_GRAPHIC 0
|
||||
#define LV_USE_DEMO_FLEX_LAYOUT 0
|
||||
#define LV_USE_DEMO_MULTILANG 0
|
||||
#define LV_USE_DEMO_TRANSFORM 0
|
||||
#define LV_USE_DEMO_SCROLL 0
|
||||
#define LV_USE_DEMO_EBIKE 0
|
||||
#define LV_USE_DEMO_HIGH_RES 0
|
||||
#define LV_USE_DEMO_SMARTWATCH 0
|
||||
#endif /* LV_BUILD_DEMOS */
|
||||
|
||||
#ifndef LV_USE_LZ4
|
||||
#if (LV_USE_LZ4_INTERNAL || LV_USE_LZ4_EXTERNAL)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# generate the cmake variables
|
||||
#
|
||||
# Author: David TRUAN (david.truan@edgemtech.ch)
|
||||
# Author: Erik Tagirov (erik.tagirov@edgemtech.ch)
|
||||
#
|
||||
|
||||
import sys
|
||||
@@ -13,6 +14,8 @@ import subprocess
|
||||
import os
|
||||
import argparse
|
||||
import re
|
||||
import importlib.util
|
||||
|
||||
|
||||
def get_args():
|
||||
parser = argparse.ArgumentParser(description="Preprocess a C header file and remove indentation.")
|
||||
@@ -57,13 +60,23 @@ def preprocess_file(pcpp_exe, input_file, tmp_file, output_file, include_dirs, d
|
||||
exit(1)
|
||||
|
||||
|
||||
def remove_indentation(tmp_file, output_file):
|
||||
# Read the temporary files and return an array of lines
|
||||
def read_lines(tmp_file):
|
||||
|
||||
try:
|
||||
with open(tmp_file, "r") as f:
|
||||
lines = f.readlines()
|
||||
except Exception as e:
|
||||
print(f"Failed to pre-process file: {e}")
|
||||
exit(1)
|
||||
|
||||
clean_lines = []
|
||||
return lines
|
||||
|
||||
def remove_indentation(lines):
|
||||
|
||||
clean_lines = []
|
||||
|
||||
try:
|
||||
for line in lines:
|
||||
stripped = line.lstrip()
|
||||
|
||||
@@ -73,39 +86,68 @@ def remove_indentation(tmp_file, output_file):
|
||||
|
||||
clean_lines.append(stripped)
|
||||
|
||||
with open(output_file, "w") as f:
|
||||
f.writelines(clean_lines)
|
||||
|
||||
print(f"Indentation removed. Cleaned output saved to {output_file}")
|
||||
|
||||
os.remove(tmp_file)
|
||||
print(f"Temporary preprocessed file {tmp_file} removed.")
|
||||
except Exception as e:
|
||||
print(f"Error during indentation removal: {e}")
|
||||
exit(1)
|
||||
|
||||
def install_pcpp_in_venv(workfolder:str) -> str:
|
||||
return clean_lines
|
||||
|
||||
# This is required - to avoid include errors when Kconfig is used and
|
||||
# LVGL is installed on the system - i.e when lvgl.h is used as a system include
|
||||
def add_include_guards(lines):
|
||||
|
||||
lines.insert(0, "#define LV_CONF_H\n\n")
|
||||
lines.insert(0, "#ifndef LV_CONF_H\n")
|
||||
lines.append("#endif /* END LV_CONF_H */\n")
|
||||
return lines
|
||||
|
||||
def init_venv(venv_path):
|
||||
"""
|
||||
Creates a virtual env named .venv inside `workfolder`
|
||||
and installs every dependecy inside `dependencies`
|
||||
Returns the path to pcpp
|
||||
Creates a virtual env named .venv in the `workfolder` directory
|
||||
It is usually set to the path of the build directory.
|
||||
If the .venv already exists it enters the venv
|
||||
Returns the path to the venv
|
||||
"""
|
||||
venv_path = os.path.join(workfolder, ".venv")
|
||||
try:
|
||||
if os.path.exists(venv_path) == False:
|
||||
# Create venv
|
||||
subprocess.check_call([sys.executable, "-m", "venv", venv_path])
|
||||
|
||||
# Enter venv
|
||||
venv_path = os.path.join(venv_path, ".venv")
|
||||
subprocess.check_call([sys.executable, "-m", "venv", venv_path])
|
||||
|
||||
if sys.platform == "win32":
|
||||
venv_pip = os.path.join(venv_path, "Scripts", "pip.exe")
|
||||
venv_pcpp = os.path.join(venv_path, "Scripts", "pcpp.exe")
|
||||
else:
|
||||
venv_pip = os.path.join(venv_path, "bin", "pip")
|
||||
venv_pcpp = os.path.join(venv_path, "bin", "pcpp")
|
||||
|
||||
subprocess.check_call([venv_pip, "install", "pcpp"])
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error setting up environnement: {e}")
|
||||
sys.exit(1)
|
||||
print(f"Error during the setup of python venv: {e}")
|
||||
exit(1)
|
||||
|
||||
return venv_path
|
||||
|
||||
def install_pcpp_in_venv(venv_path):
|
||||
"""
|
||||
Install pcpp a python implementation of the C pre-processor
|
||||
On success - Returns the path to pcpp, None on failure
|
||||
"""
|
||||
|
||||
if sys.platform == "win32":
|
||||
venv_pip = os.path.join(venv_path, "Scripts", "pip.exe")
|
||||
venv_pcpp = os.path.join(venv_path, "Scripts", "pcpp.exe")
|
||||
else:
|
||||
venv_pip = os.path.join(venv_path, "bin", "pip")
|
||||
venv_pcpp = os.path.join(venv_path, "bin", "pcpp")
|
||||
|
||||
if os.path.exists(venv_pcpp) == False:
|
||||
# Install pcpp
|
||||
try:
|
||||
subprocess.check_call([venv_pip, "install", "pcpp"])
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Failed to install PCPP: {e}")
|
||||
return None
|
||||
else:
|
||||
print("PCPP is already installed in venv")
|
||||
|
||||
|
||||
return venv_pcpp
|
||||
|
||||
@@ -113,10 +155,38 @@ def main():
|
||||
|
||||
args = get_args()
|
||||
|
||||
pcpp_exe = install_pcpp_in_venv(args.workfolder)
|
||||
# Check if PCPP is already present on the system
|
||||
# if it's not - create a python venv inside the workfolder directory
|
||||
# and install it there
|
||||
res = subprocess.run(["which", "pcpp"], capture_output=True)
|
||||
if res.returncode == 0:
|
||||
pcpp_exe = res.stdout.decode().replace("\n", "")
|
||||
print(f"Found PCPP: {pcpp_exe}")
|
||||
else:
|
||||
print("Failed to locate pcpp - installing it")
|
||||
venv_path = init_venv(args.workfolder)
|
||||
pcpp_exe = install_pcpp_in_venv(venv_path)
|
||||
if pcpp_exe is None:
|
||||
exit(1)
|
||||
|
||||
preprocess_file(pcpp_exe, args.input, args.tmp_file, args.output, args.include, args.defs)
|
||||
|
||||
remove_indentation(args.tmp_file, args.output)
|
||||
lines = read_lines(args.tmp_file)
|
||||
lines = remove_indentation(lines)
|
||||
lines = add_include_guards(lines)
|
||||
|
||||
# Write the resulting output header file with include guards and no indentation
|
||||
try:
|
||||
with open(args.output, "w") as f:
|
||||
f.writelines(lines)
|
||||
except Exception as e:
|
||||
print(f"Writing resulting file failed: {e}")
|
||||
exit(1)
|
||||
|
||||
print(f"Expanded configuration header saved to {args.output}")
|
||||
|
||||
os.remove(args.tmp_file)
|
||||
print(f"Temporary preprocessed file {args.tmp_file} removed.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user