How to have CMake resolve directories

Currently, I have to add directories to my files in my C/C++ project both in the CMakeLists.txt and my include directives, for example:

add_library (library1
src/dir1/file1.h
src/dir1/file1.c
)

and in file1.c itself:

#include “…/dir2/fileNeededByFile1.h”

etc.

I’d like CMake to resolve this for me automatically. I thought that the “include_directories” would do this, but it seems to not be the case. How can I tell CMake to look into certain directories (recursively, or if not possible, not recursively) and avoid having to write the directories one by one?

I’m really unclear on what you are asking for.

This article does a pretty good job explaining include directories with CMake though.

Thanks for the link, I will check it.

What I want is to not have to write the directory of every file both in the add_library add_executable etc. commands and the include directories in the code, as I surmise that CMake likely offers me a way to solve this. That is, instead of

add_library (library1
src/dir1/file1.h
src/dir1/file1.c
src/dir2/file2.h
src/dir2/file2.c

)

I’d like to be able to write:

add_library (library1
file1.h
file1.c
file2.h
file2.c
)

and in file1.h’s directives, instead of
#include “…/src/dir3/fileNeededByFile1.h”.

I’d like to write
#include “fileNeededByFile1.h”.

I expect that there is a

command_to_set_directories( library1
src/dir1/
src/dir2/
src/dir3/
}
to do that.

There isn’t a CMake command that auto resolves directories the way you want.

Your best tools for adding files and include directories are target_sources / target_include_directories

I’d look at this blog post by Craig Scott for handling your source files in a nice way which I have seen accepted in many projects that want to make their CMake code nicer.

Essentially your CMake script would end up looking like this:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.13)

project(FOOBAR LANGUAGES C)

add_library(library)
add_subdirectory(src)
add_subdirectory(inc)

Overall I think that’s a nice presentation :+1:

Then you have a CMakeLists.txt in src that looks like this (You can obviously do this for as many directories as you want):

# src/CMakeLists.txt
target_include_directories(library PRIVATE .)
target_sources(library PRIVATE 
     file1.c 
     file1.h
     file2.c
     file2.h
)

And potentially if you a nice library author your CMakeLists.txt in your inc directory looks like this:

# inc/CMakeLists.txt

# Notice the use of PUBLIC!
# Now when a client links against your library they automatically absorb the inc/ include directory
# Which makes their CMake code nicer since they don't need to know how your project is laid out!
target_include_directories(library PUBLIC .)
target_sources(library PRIVATE
    library1.h
)

That looks nice. Thank you so much.

1 Like