fbt_apps.py 2.6 KB

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