[RESOLVED] C source code not finding paths to headers in Pico SDK or my library

EDIT: I made the library an INTERFACE and all is well now.

I went through Step 1 and Step 2 of the official tutorial to try to get my external Raspberry Pi Pico C/C++ SDK project working with a library I am creating that is a port of an Arduino library. The fine folks over at the Raspberry Pi Pico forums don’t seem to know enough about CMake to help me. The Pico is an ARM microcontroller created by Raspberry Pi, and they provided an SDK that uses CMake as the build system. It is obtained through github. Also required is the cross-compilation toolchain ARM GNU Toolchain. I am building the firmware files on an x86_64 machine running GNU/Linux Slackware 15.0 with CMake 3.21 from their package system. The Pico SDK is 1.5.1 and requires the setting of system (bash in my case) environmental variables that provide the paths to the SDK and ARM toolchain. Those variables are set up fine, and I can use CMake to set up build directories and build the Pico examples that come with CMake files.
The SDK is here GitHub - raspberrypi/pico-sdk
As I said, to better understand CMake, I went through the tutorial, especially adding a library. However, when I run make for one of my C programs that is an example that uses my library, it can’t find the Pico SDK. I’m not sure why the Pico examples work for me, but a stand-alone project does not. I used their master CMakelists.txt as a template.
Well, the tutorial didn’t help. My library source code can’t find the Pico SDK functions. I’ve been trying to add status messages and such using get_property and cmake_print_variables after include(CMakePrintHelpers) but still no luck.
Really, what I need to know, is a clear flowchart and methodology for debugging the CMake scripts. I understand debugging C, but not this.
I don’t understand why the path to the SDK functions work for the pico/examples but not for my project. I seem to be doing the same thing, but I guess not.
Did I break it by adding a target_include_directories() command to my example file?!

full directory and file listing except build, which I deleted. dirs have slashes behind them

bash shell:


breaker@ace:~/pico$ ls -R tmp117
tmp117: 1_temp_result/  2_alerts/  3_set_offset/  CMakeLists.txt  pico_sdk_import.cmake  src/  tmp117_examples.txt
tmp117/1_temp_result: CMakeLists.txt  temp_result.c
tmp117/2_alerts: CMakeLists.txt  alerts.c
tmp117/3_set_offset: CMakeLists.txt  set_offset.c
tmp117/src: CMakeLists.txt  tmp117.c  tmp117.h  tmp117_registers.h

This is /tmp117/CMakeLists.txt

# Minimum required CMake version
cmake_minimum_required(VERSION 3.21)
# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)
# include(CMakePrintHelpers)
project(tmp117_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")
    message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
# Initialize the SDK
pico_sdk_init()
add_compile_options(
        -Wall                # Enable most warning messages
        -Wno-format          # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
        -Wno-unused-function # we have some for the docs that aren't called
        )
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
   add_compile_options(-Wno-maybe-uninitialized)
endif()
# Add the src directory to the build
add_subdirectory(src)
# Add example subdirectories
add_subdirectory(1_temp_result)
add_subdirectory(2_alerts)
add_subdirectory(3_set_offset)

EDIT: MADE THIS INTERFACE This is /tmp117/src/CMakeLists.txt

# CMakeLists.txt in the src directory
# Define a library named 'tmp117_functions'
add_library(tmp117_functions INTERFACE
    tmp117.c
)

This is for the example code C program - /tmp117/1_temp_result/CMakeLists.txt

add_executable(temp_result
        temp_result.c
        )
# pull in common dependencies and additional i2c hardware support
target_link_libraries(temp_result PUBLIC tmp117_functions pico_stdlib hardware_i2c pico_printf)
# add include paths (binary dir not needed)
target_include_directories(temp_result PRIVATE ${PROJECT_SOURCE_DIR}/src)
# create map/bin/hex file etc.
pico_add_extra_outputs(temp_result)

EDIT: This was before I used INTERFACE, it works OK now. I ran cmake and got this output:

breaker@ace:~/pico/tmp117/build$ cd .. && rm -R build && mkdir build && cd build && cmake ..
Using PICO_SDK_PATH from environment ('/usr/src/pico-sdk')
PICO_SDK_PATH is /usr/src/pico-sdk
Defaulting PICO_PLATFORM to rp2040 since not specified.
Defaulting PICO platform compiler to pico_arm_gcc since not specified.
-- Defaulting build type to 'Release' since not specified.
PICO compiler is pico_arm_gcc
-- The C compiler identification is GNU 13.2.1
-- The CXX compiler identification is GNU 13.2.1
-- The ASM compiler identification is GNU
-- Found assembler: /usr/src/arm-gnu-toolchain/bin/arm-none-eabi-gcc
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/src/arm-gnu-toolchain/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: /usr/src/arm-gnu-toolchain/bin/arm-none-eabi-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Build type is Release
Defaulting PICO target board to pico since not specified.
Using board configuration from /usr/src/pico-sdk/src/boards/include/boards/pico.h
-- Found Python3: /usr/bin/python3.9 (found version "3.9.18") found components: Interpreter 
TinyUSB available at /usr/src/pico-sdk/lib/tinyusb/src/portable/raspberrypi/rp2040; enabling build support for USB.
BTstack available at /usr/src/pico-sdk/lib/btstack
cyw43-driver available at /usr/src/pico-sdk/lib/cyw43-driver
Pico W Bluetooth build support available.
lwIP available at /usr/src/pico-sdk/lib/lwip
mbedtls available at /usr/src/pico-sdk/lib/mbedtls
-- 1_temp_result
-- Interface include directory for temp_result: /home/breaker/pico/tmp117/build
-- Interface include directory for temp_result: /home/breaker/pico/tmp117/src
-- CMAKE_INCLUDE_PATH=""
-- root
-- Pico SDK path: /usr/src/pico-sdk
-- PROJECT_SOURCE_DIR="/home/breaker/pico/tmp117" ; PROJECT_BINARY_DIR="/home/breaker/pico/tmp117/build"
-- CMAKE_INCLUDE_PATH=""
-- Configuring done
-- Generating done
-- Build files have been written to: /home/breaker/pico/tmp117/build

Now to attempt to make the example

breaker@ace:~/pico/tmp117/build$ cd 1_temp_result && make
[  2%] Creating directories for 'ELF2UF2Build'
[  5%] No download step for 'ELF2UF2Build'
[  5%] No update step for 'ELF2UF2Build'
[  8%] No patch step for 'ELF2UF2Build'
[  8%] Performing configure step for 'ELF2UF2Build'
-- The C compiler identification is GNU 11.2.0
-- The CXX compiler identification is GNU 11.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - 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: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/breaker/pico/tmp117/build/elf2uf2
[ 10%] Performing build step for 'ELF2UF2Build'
[ 50%] Building CXX object CMakeFiles/elf2uf2.dir/main.cpp.o
[100%] Linking CXX executable elf2uf2
[100%] Built target elf2uf2
[ 10%] No install step for 'ELF2UF2Build'
[ 10%] Completed 'ELF2UF2Build'
[ 10%] Built target ELF2UF2Build
Scanning dependencies of target bs2_default
[ 10%] Building ASM object pico-sdk/src/rp2_common/boot_stage2/CMakeFiles/bs2_default.dir/compile_time_choice.S.obj
[ 13%] Linking ASM executable bs2_default.elf
[ 13%] Built target bs2_default
[ 16%] Generating bs2_default.bin
[ 18%] Generating bs2_default_padded_checksummed.S
[ 18%] Built target bs2_default_padded_checksummed_asm
[ 21%] Building C object src/CMakeFiles/tmp117_functions.dir/tmp117.c.obj
/home/breaker/pico/tmp117/src/tmp117.c:5:10: fatal error: hardware/i2c.h: No such file or directory
    5 | #include "hardware/i2c.h"
      |          ^~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [src/CMakeFiles/tmp117_functions.dir/build.make:76: src/CMakeFiles/tmp117_functions.dir/tmp117.c.obj] Error 1
make[1]: *** [CMakeFiles/Makefile2:1708: src/CMakeFiles/tmp117_functions.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

C Code snippet from the above referenced /home/breaker/pico/tmp117/src/tmp117.c

// tmp117.c
#include "tmp117.h"
#include "tmp117_registers.h"
#include "hardware/i2c.h"
#include "pico/printf.h"
#include "pico/stdlib.h"
#include "pico.h"

In their examples, the bottom 4 #includes are found, but not for my library source file, and my example can't find my library header either.

Thanks for any help!
EDIT: I got it working.

I got it working

I can imagine the look on the face of someone with the same problem who’d land here after struggling with it for hours/days :slight_smile:

Yes, thanks! I still am trying to fully understand scope, and the label INTERFACE and why that particular term is used, and what it exactly means.