From bbe68d6ffc10998a364118abace7ca44ecf6ace7 Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 31 Oct 2023 15:27:58 +0400 Subject: [PATCH] [FL-3629] fbt: SD card resource handling speedup (#3178) * fbt: reduced size of resources dependency graphs, resulting in faster build task evaluation * lib: flipper_app: fixed error message & error handling for plugins --- firmware.scons | 8 +- .../plugins/plugin_manager.c | 3 +- scripts/fbt_tools/fbt_assets.py | 26 +++--- scripts/fbt_tools/fbt_resources.py | 93 +++++++++++-------- 4 files changed, 74 insertions(+), 56 deletions(-) diff --git a/firmware.scons b/firmware.scons index e8e50022..53777425 100644 --- a/firmware.scons +++ b/firmware.scons @@ -148,15 +148,11 @@ if env["IS_BASE_FIRMWARE"]: ) fw_artifacts.append(fw_extapps.sdk_tree) - # Resources for SD card - resources = fwenv.ResourcesDist( - _EXTRA_DIST=[fwenv["DOLPHIN_EXTERNAL_OUT_DIR"]], - ) - + # Resources & manifest for SD card manifest = fwenv.ManifestBuilder( "${RESOURCES_ROOT}/Manifest", - source=resources, GIT_UNIX_TIMESTAMP=get_git_commit_unix_timestamp(), + _EXTRA_DIST=[fwenv["DOLPHIN_EXTERNAL_OUT_DIR"]], ) fwenv.Replace(FW_RESOURCES_MANIFEST=manifest) fwenv.Alias("resources", manifest) diff --git a/lib/flipper_application/plugins/plugin_manager.c b/lib/flipper_application/plugins/plugin_manager.c index e2a7b83f..8f30ed13 100644 --- a/lib/flipper_application/plugins/plugin_manager.c +++ b/lib/flipper_application/plugins/plugin_manager.c @@ -66,7 +66,8 @@ PluginManagerError plugin_manager_load_single(PluginManager* manager, const char FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(lib); if(load_status != FlipperApplicationLoadStatusSuccess) { - FURI_LOG_E(TAG, "Failed to load module_demo_plugin1.fal"); + FURI_LOG_E(TAG, "Failed to load %s", path); + error = PluginManagerErrorLoaderError; break; } diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index dcf391f2..5c32ae1a 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -30,24 +30,26 @@ def _proto_emitter(target, source, env): def _dolphin_emitter(target, source, env): res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"]) - source = [res_root_dir] + source = list() source.extend(env.GlobRecursive("*.*", res_root_dir.srcnode())) target_base_dir = target[0] env.Replace(_DOLPHIN_OUT_DIR=target[0]) + env.Replace(_DOLPHIN_SRC_DIR=res_root_dir) if env["DOLPHIN_RES_TYPE"] == "external": target = [target_base_dir.File("manifest.txt")] ## A detailed list of files to be generated + # Not used ATM, becasuse it inflates the internal dependency graph too much # Preserve original paths, do .png -> .bm conversion - target.extend( - map( - lambda node: target_base_dir.File( - res_root_dir.rel_path(node).replace(".png", ".bm") - ), - filter(lambda node: isinstance(node, File), source), - ) - ) + # target.extend( + # map( + # lambda node: target_base_dir.File( + # res_root_dir.rel_path(node).replace(".png", ".bm") + # ), + # filter(lambda node: isinstance(node, File), source), + # ) + # ) else: asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}" target = [ @@ -55,7 +57,7 @@ def _dolphin_emitter(target, source, env): target_base_dir.File(asset_basename + ".h"), ] - # Debug output + ## Debug output # print( # f"Dolphin res type: {env['DOLPHIN_RES_TYPE']},\ntarget files:", # list(f.path for f in target), @@ -176,7 +178,7 @@ def generate(env): "dolphin", "-s", "dolphin_${DOLPHIN_RES_TYPE}", - "${SOURCE}", + "${_DOLPHIN_SRC_DIR}", "${_DOLPHIN_OUT_DIR}", ], ], @@ -191,7 +193,7 @@ def generate(env): "${PYTHON3}", "${ASSETS_COMPILER}", "dolphin", - "${SOURCE}", + "${_DOLPHIN_SRC_DIR}", "${_DOLPHIN_OUT_DIR}", ], ], diff --git a/scripts/fbt_tools/fbt_resources.py b/scripts/fbt_tools/fbt_resources.py index 47c62408..4c3146ba 100644 --- a/scripts/fbt_tools/fbt_resources.py +++ b/scripts/fbt_tools/fbt_resources.py @@ -7,16 +7,21 @@ from SCons.Errors import StopError from SCons.Node.FS import Dir, File -def _resources_dist_emitter(target, source, env): +def __generate_resources_dist_entries(env): + src_target_entries = [] + resources_root = env.Dir(env["RESOURCES_ROOT"]) - target = [] for app_artifacts in env["FW_EXTAPPS"].application_map.values(): for _, dist_path in filter( lambda dist_entry: dist_entry[0], app_artifacts.dist_entries ): - source.append(app_artifacts.compact) - target.append(resources_root.File(dist_path)) + src_target_entries.append( + ( + app_artifacts.compact, + resources_root.File(dist_path), + ) + ) # Deploy apps' resources too for app in env["APPBUILD"].apps: @@ -26,34 +31,48 @@ def _resources_dist_emitter(target, source, env): for res_file in env.GlobRecursive("*", apps_resource_dir): if not isinstance(res_file, File): continue - source.append(res_file) - target.append(resources_root.File(res_file.get_path(apps_resource_dir))) + src_target_entries.append( + ( + res_file, + resources_root.File( + res_file.get_path(apps_resource_dir), + ), + ) + ) # Deploy other stuff from _EXTRA_DIST for extra_dist in env["_EXTRA_DIST"]: if isinstance(extra_dist, Dir): - for extra_file in env.GlobRecursive("*", extra_dist): - if not isinstance(extra_file, File): - continue - source.append(extra_file) - target.append( - # Preserve dir name from original node - resources_root.Dir(extra_dist.name).File( - extra_file.get_path(extra_dist) - ) + src_target_entries.append( + ( + extra_dist, + resources_root.Dir(extra_dist.name), ) + ) else: raise StopError(f"Unsupported extra dist type: {type(extra_dist)}") - assert len(target) == len(source) + return src_target_entries + + +def _resources_dist_emitter(target, source, env): + src_target_entries = __generate_resources_dist_entries(env) + source = list(map(lambda entry: entry[0], src_target_entries)) return (target, source) def _resources_dist_action(target, source, env): + dist_entries = __generate_resources_dist_entries(env) + assert len(dist_entries) == len(source) shutil.rmtree(env.Dir(env["RESOURCES_ROOT"]).abspath, ignore_errors=True) - for src, target in zip(source, target): - os.makedirs(os.path.dirname(target.path), exist_ok=True) - shutil.copy(src.path, target.path) + for src, target in dist_entries: + if isinstance(src, File): + os.makedirs(os.path.dirname(target.path), exist_ok=True) + shutil.copy(src.path, target.path) + elif isinstance(src, Dir): + shutil.copytree(src.path, target.path) + else: + raise StopError(f"Unsupported dist entry type: {type(src)}") def generate(env, **kw): @@ -69,26 +88,26 @@ def generate(env, **kw): env.Append( BUILDERS={ - "ResourcesDist": Builder( - action=Action( - _resources_dist_action, - "${RESOURCEDISTCOMSTR}", - ), - emitter=_resources_dist_emitter, - ), "ManifestBuilder": Builder( - action=Action( - [ + action=[ + Action( + _resources_dist_action, + "${RESOURCEDISTCOMSTR}", + ), + Action( [ - "${PYTHON3}", - "${ASSETS_COMPILER}", - "manifest", - "${TARGET.dir.posix}", - "--timestamp=${GIT_UNIX_TIMESTAMP}", - ] - ], - "${RESMANIFESTCOMSTR}", - ) + [ + "${PYTHON3}", + "${ASSETS_COMPILER}", + "manifest", + "${TARGET.dir.posix}", + "--timestamp=${GIT_UNIX_TIMESTAMP}", + ] + ], + "${RESMANIFESTCOMSTR}", + ), + ], + emitter=_resources_dist_emitter, ), } )