fbt_apps.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from ansi.color import fg
  2. from fbt.appmanifest import (
  3. ApplicationsCGenerator,
  4. AppManager,
  5. FlipperAppType,
  6. FlipperManifestException,
  7. )
  8. from SCons.Action import Action
  9. from SCons.Builder import Builder
  10. from SCons.Errors import StopError
  11. from SCons.Warnings import WarningOnByDefault, warn
  12. from SCons.Script import GetOption
  13. # Adding objects for application management to env
  14. # AppManager env["APPMGR"] - loads all manifests; manages list of known apps
  15. # AppBuildset env["APPBUILD"] - contains subset of apps, filtered for current config
  16. def LoadAppManifest(env, entry):
  17. try:
  18. APP_MANIFEST_NAME = "application.fam"
  19. manifest_glob = entry.glob(APP_MANIFEST_NAME)
  20. if len(manifest_glob) == 0:
  21. raise FlipperManifestException(
  22. f"Folder {entry}: manifest {APP_MANIFEST_NAME} is missing"
  23. )
  24. app_manifest_file_path = manifest_glob[0].rfile().abspath
  25. env["APPMGR"].load_manifest(app_manifest_file_path, entry)
  26. env.Append(PY_LINT_SOURCES=[app_manifest_file_path])
  27. except FlipperManifestException as e:
  28. if not GetOption("silent"):
  29. warn(WarningOnByDefault, str(e))
  30. def PrepareApplicationsBuild(env):
  31. try:
  32. appbuild = env["APPBUILD"] = env["APPMGR"].filter_apps(
  33. env["APPS"], env.subst("f${TARGET_HW}")
  34. )
  35. except Exception as e:
  36. raise StopError(e)
  37. env.Append(
  38. SDK_HEADERS=appbuild.get_sdk_headers(),
  39. )
  40. def DumpApplicationConfig(target, source, env):
  41. print(f"Loaded {len(env['APPMGR'].known_apps)} app definitions.")
  42. print(fg.boldgreen("Firmware modules configuration:"))
  43. for apptype in FlipperAppType:
  44. app_sublist = env["APPBUILD"].get_apps_of_type(apptype)
  45. if app_sublist:
  46. print(
  47. fg.green(f"{apptype.value}:\n\t"),
  48. ", ".join(app.appid for app in app_sublist),
  49. )
  50. def build_apps_c(target, source, env):
  51. target_file_name = target[0].path
  52. gen = ApplicationsCGenerator(env["APPBUILD"], env.subst("$LOADER_AUTOSTART"))
  53. with open(target_file_name, "w") as file:
  54. file.write(gen.generate())
  55. def generate(env):
  56. env.AddMethod(LoadAppManifest)
  57. env.AddMethod(PrepareApplicationsBuild)
  58. env.SetDefault(
  59. APPMGR=AppManager(),
  60. APPBUILD_DUMP=env.Action(
  61. DumpApplicationConfig,
  62. "\tINFO\t",
  63. ),
  64. )
  65. env.Append(
  66. BUILDERS={
  67. "ApplicationsC": Builder(
  68. action=Action(
  69. build_apps_c,
  70. "${APPSCOMSTR}",
  71. ),
  72. suffix=".c",
  73. ),
  74. }
  75. )
  76. def exists(env):
  77. return True