How to set a macro to all target_link_libraries with target_compile_definitions

Hey everyone,
I cannot get a preprocessor macro from CMake to the whole project.

I have a simple project structure (GitHub - pbizimis/keyboard):

Project/
├─ CMakeLists.txt (1)
├─ src/
│  ├─ CMakeLists.txt (2)
│  ├─ main.c
│  ├─ rotary/
│  │  ├─ CMakeLists.txt (3)
│  │  ├─ rotary.c
│  ├─ other_module/
│  │  ├─ CMakeLists.txt (4)
│  │  ├─ module.c

My CMakeLists.txt (1):

cmake_minimum_required(VERSION 3.29)

include(pico_sdk_import.cmake)

project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

pico_sdk_init()

set(FAMILY rp2040)
set(BOARD pico_sdk)

add_subdirectory(src)

add_executable(keyboard_firmware)

pico_set_linker_script(keyboard_firmware ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld)

target_link_libraries(keyboard_firmware PRIVATE Main)

pico_add_extra_outputs(keyboard_firmware)

then my src/CMakeLists.txt

add_library(Main main.c)

add_subdirectory(config)
add_subdirectory(usb)
add_subdirectory(rotary)
add_subdirectory(oled)
add_subdirectory(flash)
add_subdirectory(halves)

target_link_libraries(Main PRIVATE USB ROTARY OLED FLASH HALVES)
target_link_libraries(Main PUBLIC pico_stdlib pico_unique_id pico_cyw43_arch_none hardware_pio)

then each module such as src/rotary/CMakeLists.txt

add_library(ROTARY rotary.c)
target_include_directories(ROTARY PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(ROTARY PUBLIC pico_stdlib USB)

I would love to just define a macro in my base CMakeLists.txt (1) with target_compile_definitions(keyboard_firmware PUBLIC EXAMPLE_MACRO) but the modules (e.g. rotary.c) do not get access to it. Any ideas if that is even possible? What I ultimately want to do is to have a second executable:

cmake_minimum_required(VERSION 3.29)

include(pico_sdk_import.cmake)

project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

pico_sdk_init()

set(FAMILY rp2040)
set(BOARD pico_sdk)

add_subdirectory(src)

add_executable(keyboard_firmware_left)
pico_set_linker_script(keyboard_firmware_left ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld)
target_link_libraries(keyboard_firmware_left PRIVATE Main)
pico_add_extra_outputs(keyboard_firmware_left)
target_compile_definitions(keyboard_firmware_left PUBLIC LEFT)

add_executable(keyboard_firmware_right)
pico_set_linker_script(keyboard_firmware_right ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld)
target_link_libraries(keyboard_firmware_right PRIVATE Main)
pico_add_extra_outputs(keyboard_firmware_right)
target_compile_definitions(keyboard_firmware_right PUBLIC RIGHT)

I would appreciate any tips,
Thank you :heart:

target_compile_definitions(keyboard_firmware PUBLIC EXAMPLE_MACRO)

Here you’ve set the compile definitions for this particular target keyboard_firmware, and any other target linking to this one should get its definitions too (because it has PUBLIC scope). But here your target is an executable, and your other targets don’t link to it (which makes sense), so they are not getting this definition.

It looks like it’s the Main target (which is a library) that you should have added the definitions to.

And if some of your targets don’t link to the Main target either, then I guess the only alternative is to add the definitions “globally” with add_compile_definitions().

At least that is my understanding of what’s happening.

1 Like

Thank you! That worked.

Is there any way I can get this to work with the add_compile_definitions():

pico_set_linker_script(keyboard_firmware_left ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld)
target_link_libraries(keyboard_firmware_left PRIVATE Main)
pico_add_extra_outputs(keyboard_firmware_left)
# add_compile_definitions(LEFT)

add_executable(keyboard_firmware_right)
pico_set_linker_script(keyboard_firmware_right ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld)
target_link_libraries(keyboard_firmware_right PRIVATE Main)
pico_add_extra_outputs(keyboard_firmware_right)
# add_compile_definitions(RIGHT)