79412892

Date: 2025-02-04 20:07:02
Score: 0.5
Natty:
Report link

I think I arrived at least at a partial understanding and solution to the question as stated (even if that, as such, is not enough to have the project compile with pico-sdk 2.1.0 and FreeRTOS-Kernel V11.1.0).

However, it is not an "easy" process - so I would appreciate if anyone can point me to something as easy as a one-liner target_link_libraries(lib PRIVATE pico_stdlib FreeRTOS-Kernel) - except, a one-liner which does not attempt to do linking.

Basically, we need to take a step back: if we want an OBJECT library, that means that simply we want to compile .o object files, and that means we do NOT want to link them (which is something you do for a final executable); so the most relevant things to for an OBJECT library is include directories and compile definitions (that is, the "one-liner" that I seek above should only copy include directories and compile definitions from pico_stdlib and FreeRTOS-Kernel library projects, it should not attempt to do linking).

So, we go back to just having target_link_libraries(my_project lib), which will cause compilation to fail with "fatal error: FreeRTOS.h: No such file or directory" - this is an include directory problem.

Then, having copied the CMake function print_target_properties() from https://stackoverflow.com/a/51987470/6197439 into the CMakeLists.txt file, we can inspect the FreeRTOS-Kernel library project by adding print_target_properties(FreeRTOS-Kernel) to the CMakeLists.txt file, which will pring:

FreeRTOS-Kernel IMPORTED = FALSE
FreeRTOS-Kernel IMPORTED_GLOBAL = FALSE
FreeRTOS-Kernel INTERFACE_COMPILE_DEFINITIONS = LIB_FREERTOS_KERNEL=1;FREE_RTOS_KERNEL_SMP=1
FreeRTOS-Kernel INTERFACE_INCLUDE_DIRECTORIES = C:/src/rp2040_pico/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include
FreeRTOS-Kernel INTERFACE_LINK_LIBRARIES = FreeRTOS-Kernel-Core;pico_base_headers;hardware_clocks;hardware_exception;pico_multicore
FreeRTOS-Kernel INTERFACE_SOURCES = C:/src/rp2040_pico/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/port.c
FreeRTOS-Kernel NAME = FreeRTOS-Kernel
FreeRTOS-Kernel TYPE = INTERFACE_LIBRARY

Notably, none of its properties (not even INTERFACE_INCLUDE_DIRECTORIES) contain the include directory for FreeRTOS.h - however, we can see in INTERFACE_LINK_LIBRARIES that it "depends" on another library project, FreeRTOS-Kernel-Core; we can also inspect that one by adding print_target_properties(FreeRTOS-Kernel-Core) to the CMakeLists.txt file, which will print:

FreeRTOS-Kernel-Core IMPORTED = FALSE
FreeRTOS-Kernel-Core IMPORTED_GLOBAL = FALSE
FreeRTOS-Kernel-Core INTERFACE_COMPILE_DEFINITIONS = PICO_CONFIG_RTOS_ADAPTER_HEADER=C:/src/rp2040_pico/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/freertos_sdk_config.h
FreeRTOS-Kernel-Core INTERFACE_INCLUDE_DIRECTORIES = C:/src/rp2040_pico/FreeRTOS-Kernel/include
FreeRTOS-Kernel-Core INTERFACE_SOURCES = C:/src/rp2040_pico/FreeRTOS-Kernel/croutine.c;C:/src/rp2040_pico/FreeRTOS-Kernel/event_groups.c;C:/src/rp2040_pico/FreeRTOS-Kernel/list.c;C:/src/rp2040_pico/FreeRTOS-Kernel/queue.c;C:/src/rp2040_pico/FreeRTOS-Kernel/stream_buffer.c;C:/src/rp2040_pico/FreeRTOS-Kernel/tasks.c;C:/src/rp2040_pico/FreeRTOS-Kernel/timers.c
FreeRTOS-Kernel-Core NAME = FreeRTOS-Kernel-Core
FreeRTOS-Kernel-Core TYPE = INTERFACE_LIBRARY

This is now something else, because the INTERFACE_INCLUDE_DIRECTORIES of FreeRTOS-Kernel-Core is in fact the include directory to FreeRTOS.h - we just need to propagate it somehow to our OBJECT library. We can do that by first reading it into a CMake variable, let's call it FRKCincl, with:

get_target_property(FRKCincl FreeRTOS-Kernel-Core INTERFACE_INCLUDE_DIRECTORIES) # "FreeRTOS.h"

... and then we can apply it to our OBJECT library with:

set_target_properties(lib PROPERTIES
  INCLUDE_DIRECTORIES ${FRKCincl}
)

When we run make next time, CMake will be triggered, and the compilation will not fail anymore at FreeRTOS.h, but instead at "portmacro.h". Following the same logic, I arrived at this:

target_link_libraries(my_project lib)

get_target_property(FRKCincl FreeRTOS-Kernel-Core INTERFACE_INCLUDE_DIRECTORIES) # "FreeRTOS.h"
get_target_property(FRKincl FreeRTOS-Kernel INTERFACE_INCLUDE_DIRECTORIES) # "portmacro.h"
# PICO_BOARD_HEADER_DIRS for "pico.h"
get_target_property(PSHSincl hardware_sync_headers INTERFACE_INCLUDE_DIRECTORIES) # "hardware/sync.h"
get_target_property(PSHBincl hardware_base_headers INTERFACE_INCLUDE_DIRECTORIES) # "hardware/address_mapped.h"
get_target_property(PSHRincl hardware_regs_headers INTERFACE_INCLUDE_DIRECTORIES) # "hardware/regs/addressmap.h"

set_target_properties(lib PROPERTIES
  INCLUDE_DIRECTORIES "${FRKCincl};${FRKincl};${PICO_BOARD_HEADER_DIRS};${PSHSincl};${PSHBincl};${PSHRincl}"
)

## printouts of properties

message("-------------")
print_target_properties(my_project)
message("-------------")
print_target_properties(pico_stdlib)
message("-------------")
print_target_properties(hardware_sync)
print_target_properties(hardware_sync_headers)
message("-------------")
print_target_properties(hardware_base)
print_target_properties(hardware_base_headers)
message("-------------")
print_target_properties(hardware_regs)
print_target_properties(hardware_regs_headers)
message("-------------")
print_target_properties(FreeRTOS-Kernel)
message("-------------")
print_target_properties(FreeRTOS-Kernel-Core)
message("-------------")
print_target_properties(lib)
message("-------------")

... and this ultimately starts failing at:

C:/src/rp2040_pico/pico-sdk/src/rp2_common/hardware_base/include/hardware/address_mapped.h:135:15: error: expected ';' before 'static'
  135 | __force_inline static void hw_set_bits(io_rw_32 *addr, uint32_t mask) {
      |               ^~~~~~~
      |               ;

... which unfortunately cannot be solved easily with the above approach (has something to do with peculiarity of pico_platform library, cannot yet figure out what).

Which is why, ultimately, it would have been great if there was something like target_link_libraries, but which only copies include directories and compile definitions (note, I've tried using INTERFACE in target_link_libraries, could not get it to work / compile to the end).

Reasons:
  • Blacklisted phrase (1): stackoverflow
  • Blacklisted phrase (1.5): would appreciate
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • High reputation (-1):
Posted by: sdbbs