extapps.scons 3.9 KB

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