Getting "not found" errors when using rgbled in C++ project

I have successfully installed the SDK and am able to build the entire pimoroni-pico project, including all the examples.

Now I wanted to start my own project, but run into compile issues, because the included files can’t find secondary header files.

I started with the “pico-boilerplate” project, which builds fine. But when I replace the source code of main.cpp with the code from the example interstate75_example.cpp, then it won’t compile.

I figured out that I need to add some includes to the CMakeLists.txt in my boilerplate project, which was difficult to figure out because there’s no instructions or examples - I only found this out in another post here in the forum. So I added:

include(drivers/hub75/hub75)
include(drivers/button/button)
include(drivers/rgbled/rgbled)

The first two includes work, but the 3rd throws an error:

In file included from /mydev/pimoroni-pico/libraries/interstate75/interstate75.hpp:5,
                 from /mydev/pico-boilerplate/main.cpp:2:
/mydev/pimoroni-pico/drivers/rgbled/rgbled.hpp:7:10: fatal error: hardware/pwm.h: No such file or directory
    7 | #include "hardware/pwm.h"
      |          ^~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/pico-boilerplate.dir/main.cpp.obj] Error 1

How do I resolve this?

The pwm.h file exists at:

/mydev/pico-sdk/src/rp2_common/hardware_pwm/include/hardware/pwm.h

I thought that all includes for the main pico SDK are automatically found.


For completeness, here’s the entire CMakeLists.txt content:

cmake_minimum_required(VERSION 3.12)

# Change your executable name to something creative!
set(NAME pico-boilerplate) # <-- Name your project/executable here!

include(pico_sdk_import.cmake)
include(pimoroni_pico_import.cmake)

# Gooey boilerplate
project(${NAME} C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Initialize the SDK
pico_sdk_init()

# Add your source files
add_executable(${NAME}
    main.cpp # <-- Add source files here!
)

# Include required libraries
# This assumes `pimoroni-pico` is stored alongside your project
#include(common/pimoroni_i2c)
#include(common/pimoroni_bus)
#include(libraries/bitmap_fonts/bitmap_fonts)
#include(libraries/hershey_fonts/hershey_fonts)
#include(libraries/pico_explorer/pico_explorer)

include(drivers/hub75/hub75)
include(drivers/button/button)
include(drivers/rgbled/rgbled)

# Don't forget to link the libraries you need!
target_link_libraries(${NAME}
#    pimoroni_i2c
#    pico_explorer # <-- List libraries here!
    pico_stdlib
    pico_multicore
    hardware_vreg
    hub75
    interstate75
)

# create map/bin/hex file etc.
pico_add_extra_outputs(${NAME})

# Set up files for the release packages
install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.uf2
    ${CMAKE_CURRENT_LIST_DIR}/README.md
    DESTINATION .
)

set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_GENERATOR "ZIP" "TGZ")
include(CPack)

CMake is a bit of an arcane art; this sounds … vaguely familiar.

You could try adding rgbled to your target_link_libraries (although logically it shouldn’t need it) - if that doesn’t work I’ll try spinning up a boilerplate and try to break it the same, so I can remember how I fixed it last time :)

I have figured it out eventually. What a pain. It’s guess work to figure out what’s needed. You’d think that CMake would figure out what’s used by looking at the source and create the needed includes and linked libs. That’s what smarter systems do, too (e.g. Xcode).

Here’s my working version:

cmake_minimum_required(VERSION 3.12)

# Name of executable.
set(NAME xcode-test)

# imports
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
include($ENV{PIMORONI_PICO_PATH}/pimoroni_pico_import.cmake)

# C/C++ boilerplate.
project(${NAME} C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Initialize the SDK
pico_sdk_init()

# Add all source files
add_executable(
	${NAME} main.cc
)

# Include required libraries
# This assumes `pimoroni-pico` is stored alongside your project
include(common/pimoroni_i2c)
include(common/pimoroni_bus)
#include(libraries/bitmap_fonts/bitmap_fonts)
#include(libraries/hershey_fonts/hershey_fonts)
#include(libraries/pico_explorer/pico_explorer)

include(drivers/hub75/hub75)
include(drivers/button/button)
include(drivers/rgbled/rgbled)
include(libraries/interstate75/interstate75)

# Libraries to link
target_link_libraries(${NAME}
	pimoroni_i2c
#	pico_explorer
	pico_stdlib
	pico_multicore
	hardware_vreg
	hub75
	interstate75
)

# enable usb output
pico_enable_stdio_usb(${NAME} 1)

# Create map/bin/hex/uf2 files 
pico_add_extra_outputs(${NAME})

# Set up files for the release packages
install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.uf2
    ${CMAKE_CURRENT_LIST_DIR}/README.md
    DESTINATION .
)

set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_GENERATOR "ZIP" "TGZ")
include(CPack)

CMake usually does a reasonable job of guessing where things are - from the fact that you’ve had to add various $PATH entries, am I right in guessing that your project isn’t sat next to the various SDKs?

The “convention” is that the pico-sdk and pimoroni-pico directories are in the same directory as your project:

/home/me/pico-development/pico-sdk
/home/me/pico-development/pimoroni-pico
/home/me/pico-development/my-amazing-app

If you have things laid out differently then yes, you’ll need to give it an extra helping hand.

That’s exactly how I layed out my directories. The issue with not with the paths but with the fact that the pimomoni sources refer to headers in a rather unspecific way - e.g. there’s multiple “hardware” dirs, and it depends on me using the right include in the cmake file to steer it into the right ones, apparently.

I just ran through sticking the interstate example into the boilerplate and it’s like I said - all you have to do is to add the driver libraries that you’ve included (hub75, button, rgbled) in the target_link_libraries as well as the includes.

The extra environment stuff shouldn’t be required if you’re following the ‘standard’ directory structures.

I do agree it’s a bit frustrating that you have to add things in two places, but once you’ve got used to that it’s generally fairly painless.

1 Like