Get a CMake macro to use in a condition

Hi. I would like to make a choice between 2 files to pass to the compiler options according to a macro defined in compile_definitions of CMake. How to get this macro in a variable for example and test it please?

It’s not clear to me what you’re asking. Can you share more details to make it a bit more concrete?

I am writing a library for 2 different MCUs with 2 different toolchains. I would like to be able to choose macros depending on the MCU I want to use and the appropriate toochain. In order to choose the right file for each toolchain (the linker script in locurence), I would like to be able to retrieve the defined macro in order to choose the right file to use for the right toolchain. I need a way to retrieve the macro I would have defined. There for example i want a way to retrieve and test the first macro (STM32F303). That will be test since it can either it or STM32F411

target_compile_definitions(
    ${TARGET_NAME} PRIVATE
    -DSTM32F303
    -D_DSP_LIB
    -D_USE_RTTI
    -D_ENABLE_IRQ
)

You can access the compile definitions for a target with get_property(defines TARGET ${TARGET_NAME} PROPERTY COMPILE_DEFINITIONS). Note that this only gets target-specific flags; it will miss things coming in from CMAKE_C_FLAGS, directory-scoped add_definitions, or usage requirements.

I think a better solution would be something like this:

add_library(mcu_stm32f411 INTERFACE)
target_compile_definitions(mcu_stm32f411 INTERFACE STM32F411)
target_link_options(mcu_stm32f411 INTERFACE "SHELL:-flag_for linker_script") # or whatever is needed

and similarly for mcu_stm32f303. You can then choose which to use per-target without having to consider the other bits.

1 Like

Thanks for your response. but i dont think it will be suitable for my case. I need something like that

if(TOOLCHAIN_DIRECTORY PATH_EQUAL "$ENV{TI_TOOLCHAIN_PATH}")
    set(LINKER_FILE   ${CMAKE_SOURCE_DIR}/device/linker_commands/STM32F303_boot.cmd)
elseif(TOOLCHAIN_DIRECTORY PATH_EQUAL "$ENV{GNU_TOOLCHAIN_PATH}")
    set(LINKER_FILE   ${CMAKE_SOURCE_DIR}/device/linker_scripts/STM32F303_boot.ld)
endif()

This is for the first toolchain depending of the target define STM32F303. Now i want a way to choose another linker files depending of that define. So i want a way to check the entered define and then proceed to the selection of the correct files. The 2 toolchains are differents and dont share the same options

To check if a symbol is defined, you can use try_compile with a source file such as:

#ifdef YOURSYMBOL
#error WAS_DEFINED
#else
#error NOT_DEFINED
#endif

call try_compile and then check if the error output includes the string WAS_DEFINED.

There is not a way to get only the first macro defined here (STM32F303) and store it in a variable ?

target_compile_definitions(
    ${TARGET_NAME} PRIVATE
    -DSTM32F303
    -D_DSP_LIB
    -D_USE_RTTI
    -D_ENABLE_IRQ
)

I dont want it to access any of my source code. The symbols are already defined. I choose one of them with a global macro defined in CMake compile_definitions propriety

get_property can only get the whole list. You can use list() operations to inspect that list though.

Thanks. So get_property(defines TARGET ${TARGET_NAME} PROPERTY COMPILE_DEFINITIONS) will get the list of all compile definitions without -D and will store them in defines right ?

I tried many names but didn’t get the right result

target_compile_definitions(
    ${TARGET_NAME} PRIVATE
    -DSTM32F303
    -D_DSP_LIB
    -D_USE_RTTI
    -D_ENABLE_IRQ
)

get_target_property(DEFINES ${TARGET_NAME} COMPILE_DEFINITIONS)

# Get the first macro defined
list(GET DEFINES 0 DEVICE_DEFINE)

and then

if(DEVICE_DEFINE STREQUAL STM32F303)
        set(LINKER_FILE   ${CMAKE_SOURCE_DIR}/device/linker_commands/STM32F303_boot.cmd)
    elseif(DEVICE_DEFINE STREQUAL STM32G473)
        set(LINKER_FILE   ${CMAKE_SOURCE_DIR}/device/linker_commands/STM32G473_boot.cmd)
    endif()

But it didn’t worked. The file was not given to the linker as expected. Am I do something wrong ?

get_property and file solved my problem. Thanks. Now i can build for 2 targets usings 2 differents toolchains without errors