SConstruct 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #
  2. # Main Fipper Build System entry point
  3. #
  4. # This file is evaluated by scons (the build system) every time fbt is invoked.
  5. # Scons constructs all referenced environments & their targets' dependency
  6. # trees on startup. So, to keep startup time as low as possible, we're hiding
  7. # construction of certain targets behind command-line options.
  8. import os
  9. EnsurePythonVersion(3, 8)
  10. DefaultEnvironment(tools=[])
  11. # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15)
  12. # This environment is created only for loading options & validating file/dir existance
  13. fbt_variables = SConscript("site_scons/commandline.scons")
  14. cmd_environment = Environment(tools=[], variables=fbt_variables)
  15. Help(fbt_variables.GenerateHelpText(cmd_environment))
  16. # Building basic environment - tools, utility methods, cross-compilation
  17. # settings, gcc flags for Cortex-M4, basic builders and more
  18. coreenv = SConscript(
  19. "site_scons/environ.scons",
  20. exports={"VAR_ENV": cmd_environment},
  21. )
  22. SConscript("site_scons/cc.scons", exports={"ENV": coreenv})
  23. # Store root dir in environment for certain tools
  24. coreenv["ROOT_DIR"] = Dir(".")
  25. # Create a separate "dist" environment and add construction envs to it
  26. distenv = coreenv.Clone(
  27. tools=["fbt_dist", "openocd", "blackmagic", "jflash"],
  28. OPENOCD_GDB_PIPE=[
  29. "|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"
  30. ],
  31. GDBOPTS_BASE=[
  32. "-ex",
  33. "target extended-remote ${GDBREMOTE}",
  34. "-ex",
  35. "set confirm off",
  36. ],
  37. GDBOPTS_BLACKMAGIC=[
  38. "-ex",
  39. "monitor swdp_scan",
  40. "-ex",
  41. "monitor debug_bmp enable",
  42. "-ex",
  43. "attach 1",
  44. "-ex",
  45. "set mem inaccessible-by-default off",
  46. ],
  47. GDBPYOPTS=[
  48. "-ex",
  49. "source debug/FreeRTOS/FreeRTOS.py",
  50. "-ex",
  51. "source debug/PyCortexMDebug/PyCortexMDebug.py",
  52. "-ex",
  53. "svd_load ${SVD_FILE}",
  54. "-ex",
  55. "compare-sections",
  56. ],
  57. JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash",
  58. ENV=os.environ,
  59. )
  60. firmware_env = distenv.AddFwProject(
  61. base_env=coreenv,
  62. fw_type="firmware",
  63. fw_env_key="FW_ENV",
  64. )
  65. # If enabled, initialize updater-related targets
  66. if GetOption("fullenv") or any(
  67. filter(lambda target: "updater" in target or "flash_usb" in target, BUILD_TARGETS)
  68. ):
  69. updater_env = distenv.AddFwProject(
  70. base_env=coreenv,
  71. fw_type="updater",
  72. fw_env_key="UPD_ENV",
  73. )
  74. # Target for self-update package
  75. dist_basic_arguments = [
  76. "--bundlever",
  77. '"${UPDATE_VERSION_STRING}"',
  78. ]
  79. dist_radio_arguments = [
  80. "--radio",
  81. '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
  82. "--radiotype",
  83. "${COPRO_STACK_TYPE}",
  84. "${COPRO_DISCLAIMER}",
  85. "--obdata",
  86. '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
  87. ]
  88. dist_resource_arguments = [
  89. "-r",
  90. '"${ROOT_DIR.abspath}/assets/resources"',
  91. ]
  92. dist_splash_arguments = (
  93. [
  94. "--splash",
  95. distenv.subst("assets/slideshow/$UPDATE_SPLASH"),
  96. ]
  97. if distenv["UPDATE_SPLASH"]
  98. else []
  99. )
  100. selfupdate_dist = distenv.DistCommand(
  101. "updater_package",
  102. (distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
  103. DIST_EXTRA=[
  104. *dist_basic_arguments,
  105. *dist_radio_arguments,
  106. *dist_resource_arguments,
  107. *dist_splash_arguments,
  108. ],
  109. )
  110. selfupdate_min_dist = distenv.DistCommand(
  111. "updater_minpackage",
  112. distenv["DIST_DEPENDS"],
  113. DIST_EXTRA=dist_basic_arguments,
  114. )
  115. # Updater debug
  116. distenv.PhonyTarget(
  117. "updater_debug",
  118. "${GDBPYCOM}",
  119. source=updater_env["FW_ELF"],
  120. GDBREMOTE="${OPENOCD_GDB_PIPE}",
  121. )
  122. distenv.PhonyTarget(
  123. "updater_blackmagic",
  124. "${GDBPYCOM}",
  125. source=updater_env["FW_ELF"],
  126. GDBOPTS=distenv.subst("$GDBOPTS_BLACKMAGIC"),
  127. GDBREMOTE="${BLACKMAGIC_ADDR}",
  128. )
  129. # Installation over USB & CLI
  130. usb_update_package = distenv.AddUsbFlashTarget(
  131. "#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
  132. )
  133. distenv.Alias("flash_usb_full", usb_update_package)
  134. usb_minupdate_package = distenv.AddUsbFlashTarget(
  135. "#build/minusbinstall.flag", (selfupdate_min_dist,)
  136. )
  137. distenv.Alias("flash_usb", usb_minupdate_package)
  138. # Target for copying & renaming binaries to dist folder
  139. basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
  140. distenv.Default(basic_dist)
  141. # Target for bundling core2 package for qFlipper
  142. copro_dist = distenv.CoproBuilder(
  143. distenv.Dir("assets/core2_firmware"),
  144. [],
  145. )
  146. distenv.Alias("copro_dist", copro_dist)
  147. firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
  148. distenv.Alias("flash", firmware_flash)
  149. firmware_jflash = distenv.AddJFlashTarget(firmware_env)
  150. distenv.Alias("jflash", firmware_jflash)
  151. firmware_bm_flash = distenv.PhonyTarget(
  152. "flash_blackmagic",
  153. "$GDB $GDBOPTS $SOURCES $GDBFLASH",
  154. source=firmware_env["FW_ELF"],
  155. GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
  156. GDBREMOTE="${BLACKMAGIC_ADDR}",
  157. GDBFLASH=[
  158. "-ex",
  159. "load",
  160. "-ex",
  161. "quit",
  162. ],
  163. )
  164. # Debugging firmware
  165. firmware_debug = distenv.PhonyTarget(
  166. "debug",
  167. "${GDBPYCOM}",
  168. source=firmware_env["FW_ELF"],
  169. GDBOPTS="${GDBOPTS_BASE}",
  170. GDBREMOTE="${OPENOCD_GDB_PIPE}",
  171. )
  172. distenv.Depends(firmware_debug, firmware_flash)
  173. distenv.PhonyTarget(
  174. "blackmagic",
  175. "${GDBPYCOM}",
  176. source=firmware_env["FW_ELF"],
  177. GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
  178. GDBREMOTE="${BLACKMAGIC_ADDR}",
  179. )
  180. # Debug alien elf
  181. distenv.PhonyTarget(
  182. "debug_other",
  183. "${GDBPYCOM}",
  184. GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
  185. GDBREMOTE="${OPENOCD_GDB_PIPE}",
  186. )
  187. # Just start OpenOCD
  188. distenv.PhonyTarget(
  189. "openocd",
  190. "${OPENOCDCOM}",
  191. )
  192. # Linter
  193. distenv.PhonyTarget(
  194. "lint",
  195. "${PYTHON3} scripts/lint.py check ${LINT_SOURCES}",
  196. LINT_SOURCES=firmware_env["LINT_SOURCES"],
  197. )
  198. distenv.PhonyTarget(
  199. "format",
  200. "${PYTHON3} scripts/lint.py format ${LINT_SOURCES}",
  201. LINT_SOURCES=firmware_env["LINT_SOURCES"],
  202. )
  203. # Find blackmagic probe
  204. distenv.PhonyTarget(
  205. "get_blackmagic",
  206. "@echo $( ${BLACKMAGIC_ADDR} $)",
  207. )