Closed cinderblock closed 1 year ago
I'm sure Graham will be along with the "proper" answer later, but in the meantime I wonder if any if the comments in #924 help? :man_shrugging:
So this compat.hpp is just needed for the fastled component? Most sdk libraries have a "_headers" version which should avoid your static lib compiling sdk source e.g. hardware_sync has a hardware_sync_headers library that adds the include paths (not that the develop branch has some improvements in this area) . As you've used PRIVATE I wouldn't expect that include compile option to be applied outside the static library. Is that not the case?
Unless you deliberately wanted to use a static lib (which from your description, you don't), you should use
add_library(FastLED INTERFACE
and
target_link_libraries(FastLED INTERFACE
There is some more detail on this here https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
As Peter says, we do have some better support for building static libraries in SDK1.5.0, but the cases you'd want to are pretty rare.
If he doesn't use a static library, every source file in the sdk will have compat.hpp included at the top?
oh - i guess i should read more closely - in all my years, i don't think i've ever noticed -include
anyhoo, yes you could therefore use _headers
versions for the target_link_libraries
Alternatively you could stick with INTERFACE, and do
set_source_files_properties(
FastLED/src/colorpalettes.cpp
FastLED/src/colorutils.cpp
FastLED/src/FastLED.cpp
FastLED/src/hsv2rgb.cpp
FastLED/src/platforms.cpp
PROPERTIES
COMPILE_FLAGS "-include ${CMAKE_CURRENT_SOURCE_DIR}/compat.hpp")
to just affect those files
Thank you all so much for the input! I have a couple things to try and these look quite promising! 😀
The _headers
option for target_link_libraries
seems like it is in line with my intent - however I'm not finding a clear example on how to use that...
While I'm here, some questions I can answer:
The INTERFACE
option (to add_library
and target_link_libraries
) is one I'm certainly confused about. CMake's documentation seems to assume I know more about the rest of how CMake works and I find it rather unclear. I think the intent is, as suggested, to just use the "interface" (aka header files) from those dependencies since the sources will be linked in at a higher level. But other include errors cropped up making me think I was using it wrong. I was thinking of building a "STATIC" library since I've created intermediate .a
files in other build chains in the past. Maybe CMake's expectations here don't quite line up with mine - based on comments here, "STATIC" is only for when your final output is a statically linkable library. I appreciate the clarification on this.
As for compat.hpp
, that is my own creation. The Pico support for FastLED seems to assume its in an Arduino environment where those functions are declared and defined. And since the Arduino environment injects the #include "Arduino.h"
above source files, FastLED expects somethings to have been declared "globally", so I created that tiny compatibility shim and need it included before their sources.
I think I prefer the set_source_files_properties method to avoid using a static library. Static libraries can quickly cause weird build issues without you realising (in my experience).
I agree that the CMake documentation about INTERFACE libraries is a bit confusing. Everything in the sdk is an INTERFACE library. I just think of them as instructions for building a final executable. So source files, compile definitions, include folders and other library dependencies etc are added to the the final executable. The upshot is when you compile your program, the whole sdk gets built. This can be a bit wasteful and it needs some care, e.g. to avoid header file name clashes but it's also quite powerful allowing you to configure the whole sdk how you want just by adding the right "link" libraries dependencies to your executable.
I've been playing with this a bunch. I've also updated to SDK 1.5.0 (am on master
actually. maybe I shouldn't)
The main thing that got me working was the set_source_files_properties(...)
option. This correctly applied those compiler args only to the source files that needed it. Thank you all very much for that suggestion.
Moving onto the INTERFACE
...
I found it builds mostly fine (more on this later) with or without STATIC
, PRIVATE
, or PUBLIC
. I can make the FastLED library STATIC
and it compiles and links as well. (I assumed STATIC
would make a libFastLED.a
as an intermediate file but that seems to be happening in my build logs no matter what I do).
However I cannot get INTERFACE
to work in any way as you suggest:
Unless you deliberately wanted to use a static lib (which from your description, you don't), you should use
add_library(FastLED INTERFACE
and
target_link_libraries(FastLED INTERFACE
[cmake] CMake Error at lib/FastLED/CMakeLists.txt:3 (add_library):
[cmake] add_library INTERFACE library requires no source arguments.
How do I define the sources of the library if not like this???
There is some more detail on this here https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
I see much talk of the SDK being an "INTERFACE
" library, but I guess I still don't understand what that means. The closest example in the pdf I saw to using INTERFACE
with add_library
is in Appendix B but I'm left with more questions than answers reading that.
Now, I've noticed something, that may be obvious to you all, likely caused by my misunderstanding of INTERFACE, but pico sources are getting built twice - in the FastLED library and for the main target.
To boot, while I can call some FastLED functions (FastLED.show()
), if I include the required FastLED.addleds<NEOPIXEL, 60>(...)
I get a confusing linker error:
[build] /tmp/cczzgpwT.s: Assembler messages:
[build] /tmp/cczzgpwT.s:812: Error: invalid offset, value too big (0x00000454)
The only place I've seen this is in #97 but I'm not using LTO... Maybe this is a symptom of building and linking some pico functions twice? And the linker is trying to reconcile the duplicates which breaks jumps because they're now too far??
Thanks for all the help. Please forgive any typos or confusing messages. It's late. Time for sleep. 🛌💤
How do I define the sources of the library if not like this???
In the version of cmake we're using, for an interface you have to add the sources in a separate line using target_sources, e.g. target_sources(NAMEOFTARGET INTERFACE ${CMAKE_CURRENT_LIST_DIR}/source.c etc) The gotcha is you have to include the full path of the source file.
Not really sure about your error - it looks like a build issue? Check what command is being called by passing VERBOSE=1 to make,
What do you mean by "version of cmake we're using"? Is this just fundamentally different in older versions?
Thank you for the suggestion. Curiously, I found that that the ${CMAKE_CURRENT_LIST_DIR}/
prefix in target_sources
was not required. (I've tried with an without throughout the following as well).
I've got everything as INTERFACE
now. I think this is making more sense.
However now I cannot get my -include
option in on just the source files that need it.
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/FastLED/src/colorpalettes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FastLED/src/colorutils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FastLED/src/FastLED.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FastLED/src/hsv2rgb.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FastLED/src/platforms.cpp
PROPERTIES
COMPILE_OPTIONS "-include compat.hpp")
I've tried CMAKE_CURRENT_LIST_DIR
instead of CMAKE_CURRENT_SOURCE_DIR
. I've tried without either. I've tried manually writing out the path relative to different levels of my various CMakeLists.txt files and build directories.
I've tried a bunch of other options too:
set_directory_properties(PROPERTIES COMPILE_OPTIONS "-include compat.hpp")
set_directory_properties(PROPERTIES COMPILE_FLAGS "-include compat.hpp")
add_compile_options(-include compat.hpp)
- Works on "current directory and below", right?target_compile_options(FastLED INTERFACE -include compat.hpp)
(again)I found this one kind of works, but applies to all source files, which causes other issues.
target_compile_options(FastLED INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-include compat.hpp>)
So I'm trying to write a generator expression to filter for only source files in a certain path, but I haven't gotten quite to that working...
target_compile_options(FastLED INTERFACE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<...>>:-include compat.hpp>)
Is there some other (easier) way to achieve the behavior (of -include
) that I want?
Is there some other (easier) way to achieve the behavior (of
-include
) that I want?
I was thinking about this a bunch and think I found an easier way.
I created a new FastLED.cpp
:
#include "compat.hpp"
#include "FastLED/src/colorpalettes.cpp"
#include "FastLED/src/colorutils.cpp"
#include "FastLED/src/FastLED.cpp"
#include "FastLED/src/hsv2rgb.cpp"
#include "FastLED/src/platforms.cpp"
I then tell CMake that is the only source file for this INTERFACE library and we're (basically) off to the races!
-include
not required!
The problem remains with this "Assembler messages" when compiling main.cpp
:
/usr/bin/arm-none-eabi-g++ -DLIB_CMSIS_CORE=1 -DLIB_PICO_BIT_OPS=1 -DLIB_PICO_BIT_OPS_PICO=1 -DLIB_PICO_DIVIDER=1 -DLIB_PICO_DIVIDER_HARDWARE=1 -DLIB_PICO_DOUBLE=1 -DLIB_PICO_DOUBLE_PICO=1 -DLIB_PICO_FLOAT=1 -DLIB_PICO_FLOAT_PICO=1 -DLIB_PICO_INT64_OPS=1 -DLIB_PICO_INT64_OPS_PICO=1 -DLIB_PICO_MALLOC=1 -DLIB_PICO_MEM_OPS=1 -DLIB_PICO_MEM_OPS_PICO=1 -DLIB_PICO_PLATFORM=1 -DLIB_PICO_PRINTF=1 -DLIB_PICO_PRINTF_PICO=1 -DLIB_PICO_RUNTIME=1 -DLIB_PICO_STANDARD_LINK=1 -DLIB_PICO_STDIO=1 -DLIB_PICO_STDIO_UART=1 -DLIB_PICO_STDLIB=1 -DLIB_PICO_SYNC=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_CMAKE_BUILD_TYPE=\"Release\" -DPICO_COPY_TO_RAM=0 -DPICO_CXX_ENABLE_EXCEPTIONS=0 -DPICO_NO_FLASH=0 -DPICO_NO_HARDWARE=0 -DPICO_ON_DEVICE=1 -DPICO_TARGET_NAME=\"my_executable\" -DPICO_USE_BLOCKED_RAM=0 -I../lib/SDK/src/common/pico_stdlib/include -I../lib/SDK/src/rp2_common/hardware_gpio/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_sync/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_uart/include -I../lib/SDK/src/rp2_common/hardware_resets/include -I../lib/SDK/src/rp2_common/hardware_clocks/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_divider/include -I../lib/SDK/src/rp2_common/pico_runtime/include -I../lib/SDK/src/rp2_common/pico_printf/include -I../lib/SDK/src/common/pico_bit_ops/include -I../lib/SDK/src/common/pico_divider/include -I../lib/SDK/src/rp2_common/pico_double/include -I../lib/SDK/src/rp2_common/pico_float/include -I../lib/SDK/src/rp2_common/pico_malloc/include -I../lib/SDK/src/rp2_common/pico_bootrom/include -I../lib/SDK/src/common/pico_binary_info/include -I../lib/SDK/src/rp2_common/pico_stdio/include -I../lib/SDK/src/rp2_common/pico_stdio_uart/include -I../lib/SDK/src/rp2_common/pico_int64_ops/include -I../lib/SDK/src/rp2_common/pico_mem_ops/include -I../lib/SDK/src/rp2_common/boot_stage2/include -I../lib/SDK/src/rp2_common/hardware_spi/include -I../lib/SDK/src/rp2_common/hardware_i2c/include -I../lib/FastLED/compat -I../lib/FastLED/FastLED/src -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 -mcpu=cortex-m0plus -mthumb -O3 -DNDEBUG -ffunction-sections -fdata-sections -fno-exceptions -fno-unwind-tables -fno-rtti -fno-use-cxa-atexit -MD -MT CMakeFiles/my_executable.dir/src/main.cpp.obj -MF CMakeFiles/my_executable.dir/src/main.cpp.obj.d -o CMakeFiles/my_executable.dir/src/main.cpp.obj -c ../src/main.cpp
/tmp/ccasthV7.s: Assembler messages:
/tmp/ccasthV7.s:812: Error: invalid offset, value too big (0x00000454)
I suspect this is a FastLED bug at this point. I'll probably start a new thread about getting this to work there. Until then I'm going to post my findings here. Any pointers would be greatly appreciated :)
Manually building with --save-temps
I can capture the intermediate assembly file that is generating the issues:
; ...
.syntax divided
@ 279 "../lib/FastLED/compat/../FastLED/src/platforms/arm/rp2040/../common/m0clockless.h" 1
loadleds3 ip, r4, #1 ,r3; loaddither7 r4, r5, r6, #1; dither5 r4, r5; scale4 r4, r6, #12, r3; adjdither7 r6,r5,#1,#4,r3; swapbbn1 r2, r4;
@ 0 "" 2
.thumb
.syntax unified
ldr r6, .L131 ; <------- Line 812: Error: invalid offset, value too big
movs r0, r2
str r6, [sp, #8]
ldr r6, [r6]
mov r2, ip
str r6, [sp]
b .L124
.L130:
cmp r1, #0
bne .LCB824
b .L129 @long jump
.LCB824:
.L124:
mov r10, r2
mov r7, r8
ldr r2, [sp, #4]
mov r6, r9
.syntax divided
; ...
Note:
/usr/bin/arm-none-eabi-g++ --version
arm-none-eabi-g++ (15:8-2019-q3-1+b1) 8.3.1 20190703 (release) [gcc-8-branch revision 273027]
What do you mean by "version of cmake we're using"?
Later versions of cmake allow you to add sources on the same line. I think you should continue this discussion on the forum.
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
:Unfortunately, since FastLED doesn't directly support CMake, I need to make my own
lib/FastLED/CMakeLists.txt
for it:I can select the sources I want in
add_library
. However they don't compile without also adding the showntarget_link_libraries
. This makes sense to me - CMake is using this information to tell the compiler where pico-sdk'sinclude
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: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:
That gets pretty far but breaks down at finding
version.h
, generated fromversion.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
: