Cmake with Include and Source Paths - Basic Setup

CMake with include and source paths - basic setup

You need a CMakeLists.txt for each source subdirectory. Your structure should look something like this:

root
|-MainProject
| |-inc
| | '-main.h
| |-src
| | |-main.cpp
| | '-CMakeLists.txt
| '-CMakeLists.txt
|-LibProject
| |-inc
| | '-test.h
| |-src
| | |-test.cpp
| | '-CMakeLists.txt
| '-CMakeLists.txt
'-CMakeLists.txt

Content of root/CMakeLists.txt:

project(MyProject)
add_subdirectory(MainProject)
add_subdirectory(LibProject)

Content of LibProject/CMakeLists.txt and MainProject/CMakeLists.txt:

add_subdirectory(src)

Content of LibProject/src/CMakeLists.txt:

# Notice name prefix of this variable, set by CMake according
# to value given with "project()" in the root CMakeLists.txt.
include_directories(${MyProject_SOURCE_DIR}/LibProject/inc)
add_library(LibProject test.cpp)

Content of MainProject/src/CMakeLists.txt:

include_directories(${MyProject_SOURCE_DIR}/MainProject/inc)
# I assume you want to use LibProject as a library in MainProject.
include_directories(${MyProject_SOURCE_DIR}/LibProject/inc)
link_directories(${MyProject_SOURCE_DIR}/LibProject/src)
add_executable(MainProject main.cpp)
target_link_libraries(MainProject LibProject)

Then configure and build with:

$ cd root
$ mkdir build
$ cd build
$ cmake ..
$ make

How to properly add include directories with CMake

Two things must be done.

First add the directory to be included:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

In case you are stuck with a very old CMake version (2.8.10 or older) without support for target_include_directories, you can also use the legacy include_directories instead:

include_directories(${YOUR_DIRECTORY})

Then you also must add the header files to the list of your source files for the current target, for instance:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

This way, the header files will appear as dependencies in the Makefile, and also for example in the generated Visual Studio project, if you generate one.

How to use those header files for several targets:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

CMake include and source paths are not the same as the Windows Directory paths

I just have given your example a try and the solution is given in the error message

CMake Error at CMakeLists.txt:10 (add_subdirectory):
add_subdirectory not given a binary directory but the given source
directory ".../src/libprojects/foolib/src"
is not a subdirectory of
".../src/libprojects/foolib/project". When
specifying an out-of-tree source a binary directory must be explicitly
specified.

So as @LPs has pointed out, see CMAKE add sub-directory which is not sub-directory on real directory. Just change your add_subdirectory() call to something like:

add_subdirectory("../src" "src")

And you won't have to prefix the 1st parameter with ${PROJECT_SOURCE_DIR} and the 2nd with ${CMAKE_CURRENT_BINARY_DIR} (both are the defaults, see add_subdirectory()).

My recommendation in your cause would be to put the main/libraries CMakeLists01.txt into the foolib folder. Then you even won't need CMakeLists02.txt.

src/libprojects/foolib/CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)

project (foolib CXX)

include_directories("../../../include")

add_library(foo "src/foo.cxx")

Especially in cases where source and header files are in separate (sub-)folders, doing something like add_library(foo src/foo.cxx) is totally ok/often used.

How to properly configure include paths with simple CMake project

The usual way to get around this issue is to create your own find module i.e. FindXXX.cmake (in your case it is FindLwIP.cmake) so that you can create LwIP_INCLUDE_DIRS variable within the package.

set(LwIP_INCLUDE_DIRS
${CMAKE_CURRENT_LIST_DIR}/../LwIP/include
${CMAKE_CURRENT_LIST_DIR}/../LwIP
${CMAKE_CURRENT_LIST_DIR}/../LwIP/include/XXX)
.
.
(omitted..)
.
.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LwIP DEFAULT_MSG LwIP_INCLUDE_DIRS LwIP_SOURCES LwIP_HEADERS)

With the above find module, your application can cleanly include the package and use the variables that are created by the find the module.

find_package(LwIP REQUIRED)
.
.
(omitted...)
.
.
include_directories(LwIP_INCLUDE_DIRS)
add_executable(${PROJECT_NAME}.elf ${SOURCES})

Since your work is related to STM32 & cmake, let me give you a great reference which will be a nice starting point for your work as well.

https://github.com/ObKo/stm32-cmake.git

Hope this helps.

CMake Include paths - library that depend on external library

In the top-level:

cmake_minimum_required(VERSION 3.21)
project(project)

option(BUILD_SHARED_LIBS "Build shared libs instead of static" ON)

add_subdirectory(libA)
add_subdirectory(libB)

add_executable(App main.cpp)
target_link_libraries(App PRIVATE libA libB)

In libA:

add_library(libA src.cpp)

# Use PUBLIC below if libA exposes libB's types in its API.
target_link_libraries(libA PRIVATE libB)

In libB:

add_library(libB foo.cpp)
target_include_directories(
libB PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)

PUBLIC and INTERFACE properties on targets propagate to their linkees. Thus, when we set up the include directories on libB, any target linking to it will get its source directory added it its include path.

We guard the include directory with $<BUILD_INTERFACE:...> so that if you ever install() the library somewhere it might be re-used in another CMake build, it won't remember details of your specific file system.

CMake : Add build directory to include path

I was looking for

include_directories (${CMAKE_BINARY_DIR})

To add the build directory in case of out-of-source build.



Related Topics



Leave a reply



Submit