CMakeLists.txt 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. cmake_minimum_required(VERSION 3.15)
  2. include(cmake/Utilities.cmake)
  3. include(cmake/GetGitRevisionDescription.cmake)
  4. set(PROJECT_VERSION_SUFFIX
  5. "<auto>"
  6. CACHE
  7. STRING
  8. "Full version suffix to be shown on the info screen in settings (e.g. full_version=4.0.3-BETA+1035.PR111.B4, suffix=-BETA+1035.PR111.B4). Defaults to '+<commit sha>.<dirty?>.<debug?>' if set to '<auto>'."
  9. )
  10. set(PROJECT_VERSION_SUFFIX_SHORT
  11. "<auto>"
  12. CACHE
  13. STRING
  14. "Short version suffix to be shown on splash screen. Defaults to '+<BUILD_NUMBER>' if set to '<auto>'."
  15. )
  16. set(BUILD_NUMBER
  17. ""
  18. CACHE
  19. STRING
  20. "Build number of the firmware. Resolved automatically if not specified.")
  21. include(cmake/ProjectVersion.cmake)
  22. resolve_version_variables()
  23. set(PROJECT_VERSION_FLAVOUR
  24. ""
  25. CACHE STRING "Firmware flavour to build - DEBUG, DEVEL, APLHA, BETA or RC")
  26. set(PROJECT_VERSION_FLAVOUR_REVISION
  27. ""
  28. CACHE STRING "Firmware flavour version, e.g. 1 for RC1, etc")
  29. if(NOT PROJECT_VERSION_FLAVOUR STREQUAL "")
  30. set(PROJECT_VERSION "${PROJECT_VERSION}-${PROJECT_VERSION_FLAVOUR}")
  31. add_compile_definitions(FW_FLAVOR=${PROJECT_VERSION_FLAVOUR})
  32. if(NOT PROJECT_VERSION_FLAVOUR_REVISION STREQUAL "")
  33. set(PROJECT_VERSION "${PROJECT_VERSION}${PROJECT_VERSION_FLAVOUR_REVISION}")
  34. add_compile_definitions(FW_FLAVERSION=${PROJECT_VERSION_FLAVOUR_REVISION})
  35. endif()
  36. endif()
  37. # Inform user about the resolved settings
  38. message(STATUS "Project version: ${PROJECT_VERSION}")
  39. message(
  40. STATUS
  41. "Project version with short suffix: ${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX_SHORT}"
  42. )
  43. set(FN_PREFIX "FW${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX_SHORT}")
  44. message(
  45. WARNING
  46. "
  47. ***************** YOUR ATTENTION PLEASE *****************
  48. CMake support is experimental. There is no guarantee at this time. If you have problems you are encouraged to fall back to the tried-and-true methods.
  49. *********************** THANK YOU **********************
  50. We now return to your regularly scheduled Firmware Build.")
  51. option(SECONDARY_LANGUAGES "Secondary language support in the firmware" ON)
  52. set(MAIN_LANGUAGES
  53. cs de es fr it pl
  54. CACHE STRING
  55. "The list of 'main' languages to be included, in the correct order")
  56. set(COMMUNITY_LANGUAGES
  57. nl
  58. ro
  59. hu
  60. hr
  61. sk
  62. sv
  63. no
  64. CACHE STRING
  65. "The list of community languages to be included, in the correct order"
  66. )
  67. set(SELECTED_LANGUAGES ${MAIN_LANGUAGES} ${COMMUNITY_LANGUAGES})
  68. get_dependency_directory(prusa3dboards PRUSA_BOARDS_DIR)
  69. project(Prusa-Firmware)
  70. add_subdirectory(lib)
  71. file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/Firmware/config.h MAX_SIZE_LINE
  72. REGEX "^#define \+LANG_SIZE_RESERVED \+")
  73. string(REGEX MATCH "0x[0-9]+" MAX_SIZE_HEX "${MAX_SIZE_LINE}")
  74. math(EXPR LANG_MAX_SIZE "${MAX_SIZE_HEX}" OUTPUT_FORMAT DECIMAL)
  75. message("Language maximum size (from config.h): ${LANG_MAX_SIZE} bytes")
  76. set(LANG_BIN_MAX 249856) # Ditto, this in xflash_layout.h but needs invocation
  77. # of the preprocessor... :-/
  78. get_recommended_gcc_version(RECOMMENDED_TOOLCHAIN_VERSION)
  79. if(CMAKE_CROSSCOMPILING AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL
  80. ${RECOMMENDED_TOOLCHAIN_VERSION})
  81. message(
  82. WARNING "Recommended AVR toolchain is ${RECOMMENDED_TOOLCHAIN_VERSION}"
  83. ", but you have ${CMAKE_CXX_COMPILER_VERSION}")
  84. elseif(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  85. message(
  86. WARNING
  87. "Recommended compiler for host tools and unittests is GCC, you have ${CMAKE_CXX_COMPILER_ID}."
  88. )
  89. endif()
  90. # append custom C/C++ flags
  91. if(CUSTOM_COMPILE_OPTIONS)
  92. string(REPLACE " " ";" CUSTOM_COMPILE_OPTIONS "${CUSTOM_COMPILE_OPTIONS}")
  93. add_compile_options(${CUSTOM_COMPILE_OPTIONS})
  94. endif()
  95. #
  96. # Global Compiler & Linker Configuration
  97. #
  98. # enable warnings
  99. add_compile_options(-Wall -Wextra -Wno-expansion-to-defined -Wsign-compare)
  100. # default standards for all targets
  101. set(CMAKE_C_STANDARD 11)
  102. set(CMAKE_CXX_STANDARD 17)
  103. # support _DEBUG macro (some code uses to recognize debug builds)
  104. if(CMAKE_BUILD_TYPE STREQUAL "Debug")
  105. add_compile_definitions(_DEBUG)
  106. endif()
  107. #
  108. # Firmware - get file lists.
  109. #
  110. set(FW_SOURCES
  111. adc.cpp
  112. backlight.cpp
  113. BlinkM.cpp
  114. bootapp.c
  115. cardreader.cpp
  116. cmdqueue.cpp
  117. Configuration.cpp
  118. ConfigurationStore.cpp
  119. conv2str.cpp
  120. Dcodes.cpp
  121. eeprom.cpp
  122. fancheck.cpp
  123. Filament_sensor.cpp
  124. first_lay_cal.cpp
  125. heatbed_pwm.cpp
  126. la10compat.cpp
  127. language.c
  128. lcd.cpp
  129. Marlin_main.cpp
  130. MarlinSerial.cpp
  131. menu.cpp
  132. mesh_bed_calibration.cpp
  133. mesh_bed_leveling.cpp
  134. messages.cpp
  135. mmu2.cpp
  136. mmu2_crc.cpp
  137. mmu2_error_converter.cpp
  138. mmu2_fsensor.cpp
  139. mmu2_log.cpp
  140. mmu2_power.cpp
  141. mmu2_progress_converter.cpp
  142. mmu2_protocol.cpp
  143. mmu2_protocol_logic.cpp
  144. mmu2_reporting.cpp
  145. mmu2_serial.cpp
  146. motion_control.cpp
  147. optiboot_xflash.cpp
  148. pat9125.cpp
  149. planner.cpp
  150. Prusa_farm.cpp
  151. qr_solve.cpp
  152. rbuf.c
  153. Sd2Card.cpp
  154. SdBaseFile.cpp
  155. SdFatUtil.cpp
  156. SdFile.cpp
  157. SdVolume.cpp
  158. Servo.cpp
  159. sm4.c
  160. sound.cpp
  161. speed_lookuptable.cpp
  162. spi.c
  163. SpoolJoin.cpp
  164. stepper.cpp
  165. swi2c.c
  166. swspi.cpp
  167. Tcodes.cpp
  168. temperature.cpp
  169. timer02.c
  170. Timer.cpp
  171. tmc2130.cpp
  172. tone04.c
  173. twi.cpp
  174. uart2.c
  175. ultralcd.cpp
  176. util.cpp
  177. vector_3.cpp
  178. xflash.c
  179. xflash_dump.cpp
  180. xyzcal.cpp)
  181. list(TRANSFORM FW_SOURCES PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/Firmware/)
  182. set(AVR_SOURCES
  183. wiring_digital.c
  184. WInterrupts.c
  185. wiring_pulse.c
  186. hooks.c
  187. wiring.c
  188. wiring_analog.c
  189. wiring_shift.c
  190. CDC.cpp
  191. PluggableUSB.cpp
  192. HardwareSerial.cpp
  193. HardwareSerial0.cpp
  194. HardwareSerial1.cpp
  195. HardwareSerial3.cpp
  196. IPAddress.cpp
  197. HardwareSerial2.cpp
  198. Print.cpp
  199. Stream.cpp
  200. Tone.cpp
  201. USBCore.cpp
  202. WMath.cpp
  203. WString.cpp
  204. abi.cpp
  205. main.cpp
  206. # new.cpp # What happened to this? it was removed in 1.0.5-1 to 1.0.5.2?
  207. )
  208. list(TRANSFORM AVR_SOURCES PREPEND ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/)
  209. #
  210. # Target configuration
  211. #
  212. if(CMAKE_CROSSCOMPILING)
  213. # Reproducible build support
  214. function(set_reproducible_sources source_list prefix)
  215. foreach(file IN LISTS ${source_list})
  216. get_filename_component(base ${file} NAME)
  217. set(target "${prefix}${base}")
  218. set_property(
  219. SOURCE ${file}
  220. APPEND
  221. PROPERTY COMPILE_OPTIONS "-frandom-seed=${target}.o")
  222. endforeach()
  223. endfunction()
  224. function(set_reproducible_target target)
  225. set_target_properties(${target} PROPERTIES STATIC_LIBRARY_OPTIONS "-D")
  226. endfunction()
  227. set_reproducible_sources(AVR_SOURCES "core/")
  228. add_link_options(-fdebug-prefix-map=${CMAKE_SOURCE_DIR}=)
  229. add_link_options(-fdebug-prefix-map=${CMAKE_BINARY_DIR}=)
  230. if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "8")
  231. add_compile_options(-ffile-prefix-map=${CMAKE_SOURCE_DIR}=)
  232. endif()
  233. # TODO: get date from the last git commit to set as epoch
  234. set(ENV{SOURCE_DATE_EPOCH} 0)
  235. if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8")
  236. string(TIMESTAMP SOURCE_DATE_EPOCH "%Y-%m-%d")
  237. add_compile_definitions(SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH}")
  238. string(TIMESTAMP SOURCE_TIME_EPOCH "%H:%M:%S")
  239. add_compile_definitions(SOURCE_TIME_EPOCH="${SOURCE_TIME_EPOCH}")
  240. endif()
  241. # default optimization flags
  242. set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
  243. set(CMAKE_CXX_FLAGS_RELEASE "-Os -g -DNDEBUG")
  244. set(CMAKE_C_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
  245. set(CMAKE_C_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
  246. # mcu and target-related settings
  247. add_compile_options(-mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10819
  248. -DARDUINO_AVR_PRUSA_EINSY_RAMBO -DARDUINO_ARCH_AVR)
  249. add_link_options(-mmcu=atmega2560 -Wl,-u,vfprintf -lprintf_flt -lm)
  250. # disable some C++ language features
  251. add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-threadsafe-statics>)
  252. add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
  253. # disable exceptions
  254. add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>)
  255. add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-unwind-tables>)
  256. # split and gc sections
  257. add_compile_options(-ffunction-sections -fdata-sections)
  258. add_link_options(-ffunction-sections -fdata-sections -Wl,--gc-sections)
  259. # LTO (with custom options)
  260. add_compile_options(-flto -fno-fat-lto-objects)
  261. add_link_options(-flto)
  262. # Create this target before we apply the GC options
  263. add_library(avr_core STATIC ${AVR_SOURCES})
  264. set_reproducible_target(avr_core)
  265. target_include_directories(
  266. avr_core PRIVATE ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/
  267. ${PRUSA_BOARDS_DIR}/variants/prusa_einsy_rambo/)
  268. endif()
  269. # Meta targets to build absolutely everything
  270. add_custom_target(ALL_FIRMWARE)
  271. add_custom_target(ALL_ENGLISH)
  272. add_custom_target(ALL_MULTILANG)
  273. add_dependencies(ALL_FIRMWARE ALL_ENGLISH ALL_MULTILANG)
  274. set_target_properties(ALL_MULTILANG PROPERTIES EXCLUDE_FROM_ALL FALSE)
  275. function(add_base_binary variant_name)
  276. add_executable(${variant_name} ${FW_SOURCES} ${FW_HEADERS}
  277. ${VARIANT_CFG_DST})
  278. set_target_properties(${variant_name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
  279. target_include_directories(
  280. ${variant_name}
  281. PRIVATE ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/
  282. ${PRUSA_BOARDS_DIR}/variants/prusa_einsy_rambo/
  283. ${VARIANT_CFG_DIR} # Include the header for this variant.
  284. ${CMAKE_SOURCE_DIR}/Firmware)
  285. target_link_libraries(${variant_name} avr_core)
  286. # # configure linker script
  287. set(LINKER_SCRIPT ${PRUSA_BOARDS_DIR}/ldscripts/avr6.xn)
  288. target_link_options(${variant_name} PUBLIC -Wl,-T,${LINKER_SCRIPT})
  289. # limit the text section to 248K (256K - 8k reserved for the bootloader)
  290. target_link_options(${variant_name} PUBLIC
  291. -Wl,--defsym=__TEXT_REGION_LENGTH__=248K)
  292. # produce ASM listing. Note we also specify the .map as a byproduct so it gets
  293. # cleaned because link_options doesn't have a "generated outputs" feature.
  294. add_custom_command(
  295. TARGET ${variant_name}
  296. POST_BUILD
  297. COMMAND ${CMAKE_OBJDUMP} --prefix ${CMAKE_SOURCE_DIR} -CSd ${variant_name} >
  298. ${variant_name}.asm
  299. BYPRODUCTS ${variant_name}.asm ${variant_name}.map)
  300. # inform about the firmware's size in terminal
  301. add_custom_command(
  302. TARGET ${variant_name}
  303. POST_BUILD
  304. COMMAND ${CMAKE_SIZE_UTIL} -C --mcu=atmega2560 ${variant_name})
  305. report_size(${variant_name})
  306. # generate linker map file
  307. target_link_options(${variant_name} PUBLIC
  308. -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${variant_name}.map)
  309. target_compile_definitions(${variant_name} PRIVATE CMAKE_LANG_CONTROL)
  310. endfunction()
  311. function(fw_add_variant variant_name)
  312. # Set FW_SOURCES to be reproducible in this variant as it's set in a separate
  313. # project
  314. set_reproducible_sources(FW_SOURCES "Firmware/")
  315. # Create the Configuration_Prusa.h for this variant so it can be #included.
  316. set(VARIANT_CFG_DIR ${CMAKE_CURRENT_BINARY_DIR}/include)
  317. set(VARIANT_CFG_DST ${VARIANT_CFG_DIR}/Configuration_prusa.h)
  318. set(VARIANT_CFG_SRC ${CMAKE_SOURCE_DIR}/Firmware/variants/${variant_name}.h)
  319. add_custom_command(
  320. OUTPUT ${VARIANT_CFG_DST}
  321. COMMAND
  322. ${CMAKE_COMMAND} -E copy ${VARIANT_CFG_SRC} ${VARIANT_CFG_DST}
  323. COMMENT "Generating Configuration_prusa.h for ${variant_name}"
  324. BYPRODUCTS ${VARIANT_CFG_DIR}
  325. DEPENDS ${VARIANT_CFG_SRC})
  326. string(REPLACE "1_75mm_" "" variant_name "${variant_name}")
  327. string(REPLACE "-E3Dv6full" "" variant_name "${variant_name}")
  328. # Single-language build
  329. set(FW_EN "${variant_name}_EN-only")
  330. set(FW_HEX ${CMAKE_BINARY_DIR}/${FN_PREFIX}-${FW_EN}.hex)
  331. add_base_binary(${FW_EN})
  332. target_compile_definitions(${FW_EN} PUBLIC LANG_MODE=0)
  333. add_custom_command(
  334. TARGET ${FW_EN}
  335. POST_BUILD
  336. COMMAND ${CMAKE_OBJCOPY} -O ihex ${FW_EN} ${FW_EN}.hex
  337. COMMAND ${CMAKE_OBJCOPY} -O ihex ${FW_EN} ${FW_HEX}
  338. BYPRODUCTS ${FW_EN}.hex ${FW_HEX}
  339. COMMENT "Generating ${FW_EN}.hex")
  340. add_dependencies(ALL_ENGLISH ${FW_EN})
  341. # Multi-language build/s
  342. set(FW_LANG_BASE "${variant_name}_Multilang_base")
  343. set(FW_LANG_PATCH "${variant_name}_Multilang_patch")
  344. add_base_binary(${FW_LANG_BASE})
  345. target_compile_definitions(${FW_LANG_BASE} PUBLIC LANG_MODE=1)
  346. # Construct language map
  347. set(LANG_TMP_DIR lang)
  348. set(LANG_MAP ${LANG_TMP_DIR}/${variant_name}_lang.map)
  349. add_custom_command(
  350. OUTPUT ${LANG_MAP}
  351. COMMAND ${CMAKE_OBJCOPY} -O binary ${FW_LANG_BASE} ${FW_LANG_PATCH}.bin
  352. COMMAND ${CMAKE_SOURCE_DIR}/lang/lang-map.py ${FW_LANG_BASE} ${FW_LANG_PATCH}.bin > ${LANG_MAP}
  353. COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${FW_LANG_PATCH}.bin ${FW_LANG_PATCH}.hex
  354. DEPENDS ${FW_LANG_BASE}
  355. BYPRODUCTS ${FW_LANG_PATCH}.bin ${FW_LANG_PATCH}.hex
  356. COMMENT "Generating ${variant_name} language map")
  357. # Build language catalogs
  358. set(LANG_BINS "")
  359. foreach(LANG IN LISTS SELECTED_LANGUAGES)
  360. set(LANG_BIN ${LANG_TMP_DIR}/${variant_name}_${LANG}.bin)
  361. set(PO_FILE "${CMAKE_SOURCE_DIR}/lang/po/Firmware_${LANG}.po")
  362. add_custom_command(
  363. OUTPUT ${LANG_BIN}
  364. #[[
  365. # Check po file:
  366. #COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lang/lang-check.py --no-warning --map ${LANG_MAP} ${PO_FILE}
  367. #]]
  368. COMMAND ${CMAKE_SOURCE_DIR}/lang/lang-build.py ${LANG_MAP} ${PO_FILE} ${LANG_BIN}
  369. # Check bin size:
  370. COMMAND
  371. ${CMAKE_COMMAND} -DLANG_MAX_SIZE=${LANG_MAX_SIZE}
  372. -DLANG_FILE=${LANG_BIN} -P ${PROJECT_CMAKE_DIR}/Check_lang_size.cmake
  373. DEPENDS ${LANG_MAP} ${PO_FILE}
  374. COMMENT "Generating ${variant_name}_${LANG}.bin")
  375. list(APPEND LANG_BINS ${LANG_BIN})
  376. endforeach()
  377. string(FIND ${variant_name} "MK3" HAS_XFLASH)
  378. if(${HAS_XFLASH} GREATER_EQUAL 0)
  379. # X-Flash based build (catalogs appended to patched binary)
  380. set(FW_LANG_FINAL "${variant_name}_Multilang")
  381. set(LANG_HEX ${CMAKE_BINARY_DIR}/${FN_PREFIX}-${FW_LANG_FINAL}.hex)
  382. set(LANG_CATBIN ${LANG_TMP_DIR}/${variant_name}_cat.bin)
  383. set(LANG_CATHEX ${LANG_TMP_DIR}/${variant_name}_cat.hex)
  384. add_custom_command(
  385. OUTPUT ${LANG_CATBIN}
  386. COMMAND ${CMAKE_COMMAND} -E cat ${LANG_BINS} > ${LANG_CATBIN}
  387. DEPENDS ${LANG_BINS}
  388. COMMENT "Merging language catalogs")
  389. #[[
  390. #add_custom_command(OUTPUT ${LANG_FINAL_BIN}
  391. # COMMAND ${CMAKE_COMMAND} -DLANG_MAX_SIZE=${LANG_BIN_MAX} -DLANG_FILE=${LANG_FINAL_BIN}
  392. # -P ${PROJECT_CMAKE_DIR}/Check_final_lang_bin_size.cmake
  393. # APPEND)
  394. #]]
  395. add_custom_command(
  396. OUTPUT ${LANG_CATHEX}
  397. COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${LANG_CATBIN} ${LANG_CATHEX}
  398. DEPENDS ${LANG_CATBIN}
  399. COMMENT "Generating Hex for language data")
  400. add_custom_command(
  401. OUTPUT ${FW_LANG_FINAL}.hex
  402. COMMAND ${CMAKE_COMMAND} -E cat ${FW_LANG_PATCH}.hex ${LANG_CATHEX} > ${FW_LANG_FINAL}.hex
  403. COMMAND ${CMAKE_COMMAND} -E copy ${FW_LANG_FINAL}.hex ${LANG_HEX}
  404. BYPRODUCTS ${LANG_HEX}
  405. DEPENDS ${FW_LANG_PATCH}.hex ${LANG_CATHEX}
  406. COMMENT "Generating final ${FW_LANG_FINAL}.hex")
  407. add_custom_target(${FW_LANG_FINAL} DEPENDS ${FW_LANG_FINAL}.hex)
  408. add_dependencies(ALL_MULTILANG ${FW_LANG_FINAL})
  409. else()
  410. set(ALL_VARIANT_HEXES "")
  411. # Non-xflash, e.g. MK2.5
  412. foreach(LANG IN LISTS SELECTED_LANGUAGES)
  413. set(FW_LANG_FINAL ${variant_name}-en_${LANG})
  414. set(LANG_HEX ${CMAKE_BINARY_DIR}/${FN_PREFIX}-${FW_LANG_FINAL}.hex)
  415. set(LANG_BIN ${LANG_TMP_DIR}/${variant_name}_${LANG}.bin)
  416. # Intermediate 2-lang bin
  417. add_custom_command(
  418. OUTPUT ${FW_LANG_FINAL}.bin
  419. COMMAND ${CMAKE_OBJCOPY} -O binary ${FW_LANG_BASE} ${FW_LANG_FINAL}.bin
  420. COMMAND ${CMAKE_SOURCE_DIR}/lang/lang-patchsec.py ${FW_LANG_BASE}
  421. ${LANG_BIN} ${FW_LANG_FINAL}.bin
  422. DEPENDS ${FW_LANG_BASE} ${LANG_BIN}
  423. COMMENT "Generating ${FW_LANG_FINAL}.bin")
  424. # Final hex
  425. add_custom_command(OUTPUT ${FW_LANG_FINAL}.hex
  426. COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${FW_LANG_FINAL}.bin ${FW_LANG_FINAL}.hex
  427. COMMAND ${CMAKE_COMMAND} -E copy ${FW_LANG_FINAL}.hex ${LANG_HEX}
  428. DEPENDS ${FW_LANG_FINAL}.bin
  429. COMMENT "Creating ${FW_LANG_FINAL}.hex")
  430. add_custom_target(${FW_LANG_FINAL} DEPENDS ${FW_LANG_FINAL}.hex)
  431. list(APPEND ALL_VARIANT_HEXES ${FW_LANG_FINAL})
  432. endforeach()
  433. add_custom_target("${variant_name}-All-Languages"
  434. DEPENDS ${ALL_VARIANT_HEXES})
  435. add_dependencies(ALL_MULTILANG "${variant_name}-All-Languages")
  436. endif()
  437. endfunction()
  438. if(CMAKE_CROSSCOMPILING)
  439. # build a list of all supported variants
  440. file(
  441. GLOB ALL_VARIANTS
  442. RELATIVE ${PROJECT_SOURCE_DIR}/Firmware/variants
  443. ${PROJECT_SOURCE_DIR}/Firmware/variants/*.h)
  444. list(TRANSFORM ALL_VARIANTS REPLACE "\.h$" "")
  445. set(FW_VARIANTS
  446. ${ALL_VARIANTS}
  447. CACHE STRING "Firmware variants to be built")
  448. foreach(THIS_VAR IN LISTS FW_VARIANTS)
  449. if(NOT ${THIS_VAR} IN_LIST ALL_VARIANTS)
  450. message(FATAL_ERROR "Variant ${THIS_VAR} does not exist")
  451. endif()
  452. message("Variant added: ${THIS_VAR}")
  453. string(REPLACE "-E3Dv6full" "" DIR_NAME "${THIS_VAR}")
  454. string(REPLACE "1_75mm_" "" DIR_NAME "${DIR_NAME}")
  455. # Generate a file in a subfolder so that we can organize things a little
  456. # more neatly in VS code
  457. file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
  458. file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME}/CMakeLists.txt
  459. "project(${DIR_NAME})\nfw_add_variant(${THIS_VAR})")
  460. add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
  461. # fw_add_variant(${TRIMMED_NAME})
  462. endforeach(THIS_VAR IN LISTS FW_VARIANTS)
  463. endif()
  464. if(NOT CMAKE_CROSSCOMPILING)
  465. enable_testing()
  466. add_subdirectory(tests)
  467. endif()