CMakeLists.txt 17 KB

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