breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

[RESOLVED] project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 8:18 am

OK, I tried, I really did. Five hours later, I need help. Basically I have C header and C source files to be used by multiple examples, but I don't know how to make cmake play nice with my created "library" yet also use the SDK. It can't find the path to the SDK the way I do it. I can make it work if my headers are in the same directory as my examples, but not if they are somewhere else. Let me explain by showing some outputs.

Code: Select all

breaker@ace:~/pico/tmp117$ echo $PICO_SDK_PATH
/usr/src/pico-sdk

breaker@ace:~/pico/tmp117$ pwd
/home/breaker/pico/tmp117

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

./1_temp_result:
CMakeLists.txt  TMP117_Registers.h  temp_result.c

./2_alerts:
CMakeLists.txt  alerts.c

./3_set_offset:
CMakeLists.txt  set_offset.c

./src:
CMakeLists.txt  tmp117.c  tmp117.h  tmp117_registers.h
My main project CMakeLists.txt

Code: Select all

breaker@ace:~/pico/tmp117$ cat ./CMakeLists.txt

# Minimum required CMake version
cmake_minimum_required(VERSION 3.21)

# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

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 the src directory to include directories
include_directories(${PROJECT_SOURCE_DIR}/src)

message(STATUS "Include Directories: ${CMAKE_INCLUDE_PATH}")

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)
CMakeLists.txt in my $PWD/src

Code: Select all

breaker@ace:~/pico/tmp117$ cat ./src/CMakeLists.txt
# CMakeLists.txt in the src directory

# Define a library named 'tmp117'
add_library(tmp117
    tmp117.c
    tmp117.h
    tmp117_registers.h
)
# Add the include directory to the library
# target_include_directories(tmp117 PUBLIC ${PROJECT_SOURCE_DIR}/src)
I tried both doing target_include_directories in the src CMakeLists.txt or putting it in the main one, but that's not the issue.
When I run make it can't find the #includes in this C file called by my header:

Code: Select all

// src/tmp117.c

#include "tmp117.h"
#include "tmp117_registers.h"
#include "hardware/i2c.h" // failure to find this and below
#include "pico/printf.h"
#include "pico/stdlib.h"
#include "pico.h"

// function definitions
// SNIP
cmake output:

Code: Select all

breaker@ace:~/pico/tmp117$ mkdir build
breaker@ace:~/pico/tmp117$ cd build
breaker@ace:~/pico/tmp117/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
-- Include Directories: 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/breaker/pico/tmp117/build
Now to build an example:

Code: Select all

breaker@ace:~/pico/tmp117/build$ ls
1_temp_result/  3_set_offset/   CMakeDoxyfile.in            CMakeFiles/  cmake_install.cmake  generated/  pioasm/
2_alerts/       CMakeCache.txt  CMakeDoxygenDefaults.cmake  Makefile     elf2uf2/             pico-sdk/   src/
breaker@ace:~/pico/tmp117/build$ cd 2_alerts
breaker@ace:~/pico/tmp117/build/2_alerts$ make
[  2%] Creating directories for 'ELF2UF2Build'
[  5%] No download step for 'ELF2UF2Build'
[  5%] No update step for 'ELF2UF2Build'
[  7%] No patch step for 'ELF2UF2Build'
[  7%] 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
[ 15%] 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.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.dir/build.make:76: src/CMakeFiles/tmp117.dir/tmp117.c.obj] Error 1
make[1]: *** [CMakeFiles/Makefile2:1708: src/CMakeFiles/tmp117.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
flags

Code: Select all

breaker@ace:~/pico/tmp117/build$ cat src/CMakeFiles/tmp117.dir/flags.make
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.21

# compile C with /usr/src/arm-gnu-toolchain/bin/arm-none-eabi-gcc
C_DEFINES = 

C_INCLUDES = -I/home/breaker/pico/tmp117/src

C_FLAGS = -mcpu=cortex-m0plus -mthumb -O3 -DNDEBUG -Wall -Wno-format -Wno-unused-function -Wno-maybe-uninitialized -std=gnu11

Where are the SDK Includes, shouldn't they be listed above?

In case it matters my tmp117.h partially:

Code: Select all

// tmp117.h

#ifndef TMP117_H
#define TMP117_H

#include <stdint.h>
#include <stdbool.h>

// definitions, function prototypes, external variables

#endif  // TMP117_H
I just realized as I am typing this that the first include below can't be found! Do I need a path here? I thought cmake did this?

Code: Select all

// alert.c

#include "tmp117.h"
#include "tmp117_registers.h"
#include "hardware/i2c.h"
#include "pico/printf.h"
#include "pico/stdlib.h"
#include "pico.h"
I am horrible with cmake. Frustrating! Thanks in advance if you see my hopefully obvious error.
Or, how do I do a relative path to my library when writing the examples so it doesn't matter where I actually put them on my system?
I want this to be a library people can use along with the SDK.

Code: Select all

#include "tmp117.h" // file not found!
Last edited by breaker on Fri Feb 23, 2024 7:44 am, edited 1 time in total.

arg001
Posts: 640
Joined: Tue Jan 23, 2018 10:06 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 10:52 am

Where's your:

Code: Select all

target_link_libraries(picoprobe PRIVATE
	pico_stdlib
        hardware_i2c
        hardware_adc
)
I don't see it in the snippets you've quoted. With the SDK, if you don't include the library you don't get the headers that go with it.

dthacher
Posts: 1025
Joined: Sun Jun 06, 2021 12:07 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 1:20 pm

I would recommend organizing the directories a little better. I would also recommend following more standard CMake processes. You may wish to just implement interface libraries for now. You can migrate to shared or static libraries later. Doing these things will help straight this out and allow future efforts to go more smoothly.

I created this to help people get started: https://github.com/daveythacher/RP2040_SKELETON. Creating a github would allow one of us to send in a pull request with suggestions.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 5:19 pm

arg001 wrote:
Sat Feb 17, 2024 10:52 am
Where's your:

Code: Select all

target_link_libraries(picoprobe PRIVATE
	pico_stdlib
        hardware_i2c
        hardware_adc
)
I don't see it in the snippets you've quoted. With the SDK, if you don't include the library you don't get the headers that go with it.
Oh, in the CMakeLists.txt for each example. I did forget to post that. I'm unsure if all listed are needed or not.

Code: Select all

breaker@ace:~/pico/tmp117/2_alerts$ ls
CMakeLists.txt  alerts.c

breaker@ace:~/pico/tmp117/2_alerts$ cat CMakeLists.txt
add_executable(alerts
        alerts.c
        )

# target_compile_definitions(alerts PRIVATE PICO_DEFAULT_I2C=0)

# pull in common dependencies and additional i2c hardware support
target_link_libraries(alerts pico_stdlib hardware_i2c pico_printf)

# Link against the 'tmp117' library
target_link_libraries(alerts tmp117)

# enable usb output, disable uart output
# pico_enable_stdio_usb(alerts 1)
# pico_enable_stdio_uart(alerts 0)

# create map/bin/hex file etc.
pico_add_extra_outputs(alerts)
Should I use PRIVATE? I'm unsure when to use PRIVATE.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 5:23 pm

dthacher wrote:
Sat Feb 17, 2024 1:20 pm
I would recommend organizing the directories a little better. I would also recommend following more standard CMake processes. You may wish to just implement interface libraries for now. You can migrate to shared or static libraries later. Doing these things will help straight this out and allow future efforts to go more smoothly.

I created this to help people get started: https://github.com/daveythacher/RP2040_SKELETON. Creating a github would allow one of us to send in a pull request with suggestions.
Well, I'm clueless about cmake, so I am unaware of what a better organization actually is, nor what standard cmake processes are. I was just taking what I saw in the pico examples, and trying to do something like that, but have a directory with headers and sources for multiple examples.

I have no idea what an interface library vs. static library even means. I'm just a very beginner at even making a library to begin with.

I will now read your skeleton, and I'm sure it will help, thanks!

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 5:54 pm

So, since my directory tree is $HOME/pico/tmp117 as my main directory, then subdirectories $HOME/pico/tmp117/src for header and source and $HOME/pico/tmp117/src/1_temp_result subdirectory as an example of one example.

So, this is not found

Code: Select all

// temp_result.c
#include "tmp117.h" // 'tmp117.h' file not found clang(pp_file_not_found)
but, of course, this is found OK

Code: Select all

// temp_result.c
#include "../src/tmp117.h"
I thought I would see if this helps you help me. Thanks.

CMakeLists.txt for /src

Code: Select all

# CMakeLists.txt in the src directory

# Define a library named 'tmp117'
add_library(tmp117
    tmp117.c
    tmp117.h
    tmp117_registers.h
)
CMakeLists.txt for /1_temp_result

Code: Select all

add_executable(temp_result
        temp_result.c
        )

# target_compile_definitions(temp_result PRIVATE PICO_DEFAULT_I2C=0)

# pull in common dependencies and additional i2c hardware support
target_link_libraries(temp_result pico_stdlib hardware_i2c pico_printf)

# enable usb output, disable uart output
# pico_enable_stdio_usb(temp_result 1)
# pico_enable_stdio_uart(temp_result 0)

# create map/bin/hex file etc.
pico_add_extra_outputs(temp_result)
Again, this was all just based off of the pico/examples without really knowing cmake. Going through the tutorial is something I should do, I guess. :roll:

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Sat Feb 17, 2024 5:57 pm

Yes, I will throw it up on github also, if that helps. Again, it would be my first time doing something like that, but I was planning on that anyway.

Should the license be the same as the SDK since it calls SDK functions? The original Sparkfun Arduino library that I am porting is Beerware.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Mon Feb 19, 2024 4:25 am

All right, I'm going through the cmake tutorial. The tutorial is ok, but CMake has a lot of stuff to learn, and it is pretty confusing. It was easier to learn programming languages like C than this CMake scripting. I understand why it used, however. Cross-platform use. So, I'm doing my homework, but it is pretty boring. I've been avoiding this, and just having fun coding using the SDK and just fumbling along with CMake by looking at examples. Cheers.

hippy
Posts: 16100
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: project can't find my library source files in subdirectory (cmake issues?)

Mon Feb 19, 2024 12:53 pm

breaker wrote:
Mon Feb 19, 2024 4:25 am
CMake has a lot of stuff to learn, and it is pretty confusing.
But most stuff is done by rote; 'you want this, then use that'.

I would recommend starting with a simple two file project, 'CMakeLists.txt' and 'main.c'. Get that building then start adding C and header files, coercing that into building.

Then move files to sub-directories and finally start using interfaces or libraries.

Once that's been done you should have a much clearer picture of 'if files are there, this is what I need to do to make them build'.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Mon Feb 19, 2024 6:05 pm

hippy wrote:
Mon Feb 19, 2024 12:53 pm
breaker wrote:
Mon Feb 19, 2024 4:25 am
CMake has a lot of stuff to learn, and it is pretty confusing.
But most stuff is done by rote; 'you want this, then use that'.

I would recommend starting with a simple two file project, 'CMakeLists.txt' and 'main.c'. Get that building then start adding C and header files, coercing that into building.

Then move files to sub-directories and finally start using interfaces or libraries.

Once that's been done you should have a much clearer picture of 'if files are there, this is what I need to do to make them build'.
What do you mean by rote? When I look at all of the documentation for CMake as well as the CMakeLists.txt that come with the Pico SDK, it is a massive amount of stuff. I only took The C Programming Language, wrote stuff for ATTiny using MPLABX and we didn't use a meta build system. I am also familiar with Arduino IDE, which of course is way too easy to use. :)

Yes, thanks for the tips, for the Pico SDK, I can make a CMakeLists.txt for a project using a main.c and also using a header and source file. It was just when I put those files into their own directories that things broke. So, my programs run and can use my #includes that contain function headers and function definitions when in the same directory. To make those CMakeLists.txt files I followed the format of the master and subdirectory examples from the Pico examples. I read more about scope in cmake, and I am starting to get that better. Also, I mis-used the term library, as my files are headers and a source file, not pre-compiled object files.

hippy
Posts: 16100
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: project can't find my library source files in subdirectory (cmake issues?)

Mon Feb 19, 2024 6:38 pm

breaker wrote:
Mon Feb 19, 2024 6:05 pm
What do you mean by rote? When I look at all of the documentation for CMake as well as the CMakeLists.txt that come with the Pico SDK, it is a massive amount of stuff.
By rote I meant by following the 'usual pattern of a typical Pico SDK CMakeLists.txt', something like this ...

Code: Select all

set(PROJECT my_project)
cmake_minimum_required(VERSION 3.12)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(${PROJECT} C CXX ASM)
pico_sdk_init()
add_executable(${PROJECT} main.c)
target_link_libraries(${PROJECT} pico_stdlib)
target_compile_options(${PROJECT} PRIVATE -Wall -Werror)
pico_add_extra_outputs(${PROJECT})
pico_enable_stdio_usb(${PROJECT}  1)
pico_enable_stdio_uart(${PROJECT} 0)
pico_set_binary_type(${PROJECT} no_flash)
That is; you don't so much have to understand 'cmake' beyond knowing such as, if you have some C files, they need to be in the 'add_executable' part. Want something to run from RAM; use that last line.

Nearly all my projects use a clone of that with just the name in the first line changed. In that respect one could say I don't need to know 'cmake' at all. In most cases I just blindly copy it into a new project and use it as is.

hippy
Posts: 16100
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: project can't find my library source files in subdirectory (cmake issues?)

Mon Feb 19, 2024 7:24 pm

breaker wrote:
Mon Feb 19, 2024 6:05 pm
It was just when I put those files into their own directories that things broke. ... To make those CMakeLists.txt files I followed the format of the master and subdirectory examples from the Pico examples.
I think that is the mistake because I don't consider the pico-examples to be very good for teaching how to use 'cmake' in one's own projects.

Fundamentally you need to understand 'cmake' to understand how it is being used and that's not a great starting position IMO.

My approach would be to add a second program file, 'sub.c' ...

Code: Select all

add_executable(${PROJECT} main.c sub.c)
Builds fine. Create 'sub.h' and add '#include' to 'main.c' and 'sub.c' and it still builds fine.

Move 'sub.c' and 'sub.h' to their own './src' directory ...

Code: Select all

add_executable(${PROJECT} main.c ./src/sub.c)
Doesn't work; 'main.c' can't see 'sub.h'. You need to tell it include files are in './src' ...

Code: Select all

add_executable(${PROJECT} main.c ./src/sub.c)
target_include_directories(${PROJECT} PRIVATE ./src)
Job done and that's where I would stop, just adding more files as I needed them.

But, if you want your './src' stuff built by its own 'CMakeLists.txt', want to minimise the number of references to explicit './src' files in your main 'CMakeLists.txt' you can do that - But I'd have to find my notes on how to.

I would have expected there to be Raspberry Pi walk-through tutorials showing how to do things like that but not sure where they would be found.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Mon Feb 19, 2024 11:30 pm

Yes, exactly. The rote stuff was easy. Follow the template and done. Yes, we need paths relative to the project, or absolute paths. Probably exporting a variable that tells the OS would help find things, just like the PICO_SDK_PATH does. The official CMake tutorial is not bad, I just had been avoiding it because my time is precious and I get busy with so many things. So, my free time needs to be just fun coding, if possible.

Consider, I am porting the SparkFun Arduino TMP117 examples to C code using Pico SDK functions. Their Arduino Library uses a directory tree of / /examples /source and somehow the Arduino IDE finds it all just fine. So, I thought, let me organize it the same way. Nope. I need to consider that the environment is different, and uses CMake. Of course I'm sure because one used the Arduino IDE to add the "library" that behind the scenes it has set up paths and links to everything without having to think.

So, I need to consider, what is standard practice for doing this using the Pico SDK, so people can grab the files and use them with the least amount of struggle, yet keep the sources separate from the examples and not all in the same directory. Is a relative path the best option, or do things break when people start moving things around?

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Tue Feb 20, 2024 5:31 pm

OK, the CMake tutorial is good. I think I will be able to figure out what to do, and revise my plan as well. I decided I don't want all of the examples built at once after all. So, each example will be a stand-alone project, I think. Then they each can call the library. Is the term link against? So much jargon. Anyway, I will hopefully post back soon with a resolution. I'm not quite done with the actual port, however.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Thu Feb 22, 2024 6:48 am

First, thanks to those who have responded. dthacher, I did not quite get your source code yet. Why so many compile flags?

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.

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. What's up with this CMake build system, it is crazy.

Soooo, why can't it find the path to the SDK now? Hmm.

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

Code: Select all

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
/tmp117/CMakeLists.txt

Code: Select all

# 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 the src directory to include directories
# include_directories(${PROJECT_SOURCE_DIR}/src)

# message(STATUS "Include Directories: ${CMAKE_INCLUDE_PATH}")

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)

message(STATUS "root")

message(STATUS "Pico SDK path: ${PICO_SDK_PATH}")

get_property(dirs3 DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
get_property(dirs3 DIRECTORY src PROPERTY INCLUDE_DIRECTORIES)
get_property(dirs3 DIRECTORY 1_temp_result PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs3})
  message(STATUS "dir=${dir}")
endforeach()

cmake_print_variables(PROJECT_SOURCE_DIR PROJECT_BINARY_DIR)
cmake_print_variables(CMAKE_INCLUDE_PATH)
/tmp117/src/CMakeLists.txt

Code: Select all

# CMakeLists.txt in the src directory

# Define a library named 'tmp117_functions'
add_library(tmp117_functions
    tmp117.c
)
This is for the example code
/tmp117/1_temp_result/CMakeLists.txt

Code: Select all

add_executable(temp_result
        temp_result.c
        )

# target_compile_definitions(temp_result PRIVATE PICO_DEFAULT_I2C=0)

# pull in common dependencies and additional i2c hardware support
target_link_libraries(temp_result PUBLIC tmp117_functions pico_stdlib hardware_i2c pico_printf)

# add tmp117_functions library to target's include directories
target_include_directories      (temp_result PUBLIC
                                 ${PROJECT_BINARY_DIR}
                                 ${PROJECT_SOURCE_DIR}/src
                                )

# enable usb output, disable uart output
# pico_enable_stdio_usb(temp_result 1)
# pico_enable_stdio_uart(temp_result 0)

# create map/bin/hex file etc.
pico_add_extra_outputs(temp_result)

# add url via pico_set_program_url
# example_auto_set_url(temp_result)
message(STATUS "1_temp_result")

get_property(dirs1 TARGET temp_result PROPERTY INCLUDE_DIRECTORIES)
get_property(dirs2 TARGET temp_result PROPERTY INTERFACE_INCLUDE_DIRECTORIES)

foreach(dir ${dirs2})
  message(STATUS "Interface include directory for temp_result: ${dir}")
endforeach()

get_property(dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
  message(STATUS "dir='${dir}'")
endforeach()

cmake_print_variables(CMAKE_INCLUDE_PATH)
So, I run cmake and get this output

Code: Select all

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 make the example

Code: Select all

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
Code snippet from the above referenced /home/breaker/pico/tmp117/src/tmp117.c

Code: Select all

// tmp117.c
#include "tmp117.h"
#include "tmp117_registers.h"
#include "hardware/i2c.h"
#include "pico/printf.h"
#include "pico/stdlib.h"
#include "pico.h"
Time to go hiking instead, too much useless CMake tutorials and fruitless hours spent.

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Thu Feb 22, 2024 6:48 pm

Anyone know how to debug cmake and what paths are being called?

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Fri Feb 23, 2024 7:42 am

I got it working!

@dthacher Thank you so much for creating the RP2040 Skeleton! It really helped me see what was going on!

The disassembler function did not work for me because of the path to my toolchain, so I removed that from the top level CMakeLists.txt

My main issue was I did not make an INTERFACE type library! m-)

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: project can't find my library source files in subdirectory (cmake issues?)

Fri Feb 23, 2024 7:47 am

dthacher wrote:
Sat Feb 17, 2024 1:20 pm
You may wish to just implement interface libraries for now.
Very true, as I have discovered!

breaker
Posts: 237
Joined: Mon May 06, 2013 6:42 am

Re: [RESOLVED] project can't find my library source files in subdirectory (cmake issues?)

Fri Mar 29, 2024 5:42 pm

Recently I had a new problem with this where the object files were compiled, but the linker could not link them to create the elf when I ran "make."

I also have updated my CMake to version 3.24.1, which may or may not have caused the issue. What I found is when adding an interface library, target_sources needs to be used instead of listing the sources inside add_library as shown in the CMake tutorial here: https://cmake.org/cmake/help/latest/gui ... -a-library This absolutely does not work for an INTERFACE library. Again, a big thanks to Davey Thacher for the RP2040_SKELETON, I couldn't have done it without this. https://github.com/daveythacher/RP2040_SKELETON

Here are my working CMakeLists.txt files, and directory listing. I put the library source and headers into ./src to KISS and YAGNI:

Code: Select all

breaker@ace:~/pico/tmp117$ ls -R
.:
CMakeLists.txt  cm.sh*  examples/  pico_sdk_import.cmake  src/  tmp117_examples.txt

./examples:
1_temp_result/  2_alerts/  3_set_offset/  4_set_conversion_mode/  CMakeLists.txt

./examples/1_temp_result:
CMakeLists.txt  temp_result.c

./examples/2_alerts:
CMakeLists.txt  alerts.c

./examples/3_set_offset:
CMakeLists.txt  set_offset.c

./examples/4_set_conversion_mode:
CMakeLists.txt  set_conversion_mode.c

./src:
CMakeLists.txt  tmp117.c  tmp117.h  tmp117_registers.h
./CMakeLists.txt (top level)

Code: Select all

# Top level CMakeLists.txt in $HOME/pico/tmp117

# Minimum required CMake version
cmake_minimum_required(VERSION 3.13)

# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

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 library source and headers directory to the build
add_subdirectory(src)

# Add the examples directory to the build
add_subdirectory(examples)

cmake_policy(GET CMP0079 policy_value)
if(policy_value STREQUAL "NEW")
    message(STATUS "CMake policy CMP0079 is set to NEW.")
else()
    message(STATUS "CMake policy CMP0079 is not set to NEW.")
endif()

message(STATUS "END tmp117/CMakeLists.txt")
./src CMakeLists.txt where the INTERFACE library is added.
A relative path is necessary, I used the variable ${CMAKE_CURRENT_SOURCE_DIR} as part of that path.

Code: Select all

# CMakeLists.txt in the tmp117/src directory

# Define an INTERFACE library named 'tmp117_functions'
add_library(tmp117_functions INTERFACE)

# Add the source file tmp117.c to the tmp117_functions interface
target_sources(tmp117_functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/tmp117.c)

# Add the current source directory to the include path for tmp117_functions
target_include_directories(tmp117_functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

# Link necessary libraries to the tmp117_functions interface
target_link_libraries(tmp117_functions INTERFACE
    pico_stdlib
    hardware_i2c
    pico_printf
)

message(STATUS "END tmp117/src/CMakeLists.txt")
I now have the examples directories organized under an examples subdirectory, but this isn't necessary:

Code: Select all

# Add example subdirectories
add_subdirectory(1_temp_result)
add_subdirectory(2_alerts)
add_subdirectory(3_set_offset)
add_subdirectory(4_set_conversion_mode)

message(STATUS "END tmp117/examples/CMakeLists.txt")
Finally here is a CMakeLists.txt for my first example program.
${PROJECT_SOURCE_DIR}/src was used for the path for the target_include_directories otherwise, it can't be located.

Code: Select all

# Example 1 (tmp117/examples/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 PRIVATE tmp117_functions pico_stdlib hardware_i2c pico_printf)

# add include paths
target_include_directories(temp_result PRIVATE ${PROJECT_SOURCE_DIR}/src)

# enable usb output, disable uart output
pico_enable_stdio_usb(temp_result 1)
pico_enable_stdio_uart(temp_result 0)

# create map/bin/hex file etc.
pico_add_extra_outputs(temp_result)

# add url via pico_set_program_url
# example_auto_set_url(temp_result)

message(STATUS "END tmp117/examples/1_temp_result/CMakeLists.txt")
I guess I'm finally starting to wrap my mind around CMake!

Return to “SDK”