Skip to content

How to use CMake functionality with other libraries that depend on SDK #1234

Closed
@cinderblock

Description

@cinderblock

I've got a basic simple program working with the SDK. I'm trying to add FastLED to control a string of pixels. I'm a little new to CMake so maybe I'm doing something silly, but I'm pretty familiar with other build chains so I know what needs to happen high level.

My CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)

include(lib/SDK/pico_sdk_init.cmake)

project(my_project)

# initialize the Raspberry Pi Pico SDK
pico_sdk_init()

add_executable(my_executable
    src/main.cpp
)

# Add pico_stdlib library which aggregates commonly used features
target_link_libraries(my_executable PUBLIC
    pico_stdlib
    hardware_spi
    hardware_i2c

    # hardware_sync
    # hardware_gpio
    # hardware_clocks
    # hardware_dma
    # hardware_pio
    # cmsis_core
    # pico_malloc
    # pico_time

    FastLED
)

add_subdirectory(lib/FastLED)

# create map/bin/hex/uf2 file in addition to ELF.
pico_add_extra_outputs(my_executable)

Unfortunately, since FastLED doesn't directly support CMake, I need to make my own lib/FastLED/CMakeLists.txt for it:

add_library(FastLED STATIC
    FastLED/src/colorpalettes.cpp
    FastLED/src/colorutils.cpp
    FastLED/src/FastLED.cpp
    FastLED/src/hsv2rgb.cpp
    FastLED/src/platforms.cpp
)
target_link_libraries(FastLED PRIVATE
    hardware_sync
    hardware_gpio
    hardware_clocks
    hardware_dma
    hardware_pio
    cmsis_core
    pico_malloc
    pico_time
)
# include `compat.hpp` when building all FastLED sources (replaces `Arduino.h`)
target_compile_options(FastLED PRIVATE -include ${CMAKE_CURRENT_SOURCE_DIR}/compat.hpp)

I can select the sources I want in add_library. However they don't compile without also adding the shown target_link_libraries. This makes sense to me - CMake is using this information to tell the compiler where pico-sdk's include directories are and we can build from there.

The problem that comes up is that these dependencies are then built with the extra target_compile_options which breaks the compilation, notably of pico-sdk's Assembly sources:

[build] FAILED: lib/FastLED/CMakeFiles/FastLED.dir/__/SDK/src/rp2_common/hardware_irq/irq_handler_chain.S.obj 
[build] /usr/bin/arm-none-eabi-gcc -DLIB_CMSIS_CORE=1 -DLIB_PICO_MALLOC=1 -DLIB_PICO_PLATFORM=1 -DLIB_PICO_SYNC=1 -DLIB_PICO_SYNC_CORE=1 -DLIB_PICO_SYNC_CRITICAL_SECTION=1 -DLIB_PICO_SYNC_MUTEX=1 -DLIB_PICO_SYNC_SEM=1 -DLIB_PICO_TIME=1 -DLIB_PICO_UTIL=1 -DPICO_BOARD=\"pico\" -DPICO_BUILD=1 -DPICO_NO_HARDWARE=0 -DPICO_ON_DEVICE=1 -I../lib/SDK/src/rp2_common/hardware_sync/include -I../lib/SDK/src/common/pico_base/include -Igenerated/pico_base -I../lib/SDK/src/boards/include -I../lib/SDK/src/rp2_common/pico_platform/include -I../lib/SDK/src/rp2040/hardware_regs/include -I../lib/SDK/src/rp2_common/hardware_base/include -I../lib/SDK/src/rp2040/hardware_structs/include -I../lib/SDK/src/rp2_common/hardware_claim/include -I../lib/SDK/src/rp2_common/hardware_gpio/include -I../lib/SDK/src/rp2_common/hardware_irq/include -I../lib/SDK/src/common/pico_sync/include -I../lib/SDK/src/common/pico_time/include -I../lib/SDK/src/rp2_common/hardware_timer/include -I../lib/SDK/src/common/pico_util/include -I../lib/SDK/src/rp2_common/hardware_clocks/include -I../lib/SDK/src/rp2_common/hardware_resets/include -I../lib/SDK/src/rp2_common/hardware_pll/include -I../lib/SDK/src/rp2_common/hardware_vreg/include -I../lib/SDK/src/rp2_common/hardware_watchdog/include -I../lib/SDK/src/rp2_common/hardware_xosc/include -I../lib/SDK/src/rp2_common/hardware_dma/include -I../lib/SDK/src/rp2_common/hardware_pio/include -I../lib/SDK/src/rp2_common/cmsis/stub/CMSIS/Core/Include -I../lib/SDK/src/rp2_common/cmsis/stub/CMSIS/Device/RaspberryPi/RP2040/Include -I../lib/SDK/src/rp2_common/pico_malloc/include -mcpu=cortex-m0plus -mthumb -Og -g -include /home/pi/pico/lib/FastLED/compat.hpp -o lib/FastLED/CMakeFiles/FastLED.dir/__/SDK/src/rp2_common/hardware_irq/irq_handler_chain.S.obj   -c ../lib/SDK/src/rp2_common/hardware_irq/irq_handler_chain.S
[build] /usr/lib/gcc/arm-none-eabi/8.3.1/include/stddef.h: Assembler messages:
[build] /usr/lib/gcc/arm-none-eabi/8.3.1/include/stddef.h:216: Error: bad instruction `typedef unsigned int size_t'
[build] /usr/lib/gcc/arm-none-eabi/8.3.1/include/stddef.h:328: Error: bad instruction `typedef unsigned int wchar_t'
[build] /usr/lib/gcc/arm-none-eabi/8.3.1/include/stddef.h:149: Error: bad instruction `typedef int ptrdiff_t'
[build] /usr/lib/gcc/arm-none-eabi/8.3.1/include/stddef.h:357: Error: bad instruction `typedef unsigned int wint_t'
...

I thought by specifying the libraries at the top level it would force them to be compiled there with those options. It seems they do, but don't replace the similar compilation in the dependency.

I suspect I'm missing some simple option that means just "get the include directories of these dependencies". But I've tried many permutations of target_link_libraries's (and other functions') options to no avail.

I've even tried manually specifying the include directories that are missing with something like:

target_include_directories(FastLED PRIVATE
    ../SDK/src/rp2_common/hardware_sync/include
    ../SDK/src/rp2_common/hardware_gpio/include
    ../SDK/src/rp2_common/hardware_clocks/include
    ../SDK/src/rp2_common/hardware_dma/include
    ../SDK/src/rp2_common/hardware_pio/include
    ../SDK/src/rp2_common/cmsis_core/include
    ../SDK/src/rp2_common/pico_malloc/include
    ../SDK/src/common/pico_time/include
    ../SDK/src/common/pico_base/include
)

That gets pretty far but breaks down at finding version.h, generated from version.h.in.

I've looked through the SDK documentation and examples but rarely found more detail on the pico sdk/cmake expects me to tell it what it needs to know. Any thoughts on moving forward here would be greatly appreciated.

For completeness compat.hpp:

#include <stdlib.h>
#include "pico/time.h"
#include "RP2040.h"

// FastLED tests for this to enable RP2040 code
#define ARDUINO_ARCH_RP2040

static inline uint32_t micros(void) { return to_us_since_boot(get_absolute_time()); }
static inline uint32_t millis(void) { return to_ms_since_boot(get_absolute_time()); }
static inline void yield(void) {};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions