fbt_assets.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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.srcnode()),
  26. )
  27. target_base_dir = target[0]
  28. env.Replace(_DOLPHIN_OUT_DIR=target[0])
  29. if env["DOLPHIN_RES_TYPE"] == "external":
  30. target = [target_base_dir.File("manifest.txt")]
  31. ## A detailed list of files to be generated
  32. ## works better if we just leave target the folder
  33. # target = []
  34. # target.extend(
  35. # map(
  36. # lambda node: target_base_dir.File(
  37. # res_root_dir.rel_path(node).replace(".png", ".bm")
  38. # ),
  39. # filter(lambda node: isinstance(node, SCons.Node.FS.File), source),
  40. # )
  41. # )
  42. else:
  43. asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}"
  44. target = [
  45. target_base_dir.File(asset_basename + ".c"),
  46. target_base_dir.File(asset_basename + ".h"),
  47. ]
  48. # Debug output
  49. # print(
  50. # f"Dolphin res type: {env['DOLPHIN_RES_TYPE']},\ntarget files:",
  51. # list(f.path for f in target),
  52. # f"\nsource files:",
  53. # list(f.path for f in source),
  54. # )
  55. return target, source
  56. def _invoke_git(args, source_dir):
  57. cmd = ["git"]
  58. cmd.extend(args)
  59. return (
  60. subprocess.check_output(cmd, cwd=source_dir, stderr=subprocess.STDOUT)
  61. .strip()
  62. .decode()
  63. )
  64. def proto_ver_generator(target, source, env):
  65. target_file = target[0]
  66. src_dir = source[0].dir.abspath
  67. try:
  68. git_fetch = _invoke_git(
  69. ["fetch", "--tags"],
  70. source_dir=src_dir,
  71. )
  72. except (subprocess.CalledProcessError, EnvironmentError) as e:
  73. # Not great, not terrible
  74. print("Git: fetch failed")
  75. try:
  76. git_describe = _invoke_git(
  77. ["describe", "--tags", "--abbrev=0"],
  78. source_dir=src_dir,
  79. )
  80. except (subprocess.CalledProcessError, EnvironmentError) as e:
  81. print("Git: describe failed")
  82. Exit("git error")
  83. # print("describe=", git_describe)
  84. git_major, git_minor = git_describe.split(".")
  85. version_file_data = (
  86. "#pragma once",
  87. f"#define PROTOBUF_MAJOR_VERSION {git_major}",
  88. f"#define PROTOBUF_MINOR_VERSION {git_minor}",
  89. "",
  90. )
  91. with open(str(target_file), "wt") as file:
  92. file.write("\n".join(version_file_data))
  93. def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"):
  94. # Gathering icons sources
  95. icons_src = env.GlobRecursive("*.png", source_dir)
  96. icons_src += env.GlobRecursive("frame_rate", source_dir)
  97. icons = env.IconBuilder(
  98. target_dir,
  99. ICON_SRC_DIR=source_dir,
  100. ICON_FILE_NAME=icon_bundle_name,
  101. )
  102. env.Depends(icons, icons_src)
  103. return icons
  104. def generate(env):
  105. env.SetDefault(
  106. ASSETS_COMPILER="${ROOT_DIR.abspath}/scripts/assets.py",
  107. NANOPB_COMPILER="${ROOT_DIR.abspath}/lib/nanopb/generator/nanopb_generator.py",
  108. )
  109. env.AddMethod(CompileIcons)
  110. if not env["VERBOSE"]:
  111. env.SetDefault(
  112. ICONSCOMSTR="\tICONS\t${TARGET}",
  113. PROTOCOMSTR="\tPROTO\t${SOURCE}",
  114. DOLPHINCOMSTR="\tDOLPHIN\t${DOLPHIN_RES_TYPE}",
  115. RESMANIFESTCOMSTR="\tMANIFEST\t${TARGET}",
  116. PBVERCOMSTR="\tPBVER\t${TARGET}",
  117. )
  118. env.Append(
  119. BUILDERS={
  120. "IconBuilder": Builder(
  121. action=Action(
  122. '${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir} --filename ${ICON_FILE_NAME}',
  123. "${ICONSCOMSTR}",
  124. ),
  125. emitter=icons_emitter,
  126. ),
  127. "ProtoBuilder": Builder(
  128. action=Action(
  129. '${PYTHON3} "${NANOPB_COMPILER}" -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}',
  130. "${PROTOCOMSTR}",
  131. ),
  132. emitter=proto_emitter,
  133. suffix=".pb.c",
  134. src_suffix=".proto",
  135. ),
  136. "DolphinSymBuilder": Builder(
  137. action=Action(
  138. '${PYTHON3} "${ASSETS_COMPILER}" dolphin -s dolphin_${DOLPHIN_RES_TYPE} "${SOURCE}" "${_DOLPHIN_OUT_DIR}"',
  139. "${DOLPHINCOMSTR}",
  140. ),
  141. emitter=dolphin_emitter,
  142. ),
  143. "DolphinExtBuilder": Builder(
  144. action=Action(
  145. '${PYTHON3} "${ASSETS_COMPILER}" dolphin "${SOURCE}" "${_DOLPHIN_OUT_DIR}"',
  146. "${DOLPHINCOMSTR}",
  147. ),
  148. emitter=dolphin_emitter,
  149. ),
  150. "ProtoVerBuilder": Builder(
  151. action=Action(
  152. proto_ver_generator,
  153. "${PBVERCOMSTR}",
  154. ),
  155. ),
  156. }
  157. )
  158. def exists(env):
  159. return True