fbt_assets.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import SCons
  2. from SCons.Builder import Builder
  3. from SCons.Action import Action
  4. from SCons.Node.FS import File
  5. import os
  6. import subprocess
  7. def icons_emitter(target, source, env):
  8. target = [
  9. target[0].File(env.subst("${ICON_FILE_NAME}.c")),
  10. target[0].File(env.subst("${ICON_FILE_NAME}.h")),
  11. ]
  12. source = env.GlobRecursive("*.*", env["ICON_SRC_DIR"])
  13. return target, source
  14. def proto_emitter(target, source, env):
  15. target = []
  16. for src in source:
  17. basename = os.path.splitext(src.name)[0]
  18. target.append(env.File(f"compiled/{basename}.pb.c"))
  19. target.append(env.File(f"compiled/{basename}.pb.h"))
  20. return target, source
  21. def dolphin_emitter(target, source, env):
  22. res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"])
  23. source = [res_root_dir]
  24. source.extend(
  25. env.GlobRecursive("*.*", res_root_dir),
  26. )
  27. target_base_dir = target[0]
  28. env.Replace(_DOLPHIN_OUT_DIR=target[0])
  29. if env["DOLPHIN_RES_TYPE"] == "external":
  30. target = []
  31. target.extend(
  32. map(
  33. lambda node: target_base_dir.File(
  34. res_root_dir.rel_path(node).replace(".png", ".bm")
  35. ),
  36. filter(lambda node: isinstance(node, SCons.Node.FS.File), source),
  37. )
  38. )
  39. else:
  40. asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}"
  41. target = [
  42. target_base_dir.File(asset_basename + ".c"),
  43. target_base_dir.File(asset_basename + ".h"),
  44. ]
  45. return target, source
  46. def _invoke_git(args, source_dir):
  47. cmd = ["git"]
  48. cmd.extend(args)
  49. return (
  50. subprocess.check_output(cmd, cwd=source_dir, stderr=subprocess.STDOUT)
  51. .strip()
  52. .decode()
  53. )
  54. def proto_ver_generator(target, source, env):
  55. target_file = target[0]
  56. src_dir = source[0].dir.abspath
  57. try:
  58. git_fetch = _invoke_git(
  59. ["fetch", "--tags"],
  60. source_dir=src_dir,
  61. )
  62. except (subprocess.CalledProcessError, EnvironmentError) as e:
  63. # Not great, not terrible
  64. print("Git: fetch failed")
  65. try:
  66. git_describe = _invoke_git(
  67. ["describe", "--tags", "--abbrev=0"],
  68. source_dir=src_dir,
  69. )
  70. except (subprocess.CalledProcessError, EnvironmentError) as e:
  71. print("Git: describe failed")
  72. Exit("git error")
  73. # print("describe=", git_describe)
  74. git_major, git_minor = git_describe.split(".")
  75. version_file_data = (
  76. "#pragma once",
  77. f"#define PROTOBUF_MAJOR_VERSION {git_major}",
  78. f"#define PROTOBUF_MINOR_VERSION {git_minor}",
  79. "",
  80. )
  81. with open(str(target_file), "wt") as file:
  82. file.write("\n".join(version_file_data))
  83. def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"):
  84. # Gathering icons sources
  85. icons_src = env.GlobRecursive("*.png", source_dir)
  86. icons_src += env.GlobRecursive("frame_rate", source_dir)
  87. icons = env.IconBuilder(
  88. target_dir,
  89. ICON_SRC_DIR=source_dir,
  90. ICON_FILE_NAME=icon_bundle_name,
  91. )
  92. env.Depends(icons, icons_src)
  93. return icons
  94. def generate(env):
  95. env.SetDefault(
  96. ASSETS_COMPILER="${ROOT_DIR.abspath}/scripts/assets.py",
  97. NANOPB_COMPILER="${ROOT_DIR.abspath}/lib/nanopb/generator/nanopb_generator.py",
  98. )
  99. env.AddMethod(CompileIcons)
  100. if not env["VERBOSE"]:
  101. env.SetDefault(
  102. ICONSCOMSTR="\tICONS\t${TARGET}",
  103. PROTOCOMSTR="\tPROTO\t${SOURCE}",
  104. DOLPHINCOMSTR="\tDOLPHIN\t${DOLPHIN_RES_TYPE}",
  105. RESMANIFESTCOMSTR="\tMANIFEST\t${TARGET}",
  106. PBVERCOMSTR="\tPBVER\t${TARGET}",
  107. )
  108. env.Append(
  109. BUILDERS={
  110. "IconBuilder": Builder(
  111. action=Action(
  112. '${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir} --filename ${ICON_FILE_NAME}',
  113. "${ICONSCOMSTR}",
  114. ),
  115. emitter=icons_emitter,
  116. ),
  117. "ProtoBuilder": Builder(
  118. action=Action(
  119. '${PYTHON3} "${NANOPB_COMPILER}" -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}',
  120. "${PROTOCOMSTR}",
  121. ),
  122. emitter=proto_emitter,
  123. suffix=".pb.c",
  124. src_suffix=".proto",
  125. ),
  126. "DolphinSymBuilder": Builder(
  127. action=Action(
  128. '${PYTHON3} "${ASSETS_COMPILER}" dolphin -s dolphin_${DOLPHIN_RES_TYPE} "${SOURCE}" "${_DOLPHIN_OUT_DIR}"',
  129. "${DOLPHINCOMSTR}",
  130. ),
  131. emitter=dolphin_emitter,
  132. ),
  133. "DolphinExtBuilder": Builder(
  134. action=Action(
  135. '${PYTHON3} "${ASSETS_COMPILER}" dolphin "${SOURCE}" "${_DOLPHIN_OUT_DIR}"',
  136. "${DOLPHINCOMSTR}",
  137. ),
  138. emitter=dolphin_emitter,
  139. ),
  140. "ProtoVerBuilder": Builder(
  141. action=Action(
  142. proto_ver_generator,
  143. "${PBVERCOMSTR}",
  144. ),
  145. ),
  146. }
  147. )
  148. def exists(env):
  149. return True