extapps.scons 4.0 KB

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