technyon / Arduino-CMake-Toolchain

CMake toolchain for all Arduino compatible boards
MIT License
19 stars 7 forks source link

Compile problems with the philhower RP2040 core #3

Open myklemykle opened 2 months ago

myklemykle commented 2 months ago

Hi, i'm importing my issue from the upstream fork to here ... basically I'm wishing I could get this toolchain working for the RP2040 core I'm using. The readme suggests that it's known to work on ESP32 and could in theory work with any other Arduino core. But if that's not even your goal, then I won't pursue this any further.

At the moment I'm not able to compile all of the examples, though I can compile some of them. The issues seem to be due to various components of the RP2040 core not being found.

This is my cmake command:

% mkdir build
% cd build
% cmake -D CMAKE_TOOLCHAIN_FILE=../Arduino-toolchain.cmake -DARDUINO_INSTALL_PATH=/Applications/Arduino\ +\ Teensy\ 1.8.16.app/Contents/Java -DARDUINO_SKETCHBOOK_PATH=$HOME/Documents/Arduino ../Examples
/Applications/Arduino + Teensy 1.8.16.app/Contents/Java
-- Found Arduino Platform: /Applications/Arduino + Teensy 1.8.16.app/Contents/Java/hardware/arduino/avr
-- Found Arduino Platform: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2
-- Found Arduino Platform: /Volumes/External/mykle/Library/Arduino15/packages/teensy/hardware/avr/1.59.0
-- Selected Arduino Board: Generic RP2040 [rp2040.generic]
-- Selected board option: "Flash Size" = "2MB (no FS)"
-- Selected board option: "CPU Speed" = "133 MHz"
-- Selected board option: "Optimize" = "Small (-Os) (standard)"
-- Selected board option: "RTTI" = "Disabled"
-- Selected board option: "Stack Protector" = "Disabled"
-- Selected board option: "C++ Exceptions" = "Disabled"
-- Selected board option: "Debug Port" = "Disabled"
-- Selected board option: "Debug Level" = "None"
-- Selected board option: "USB Stack" = "Adafruit TinyUSB"
-- Selected board option: "IP/Bluetooth Stack" = "IPv4 Only"
-- Selected board option: "Boot Stage 2" = "Generic SPI /2"
-- Selected board option: "Upload Method" = "Default (UF2)"
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/arm-none-eabi-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/arm-none-eabi-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Arduino Library EEPROM: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/EEPROM
-- Found Arduino Library Adafruit_TinyUSB: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/Adafruit_TinyUSB_Arduino
-- Found Arduino Library SPI: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/SPI
-- Found Arduino Library SdFat: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/ESP8266SdFat
-- Found Arduino Library USB: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/Adafruit_TinyUSB_Arduino
-- Found Arduino Library Stepper: /Volumes/External/mykle/Documents/Arduino/libraries/Stepper
-- Found Arduino Library local_lib: /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/02_arduino_lib/libraries/local_lib
-- Found Arduino Library Wire: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/Wire
-- Found Arduino Library SD: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/SD
-- Found Arduino Library FS: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/LittleFS
-- Found Arduino Library SDFS: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/SDFS
-- Found Arduino Library LittleFS: /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/LittleFS
-- Configuring done
-- Generating done
-- Build files have been written to: /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build

The options all appear correct to me.

The first problem I get when trying to make any of the targets is that the final link step fails, with this sort of error:

[100%] Linking CXX executable arduino_lib.elf
Executing recipe.hooks.linking.prelink.1.pattern hook
Executing recipe.hooks.linking.prelink.2.pattern hook
/Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/ld: cannot open linker script file /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/memmap_default.ld: No such file or directory
collect2: error: ld returned 1 exit status
make[3]: *** [02_arduino_lib/arduino_lib.elf] Error 1
make[2]: *** [02_arduino_lib/CMakeFiles/arduino_lib.dir/all] Error 2
make[1]: *** [02_arduino_lib/CMakeFiles/arduino_lib.dir/rule] Error 2
make: *** [arduino_lib] Error 2

The build is looking for memmap_default.ld in the wrong place. It gets built, but it's in the example subdirectory, one directory under the main build directory where the build is searching. If I link that file from where it was built to where the build is searching, then I see the same problem with another file, boot2.o. If i link that file as well, then some of the examples finally appear to build correctly.

However I still can't build hello_world, because of another linker error:

[ 93%] Built target _arduino_lib_core
[ 93%] Linking CXX executable hello_world.elf
Executing recipe.hooks.linking.prelink.1.pattern hook
Executing recipe.hooks.linking.prelink.2.pattern hook
/Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/ld: CMakeFiles/hello_world.dir/hello_world.cpp.o: in function `setup':
/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/01_hello_world/hello_world.cpp:7: undefined reference to `_ZN17Adafruit_USBD_CDC5beginEm'
/Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/ld: /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/01_hello_world/hello_world.cpp:16: undefined reference to `Serial'
collect2: error: ld returned 1 exit status
make[3]: *** [01_hello_world/hello_world.elf] Error 1
make[2]: *** [01_hello_world/CMakeFiles/hello_world.dir/all] Error 2
make[1]: *** [01_hello_world/CMakeFiles/hello_world.dir/rule] Error 2
make: *** [hello_world] Error 2

This looks to me like the linker is not finding the compiled Adafruit_TinyUSB classes. (_ZN17Adafruit_USBD_CDC5beginEm looks to me like a GCC-encoded method name.) I'm not sure if it intends to be looking for the version included with the examples in 02_arduino_lib (which do appear to build correctly) or whether it's trying to find the version provided with the RP2040 core (which cmake found OK, as logged above.)

So all of this seems to come down to link-stage errors. Maybe the linker, or the compiler that calls it, needs to be provided with more library paths? I'm really not sure how to debug this further because it's running into the border between the cmake package and the rp2040 core & I don't know which side is responsible for these compiler invocations.

Any help would be much appreciated!

myklemykle commented 2 months ago

ArduinoSystem.cmake is one of the generated cmake files, and it's got the wrong locations hardcoded for bothmemmap_default.ld and boot2.o . In both cases it's looking for these files in the main build directory, but they're being created in one (or more) of the example subdirectories. Is that a cmake bug?

Also, when i run make VERBOSE=1 i see the -L flag being passed to gcc specifies the top-level build directory, but the libraries are being built in the 02_arduino_libs subdirectory. Is gcc supposed to do a recursive search under library paths?

Nevertheless, even after I linked every single .a file from the subdirectories into the main build directory, I still get that same error about a missing symbol:

mykle@viv ~/Documents/tmp/Arduino-CMake-Toolchain/Examples_build ±master⚡ » make hello_world VERBOSE=1                                                                                                                                  130 ↵
/opt/local/bin/cmake -S/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples -B/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build --check-build-system CMakeFiles/Makefile.cmake 0
/Library/Developer/CommandLineTools/usr/bin/make  -f CMakeFiles/Makefile2 hello_world
/opt/local/bin/cmake -S/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples -B/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build --check-build-system CMakeFiles/Makefile.cmake 0
/opt/local/bin/cmake -E cmake_progress_start /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/CMakeFiles 16
/Library/Developer/CommandLineTools/usr/bin/make  -f CMakeFiles/Makefile2 01_hello_world/CMakeFiles/hello_world.dir/all
/Library/Developer/CommandLineTools/usr/bin/make  -f 01_hello_world/CMakeFiles/_arduino_lib_core.dir/build.make 01_hello_world/CMakeFiles/_arduino_lib_core.dir/depend
cd /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build && /opt/local/bin/cmake -E cmake_depends "Unix Makefiles" /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/01_hello_world /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world/CMakeFiles/_arduino_lib_core.dir/DependInfo.cmake --color=
/Library/Developer/CommandLineTools/usr/bin/make  -f 01_hello_world/CMakeFiles/_arduino_lib_core.dir/build.make 01_hello_world/CMakeFiles/_arduino_lib_core.dir/build
make[3]: Nothing to be done for `01_hello_world/CMakeFiles/_arduino_lib_core.dir/build'.
[ 93%] Built target _arduino_lib_core
/Library/Developer/CommandLineTools/usr/bin/make  -f 01_hello_world/CMakeFiles/hello_world.dir/build.make 01_hello_world/CMakeFiles/hello_world.dir/depend
cd /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build && /opt/local/bin/cmake -E cmake_depends "Unix Makefiles" /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/01_hello_world /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world/CMakeFiles/hello_world.dir/DependInfo.cmake --color=
/Library/Developer/CommandLineTools/usr/bin/make  -f 01_hello_world/CMakeFiles/hello_world.dir/build.make 01_hello_world/CMakeFiles/hello_world.dir/build
[ 93%] Linking CXX executable hello_world.elf
Executing recipe.hooks.linking.prelink.1.pattern hook
cd /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world && /Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-python3/1.0.1-base-3a57aed/python3 -I /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/tools/simplesub.py --input /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/lib/memmap_default.ld --out /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world/memmap_default.ld --sub __FLASH_LENGTH__ 2093056 --sub __EEPROM_START__ 270528512 --sub __FS_START__ 270528512 --sub __FS_END__ 270528512 --sub __RAM_LENGTH__ 256k
Executing recipe.hooks.linking.prelink.2.pattern hook
cd /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world && /Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/arm-none-eabi-gcc -Werror=return-type -Wno-psabi -DUSE_TINYUSB -I/Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/Adafruit_TinyUSB_Arduino/src/arduino -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DUSBD_PID=0xf00a -DUSBD_VID=0x2e8a -DUSBD_MAX_POWER_MA=250 -DUSB_MANUFACTURER=\"Generic\" -DUSB_PRODUCT=\"RP2040\" -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_LWIP=1 -DLWIP_IPV6=0 -DLWIP_IPV4=1 -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1 -DARDUINO_VARIANT=\"generic\" -DTARGET_RP2040 -DPICO_FLASH_SIZE_BYTES=2097152 -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections -fno-exceptions -DARM_MATH_CM0_FAMILY -DARM_MATH_CM0_PLUS -Os -u _printf_float -u _scanf_float -c /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/boot2/boot2_generic_03h_2_padded_checksum.S -I/Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/pico-sdk/src/rp2040/hardware_regs/include/ -I/Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/pico-sdk/src/common/pico_binary_info/include -o /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world/boot2.o
cd /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/01_hello_world && /opt/local/bin/cmake -E cmake_link_script CMakeFiles/hello_world.dir/link.txt --verbose=1
/Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/arm-none-eabi-g++  -L/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build -Werror=return-type -Wno-psabi  -DUSE_TINYUSB -I/Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/libraries/Adafruit_TinyUSB_Arduino/src/arduino -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DUSBD_PID=0xf00a -DUSBD_VID=0x2e8a -DUSBD_MAX_POWER_MA=250 "-DUSB_MANUFACTURER=\"Generic\"" "-DUSB_PRODUCT=\"RP2040\"" -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_LWIP=1 -DLWIP_IPV6=0 -DLWIP_IPV4=1 -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1 "-DARDUINO_VARIANT=\"generic\"" -DTARGET_RP2040 -DPICO_FLASH_SIZE_BYTES=2097152 -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections -fno-exceptions  -DARM_MATH_CM0_FAMILY -DARM_MATH_CM0_PLUS  -Os -u _printf_float -u _scanf_float  @/Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/lib/platform_wrap.txt -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--script=/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/memmap_default.ld -Wl,-Map,/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/hello_world.map -o hello_world.elf -Wl,--no-warn-rwx-segments -Wl,--start-group CMakeFiles/hello_world.dir/hello_world.cpp.o  lib_arduino_lib_core.a   /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples_build/boot2.o /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/lib/ota.o  /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/lib/libpico.a /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/lib/libpicow-noipv6-nobtc-noble.a  /Volumes/External/mykle/Library/Arduino15/packages/rp2040/hardware/rp2040/3.7.2/lib/libbearssl.a -lm -lc -lstdc++ -lc -Wl,--end-group
/Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/ld: CMakeFiles/hello_world.dir/hello_world.cpp.o: in function `setup':
/Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/01_hello_world/hello_world.cpp:7: undefined reference to `_ZN17Adafruit_USBD_CDC5beginEm'
/Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/ld: /Volumes/External/mykle/Documents/tmp/Arduino-CMake-Toolchain/Examples/01_hello_world/hello_world.cpp:16: undefined reference to `Serial'
collect2: error: ld returned 1 exit status
make[3]: *** [01_hello_world/hello_world.elf] Error 1
make[2]: *** [01_hello_world/CMakeFiles/hello_world.dir/all] Error 2
make[1]: *** [01_hello_world/CMakeFiles/hello_world.dir/rule] Error 2
make: *** [hello_world] Error 2

In this case, I symlinked lib_arduino_lib_Adafruit_TinyUSB.a into the Examples_build directory, and I confirmed it does contain the missing symbol _ZN17Adafruit_USBD_CDC5beginEm. But still the linker is not finding it. I don't get it.

The thing is, it seems like this stuff would be just as wrong for the ESP32 core as for the RP2040 core. The examples are in subdirectories either way. But the docs in this repo say that ESP32 compiles work? Can you confirm?

I wonder if this is because I'm using a different version of g++? It's /Volumes/External/mykle/Library/Arduino15/packages/rp2040/tools/pqt-gcc/2.2.0-d04e724/bin/arm-none-eabi-g++ which is GCC 12.3.0. What version does the ESP32 core use?

myklemykle commented 2 months ago

I'm sorry that I don't have a quicker grasp of the build tools involved here (I was conflating the gcc meanings of -L and -l) but basically I have figured out how to get this to compile:

There is a generated file, 01_hello_world/CMakeFiles/hello_world.dir/link.txt . I don't know what part of the cmake process generates it. It contains the g++ command that's failing. The failure is because the compiler doesn't find the Adafruit TinyUSB library.

The thing is, I'm not sure whether it's expecting to find the version of Adafruit_TinyUSB that's included with the RP2040 core or the version that's included with the examples. What is the intention of the example? At any rate, there's no -l flag on the compilation line to actually include that library.

If I first copy the library from 01_hello_world/lib_arduino_lib_core.a to ./libTinyUSB.a and then add -lTinyUSB to the command in that link.txt file, then the hello_world example compiles.

Is there any kind of doc or map that explains the genesis of the various generated build files? How do we trace these errors upstream to a source? I guess I don't understand cmake too deeply, but every cmake tutorial example I've looked at is way less complicated than what's going on here.

myklemykle commented 2 months ago

Continuing the odyssey in these comments here as I bang my head against the problem ...

These compile commands come out of Arduino build properties that are "recipies." and the one that is failing comes from the build property recipe.c.combine.pattern. That recipe has a variable {object_files} that is meant to be replaced with the correct locations of all the object files to link, and cmake is injecting its internally-generated list of libraries (LINK_LIBRARIES) which is exactly what's wrong. Somehow its auto-detection of necessary Arduino libraries is incorrect. I guess I knew that, but now I'm even more sure. =)

myklemykle commented 2 months ago

Update: I have found that even though I'm having trouble getting the examples in this repo to compile, I have gotten it to work in another repo of mine; all the libraries were found, and used, and compilation was successful without any tweaking necessary. I don't get why it's these examples in particular that give me trouble.