diff --git a/.claude/rules/key-conventions.md b/.claude/rules/key-conventions.md index e75121ade..96d9837ae 100644 --- a/.claude/rules/key-conventions.md +++ b/.claude/rules/key-conventions.md @@ -6,5 +6,6 @@ - `Modules/` contains cross-cutting modules. e.g.`lvgl-module` (LVGL task management). - `Data/data/` is flashed as a FAT filesystem image on ESP32 devices that don't have an SD card. - `Data/system/` is embedded in the Tactility project as generated C byte arrays (`generated_assets.h`, see `Buildscripts/generate-assets.py`). + A device overrides a file by placing one at the same relative path in `Devices//system/` (e.g. `system/app/Boot/assets/logo.png`). - The binfont files of the default font size are generated at build time into `generated_fonts.h` (see `Buildscripts/generate-fonts.py`). - Translations are in `Translations/` as CSV files, generated via `generate.py`. diff --git a/Buildscripts/generate-assets.py b/Buildscripts/generate-assets.py index d282c7d29..8e5ba92c1 100644 --- a/Buildscripts/generate-assets.py +++ b/Buildscripts/generate-assets.py @@ -2,12 +2,14 @@ """ Embeds every file of an asset folder as a C byte array. -Usage: generate-assets.py +Usage: generate-assets.py [...] Writes generated_assets.h and generated_assets.c. A file "fonts/AdwaitaSans.ttf" becomes the symbols asset_fonts_AdwaitaSans_ttf (the bytes) and asset_fonts_AdwaitaSans_ttf_size (the byte count). The size is also available as the constant asset_fonts_AdwaitaSans_ttf_SIZE for use in constant initializers. Text files get an extra terminating 0 byte that is not part of the size, so they can be used as C strings. +A file in an overlay folder replaces the file with the same relative path in the asset folder. +Overlay folders that don't exist are skipped. Output files are only rewritten when their content changes, to avoid needless recompiles. """ import os @@ -31,18 +33,21 @@ def write_if_changed(path: str, content: str): def main(): - if len(sys.argv) != 3: - print(f"Usage: {sys.argv[0]} ") + if len(sys.argv) < 3: + print(f"Usage: {sys.argv[0]} [...]") sys.exit(1) - asset_folder = os.path.abspath(sys.argv[1]) + asset_folders = [os.path.abspath(sys.argv[1])] + [os.path.abspath(folder) for folder in sys.argv[3:]] output_folder = os.path.abspath(sys.argv[2]) os.makedirs(output_folder, exist_ok=True) - relative_paths = [] - for directory, _, file_names in os.walk(asset_folder): - for file_name in file_names: - relative_paths.append(os.path.relpath(os.path.join(directory, file_name), asset_folder).replace(os.sep, "/")) - relative_paths.sort() + # Maps each relative path to the folder that provides it: later folders win + asset_paths = {} + for asset_folder in asset_folders: + for directory, _, file_names in os.walk(asset_folder): + for file_name in file_names: + relative_path = os.path.relpath(os.path.join(directory, file_name), asset_folder).replace(os.sep, "/") + asset_paths[relative_path] = asset_folder + relative_paths = sorted(asset_paths) header = [ "// Generated by Buildscripts/generate-assets.py. Do not edit.", @@ -62,7 +67,7 @@ def main(): "", ] for relative_path in relative_paths: - with open(os.path.join(asset_folder, relative_path), "rb") as file: + with open(os.path.join(asset_paths[relative_path], relative_path), "rb") as file: data = file.read() symbol = symbol_name(relative_path) size = len(data) diff --git a/Tactility/CMakeLists.txt b/Tactility/CMakeLists.txt index 23d2a221b..99b18c319 100644 --- a/Tactility/CMakeLists.txt +++ b/Tactility/CMakeLists.txt @@ -224,10 +224,10 @@ add_dependencies(${COMPONENT_LIB} Generated) # # Rewrites its outputs only when the content changes. The assets are the whole Data/system tree, -# so no fixed DEPENDS list is kept. +# so no fixed DEPENDS list is kept. Files in the device's system/ folder replace the ones with the same path. add_custom_target(GeneratedAssets ALL COMMAND python "${CMAKE_SOURCE_DIR}/Buildscripts/generate-assets.py" - "${CMAKE_SOURCE_DIR}/Data/system" "${GENERATED_DIR}" + "${CMAKE_SOURCE_DIR}/Data/system" "${GENERATED_DIR}" "${DEVICETREE_LOCATION}/system" BYPRODUCTS "${GENERATED_DIR}/generated_assets.c" "${GENERATED_DIR}/generated_assets.h" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" COMMENT "Generating asset source files..."