CMakeLists.txt 17 KB

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