[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
This commit is contained in:
hedger 2023-10-31 15:27:58 +04:00 committed by GitHub
parent 9af81ce8d0
commit bbe68d6ffc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 56 deletions

View File

@ -148,15 +148,11 @@ if env["IS_BASE_FIRMWARE"]:
) )
fw_artifacts.append(fw_extapps.sdk_tree) fw_artifacts.append(fw_extapps.sdk_tree)
# Resources for SD card # Resources & manifest for SD card
resources = fwenv.ResourcesDist(
_EXTRA_DIST=[fwenv["DOLPHIN_EXTERNAL_OUT_DIR"]],
)
manifest = fwenv.ManifestBuilder( manifest = fwenv.ManifestBuilder(
"${RESOURCES_ROOT}/Manifest", "${RESOURCES_ROOT}/Manifest",
source=resources,
GIT_UNIX_TIMESTAMP=get_git_commit_unix_timestamp(), GIT_UNIX_TIMESTAMP=get_git_commit_unix_timestamp(),
_EXTRA_DIST=[fwenv["DOLPHIN_EXTERNAL_OUT_DIR"]],
) )
fwenv.Replace(FW_RESOURCES_MANIFEST=manifest) fwenv.Replace(FW_RESOURCES_MANIFEST=manifest)
fwenv.Alias("resources", manifest) fwenv.Alias("resources", manifest)

View File

@ -66,7 +66,8 @@ PluginManagerError plugin_manager_load_single(PluginManager* manager, const char
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(lib); FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(lib);
if(load_status != FlipperApplicationLoadStatusSuccess) { 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; break;
} }

View File

@ -30,24 +30,26 @@ def _proto_emitter(target, source, env):
def _dolphin_emitter(target, source, env): def _dolphin_emitter(target, source, env):
res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"]) res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"])
source = [res_root_dir] source = list()
source.extend(env.GlobRecursive("*.*", res_root_dir.srcnode())) source.extend(env.GlobRecursive("*.*", res_root_dir.srcnode()))
target_base_dir = target[0] target_base_dir = target[0]
env.Replace(_DOLPHIN_OUT_DIR=target[0]) env.Replace(_DOLPHIN_OUT_DIR=target[0])
env.Replace(_DOLPHIN_SRC_DIR=res_root_dir)
if env["DOLPHIN_RES_TYPE"] == "external": if env["DOLPHIN_RES_TYPE"] == "external":
target = [target_base_dir.File("manifest.txt")] target = [target_base_dir.File("manifest.txt")]
## A detailed list of files to be generated ## 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 # Preserve original paths, do .png -> .bm conversion
target.extend( # target.extend(
map( # map(
lambda node: target_base_dir.File( # lambda node: target_base_dir.File(
res_root_dir.rel_path(node).replace(".png", ".bm") # res_root_dir.rel_path(node).replace(".png", ".bm")
), # ),
filter(lambda node: isinstance(node, File), source), # filter(lambda node: isinstance(node, File), source),
) # )
) # )
else: else:
asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}" asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}"
target = [ target = [
@ -55,7 +57,7 @@ def _dolphin_emitter(target, source, env):
target_base_dir.File(asset_basename + ".h"), target_base_dir.File(asset_basename + ".h"),
] ]
# Debug output ## Debug output
# print( # print(
# f"Dolphin res type: {env['DOLPHIN_RES_TYPE']},\ntarget files:", # f"Dolphin res type: {env['DOLPHIN_RES_TYPE']},\ntarget files:",
# list(f.path for f in target), # list(f.path for f in target),
@ -176,7 +178,7 @@ def generate(env):
"dolphin", "dolphin",
"-s", "-s",
"dolphin_${DOLPHIN_RES_TYPE}", "dolphin_${DOLPHIN_RES_TYPE}",
"${SOURCE}", "${_DOLPHIN_SRC_DIR}",
"${_DOLPHIN_OUT_DIR}", "${_DOLPHIN_OUT_DIR}",
], ],
], ],
@ -191,7 +193,7 @@ def generate(env):
"${PYTHON3}", "${PYTHON3}",
"${ASSETS_COMPILER}", "${ASSETS_COMPILER}",
"dolphin", "dolphin",
"${SOURCE}", "${_DOLPHIN_SRC_DIR}",
"${_DOLPHIN_OUT_DIR}", "${_DOLPHIN_OUT_DIR}",
], ],
], ],

View File

@ -7,16 +7,21 @@ from SCons.Errors import StopError
from SCons.Node.FS import Dir, File 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"]) resources_root = env.Dir(env["RESOURCES_ROOT"])
target = []
for app_artifacts in env["FW_EXTAPPS"].application_map.values(): for app_artifacts in env["FW_EXTAPPS"].application_map.values():
for _, dist_path in filter( for _, dist_path in filter(
lambda dist_entry: dist_entry[0], app_artifacts.dist_entries lambda dist_entry: dist_entry[0], app_artifacts.dist_entries
): ):
source.append(app_artifacts.compact) src_target_entries.append(
target.append(resources_root.File(dist_path)) (
app_artifacts.compact,
resources_root.File(dist_path),
)
)
# Deploy apps' resources too # Deploy apps' resources too
for app in env["APPBUILD"].apps: 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): for res_file in env.GlobRecursive("*", apps_resource_dir):
if not isinstance(res_file, File): if not isinstance(res_file, File):
continue continue
source.append(res_file) src_target_entries.append(
target.append(resources_root.File(res_file.get_path(apps_resource_dir))) (
res_file,
resources_root.File(
res_file.get_path(apps_resource_dir),
),
)
)
# Deploy other stuff from _EXTRA_DIST # Deploy other stuff from _EXTRA_DIST
for extra_dist in env["_EXTRA_DIST"]: for extra_dist in env["_EXTRA_DIST"]:
if isinstance(extra_dist, Dir): if isinstance(extra_dist, Dir):
for extra_file in env.GlobRecursive("*", extra_dist): src_target_entries.append(
if not isinstance(extra_file, File): (
continue extra_dist,
source.append(extra_file) resources_root.Dir(extra_dist.name),
target.append(
# Preserve dir name from original node
resources_root.Dir(extra_dist.name).File(
extra_file.get_path(extra_dist)
)
) )
)
else: else:
raise StopError(f"Unsupported extra dist type: {type(extra_dist)}") 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) return (target, source)
def _resources_dist_action(target, source, env): 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) shutil.rmtree(env.Dir(env["RESOURCES_ROOT"]).abspath, ignore_errors=True)
for src, target in zip(source, target): for src, target in dist_entries:
os.makedirs(os.path.dirname(target.path), exist_ok=True) if isinstance(src, File):
shutil.copy(src.path, target.path) 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): def generate(env, **kw):
@ -69,26 +88,26 @@ def generate(env, **kw):
env.Append( env.Append(
BUILDERS={ BUILDERS={
"ResourcesDist": Builder(
action=Action(
_resources_dist_action,
"${RESOURCEDISTCOMSTR}",
),
emitter=_resources_dist_emitter,
),
"ManifestBuilder": Builder( "ManifestBuilder": Builder(
action=Action( action=[
[ Action(
_resources_dist_action,
"${RESOURCEDISTCOMSTR}",
),
Action(
[ [
"${PYTHON3}", [
"${ASSETS_COMPILER}", "${PYTHON3}",
"manifest", "${ASSETS_COMPILER}",
"${TARGET.dir.posix}", "manifest",
"--timestamp=${GIT_UNIX_TIMESTAMP}", "${TARGET.dir.posix}",
] "--timestamp=${GIT_UNIX_TIMESTAMP}",
], ]
"${RESMANIFESTCOMSTR}", ],
) "${RESMANIFESTCOMSTR}",
),
],
emitter=_resources_dist_emitter,
), ),
} }
) )