Generate two binaries that share CMakeFile but different linker script

In my embedded project I have a use case in which the CMakelist.txt needs to generate two “quasi identical” binaries that share the same build process, same sources, headers and dependencies, but different linker scripts. I don’t know how to cleanly do this.
For now I’m using a variable defined when launching cmake:

# Compile option variables
set(BOOTLOADER_SPACE_EN ON CACHE BOOL "Enable additional space before the binary for fitting the bootloader")

And then using the output of this variable to generate either one binary or the other.

if(${BOOTLOADER_SPACE_EN}) 
    set(EXECUTABLE_NAME "${PROJECT_NAME}_shifted")
else()
    set(EXECUTABLE_NAME ${PROJECT_NAME})
endif()
message("Adding Executable: ${EXECUTABLE_NAME}")
add_executable(${EXECUTABLE_NAME})

if(${BOOTLOADER_SPACE_EN})
    stm32_add_linker_script(${EXECUTABLE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/STM32F446RETx_FLASH_shifted.ld)
else()
    stm32_add_linker_script(${EXECUTABLE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/STM32F446RETx_FLASH.ld)
endif()

What I don’t like about this method is that the generated Makefile (if I understood correctly) doesn’t contain both options, therefore if one wanted to switch what binary must be generated, cmake must be re-issued with a different option.
I think that the best solution should be to decide that at build time (as makefile parameters instead of cmake) what you want to get, is this correct/the best way to do this?

What would you do in my shoes, is there something I could do better?

Makefile parameters would only work in Make, not in any other build tool. So CMake does not support that.

Changing the cache variable and recall the build, automatically does recall CMake. So your current solution is the straight forward one.

Apart from that I guess, it’s only possible to put all sources into libraries (static, object). And create two executables and add those libraries to both. Or maybe use a generator expression to “copy” the dependencies of the first exe to the second one.

A total different (CMake independent) solution may be, to always create the same executable. And use a dummy bootloader (e.g. a simple jump) for the other use case.

Apart from that I guess, it’s only possible to put all sources into libraries (static, object). And create two executables and add those libraries to both. Or maybe use a generator expression to “copy” the dependencies of the first exe to the second one.

Could you elaborate more on this part? what do you mean by libraries? and do you have a template for the code generation?
Because I like the idea of generating both executables but I don’t like to rewrite the same CMake code for both to generate them.

Libraries as in add_library. And add the libraries to both executables instead of one.

The alternative solution by copying the dependencies, may look like this, but I never tried it myself:

add_executable(${EXECUTABLE_NAME})

add_executable(${EXECUTABLE_NAME}_shifted)
target_link_libraries(${EXECUTABLE_NAME}_shifted
  PRIVATE
    $<TARGET_PROPERTY:${EXECUTABLE_NAME},LINK_LIBRARIES>
)
1 Like