extapps.scons 3.9 KB

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