Description
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) {};