extapps.scons 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from dataclasses import dataclass, field
  2. from fbt.appmanifest import FlipperAppType
  3. from SCons.Node import NodeList
  4. from SCons.Warnings import warn, WarningOnByDefault
  5. Import("ENV")
  6. appenv = ENV["APPENV"] = ENV.Clone(
  7. tools=[
  8. "fbt_extapps",
  9. "fbt_assets",
  10. "fbt_sdk",
  11. ],
  12. RESOURCES_ROOT=ENV.Dir("#/assets/resources"),
  13. )
  14. appenv.Replace(
  15. LINKER_SCRIPT_PATH=appenv["APP_LINKER_SCRIPT_PATH"],
  16. )
  17. appenv.AppendUnique(
  18. CCFLAGS=[
  19. "-ggdb3",
  20. "-mword-relocations",
  21. "-mlong-calls",
  22. "-fno-common",
  23. "-nostdlib",
  24. "-fvisibility=hidden",
  25. ],
  26. LINKFLAGS=[
  27. "-Ur",
  28. "-Wl,-Ur",
  29. # "-Wl,--orphan-handling=error",
  30. "-Bsymbolic",
  31. "-nostartfiles",
  32. "-mlong-calls",
  33. "-fno-common",
  34. "-nostdlib",
  35. "-Wl,--gc-sections",
  36. "-Wl,--no-export-dynamic",
  37. "-fvisibility=hidden",
  38. "-Wl,-e${APP_ENTRY}",
  39. "-Xlinker",
  40. "-Map=${TARGET}.map",
  41. "-specs=nano.specs",
  42. "-specs=nosys.specs",
  43. ],
  44. LIBS=[
  45. "m",
  46. "gcc",
  47. "stdc++",
  48. "supc++",
  49. ],
  50. )
  51. @dataclass
  52. class FlipperExtAppBuildArtifacts:
  53. application_map: dict = field(default_factory=dict)
  54. resources_dist: NodeList = field(default_factory=NodeList)
  55. sdk_tree: NodeList = field(default_factory=NodeList)
  56. apps_to_build_as_faps = [
  57. FlipperAppType.PLUGIN,
  58. FlipperAppType.EXTERNAL,
  59. FlipperAppType.DEBUG,
  60. ]
  61. known_extapps = [
  62. app
  63. for apptype in apps_to_build_as_faps
  64. for app in appenv["APPBUILD"].get_apps_of_type(apptype, True)
  65. ]
  66. # Ugly access to global option
  67. if extra_app_list := GetOption("extra_ext_apps"):
  68. known_extapps.extend(map(appenv["APPMGR"].get, extra_app_list.split(",")))
  69. incompatible_apps = []
  70. for app in known_extapps:
  71. if not app.supports_hardware_target(appenv.subst("f${TARGET_HW}")):
  72. incompatible_apps.append(app)
  73. continue
  74. appenv.BuildAppElf(app)
  75. extapps = FlipperExtAppBuildArtifacts()
  76. extapps.application_map = appenv["EXT_APPS"]
  77. if incompatible_apps:
  78. warn(
  79. WarningOnByDefault,
  80. f"Skipping build of {len(incompatible_apps)} incompatible app(s): "
  81. + ", ".join(f"'{app.name}' (id '{app.appid}')" for app in incompatible_apps),
  82. )
  83. if appenv["FORCE"]:
  84. appenv.AlwaysBuild(
  85. list(app_artifact.compact for app_artifact in extapps.application_map.values())
  86. )
  87. Alias(
  88. "faps",
  89. list(app_artifact.validator for app_artifact in extapps.application_map.values()),
  90. )
  91. extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], [])
  92. if appsrc := appenv.subst("$APPSRC"):
  93. appenv.AddAppLaunchTarget(appsrc, "launch_app")
  94. # SDK management
  95. amalgamated_api = "${BUILD_DIR}/sdk_origin"
  96. sdk_source = appenv.ApiAmalgamator(
  97. amalgamated_api,
  98. # Deps on root SDK headers and generated files
  99. (appenv["SDK_HEADERS"], appenv["FW_ASSETS_HEADERS"]),
  100. )
  101. # Extra deps on headers included in deeper levels
  102. # Available on second and subsequent builds
  103. Depends(sdk_source, appenv.ProcessSdkDepends(f"{amalgamated_api}.d"))
  104. appenv["SDK_DIR"] = appenv.Dir("${BUILD_DIR}/sdk_headers")
  105. sdk_header_tree = appenv.SDKHeaderTreeExtractor(appenv["SDK_DIR"], amalgamated_api)
  106. Depends(sdk_header_tree, appenv["SDK_DEFINITION"])
  107. # AlwaysBuild(sdk_tree)
  108. Alias("sdk_tree", sdk_header_tree)
  109. extapps.sdk_tree = sdk_header_tree
  110. api_check = appenv.ApiTableValidator(appenv["SDK_DEFINITION"], amalgamated_api)
  111. Precious(api_check)
  112. NoClean(api_check)
  113. AlwaysBuild(api_check)
  114. Alias("api_check", api_check)
  115. firmware_apitable = appenv.ApiSymbolTable(
  116. "${BUILD_DIR}/assets/compiled/firmware_api_table.h", appenv["SDK_DEFINITION"]
  117. )
  118. Alias("api_table", firmware_apitable)
  119. ENV.Replace(
  120. FW_API_TABLE=firmware_apitable,
  121. _APP_ICONS=appenv["_APP_ICONS"],
  122. )
  123. if appenv["FORCE"]:
  124. appenv.AlwaysBuild(sdk_source, sdk_header_tree, api_check, firmware_apitable)
  125. Return("extapps")