from SCons.Errors import UserError Import("ENV") from fbt.appmanifest import FlipperAppType appenv = ENV["APPENV"] = ENV.Clone( tools=[ ( "fbt_extapps", { "EXT_APPS_WORK_DIR": ENV.subst( "${BUILD_DIR}/.extapps", ) }, ), "fbt_assets", "fbt_sdk", ] ) appenv.Replace( LINKER_SCRIPT=appenv.subst("$APP_LINKER_SCRIPT"), ) appenv.AppendUnique( CCFLAGS=[ "-ggdb3", "-mword-relocations", "-mlong-calls", "-fno-common", "-nostdlib", "-fvisibility=hidden", ], LINKFLAGS=[ "-Ur", "-Wl,-Ur", # "-Wl,--orphan-handling=error", "-Bsymbolic", "-nostartfiles", "-mlong-calls", "-fno-common", "-nostdlib", "-Wl,--gc-sections", "-Wl,--no-export-dynamic", "-fvisibility=hidden", "-Wl,-e${APP_ENTRY}", "-Xlinker", "-Map=${TARGET}.map", "-specs=nano.specs", "-specs=nosys.specs", ], LIBS=[ "m", "gcc", "stdc++", "supc++", ], ) extapps = appenv["_extapps"] = { "compact": {}, "debug": {}, "validators": {}, "dist": {}, "resources_dist": None, "sdk_tree": None, } def build_app_as_external(env, appdef): compact_elf, debug_elf, validator = env.BuildAppElf(appdef) extapps["compact"][appdef.appid] = compact_elf extapps["debug"][appdef.appid] = debug_elf extapps["validators"][appdef.appid] = validator extapps["dist"][appdef.appid] = (appdef.fap_category, compact_elf) apps_to_build_as_faps = [ FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL, ] if appenv["DEBUG_TOOLS"]: apps_to_build_as_faps.append(FlipperAppType.DEBUG) for apptype in apps_to_build_as_faps: for app in appenv["APPBUILD"].get_apps_of_type(apptype, True): build_app_as_external(appenv, app) # Ugly access to global option if extra_app_list := GetOption("extra_ext_apps"): for extra_app in extra_app_list.split(","): build_app_as_external(appenv, appenv["APPMGR"].get(extra_app)) if appenv["FORCE"]: appenv.AlwaysBuild(extapps["compact"].values()) # Deprecation stub def legacy_app_build_stub(**kw): raise UserError(f"Target name 'firmware_extapps' is deprecated, use 'faps' instead") appenv.PhonyTarget("firmware_extapps", appenv.Action(legacy_app_build_stub, None)) Alias("faps", extapps["compact"].values()) Alias("faps", extapps["validators"].values()) extapps["resources_dist"] = appenv.FapDist(appenv.Dir("#/assets/resources/apps"), []) if appsrc := appenv.subst("$APPSRC"): app_manifest, fap_file, app_validator = appenv.GetExtAppFromPath(appsrc) appenv.PhonyTarget( "launch_app", '${PYTHON3} "${APP_RUN_SCRIPT}" ${SOURCE} --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"', source=fap_file, FAP_CATEGORY=app_manifest.fap_category, ) appenv.Alias("launch_app", app_validator) # SDK management sdk_origin_path = "${BUILD_DIR}/sdk_origin" sdk_source = appenv.SDKPrebuilder( sdk_origin_path, # Deps on root SDK headers and generated files (appenv["SDK_HEADERS"], appenv["FW_ASSETS_HEADERS"]), ) # Extra deps on headers included in deeper levels Depends(sdk_source, appenv.ProcessSdkDepends(f"{sdk_origin_path}.d")) appenv["SDK_DIR"] = appenv.Dir("${BUILD_DIR}/sdk") sdk_tree = extapps["sdk_tree"] = appenv.SDKTree(appenv["SDK_DIR"], sdk_origin_path) # AlwaysBuild(sdk_tree) Alias("sdk_tree", sdk_tree) sdk_apicheck = appenv.SDKSymUpdater(appenv["SDK_DEFINITION"], sdk_origin_path) Precious(sdk_apicheck) NoClean(sdk_apicheck) AlwaysBuild(sdk_apicheck) Alias("sdk_check", sdk_apicheck) sdk_apisyms = appenv.SDKSymGenerator( "${BUILD_DIR}/assets/compiled/symbols.h", appenv["SDK_DEFINITION"] ) Alias("api_syms", sdk_apisyms) if appenv["FORCE"]: appenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms) Return("extapps")