What's the best way to include headers from FetchContent deps?

I’ve added the bare-bones FetchContent statements to my project that declare and make available some support libraries that I’ve also written. I’ve been successfully compiling and running from my source tree but didn’t realize that I was still including the headers that I had installed to my system before learning how to fetch dependencies.

cmake_minimum_required(VERSION 3.22)

project(aoc-2022 VERSION 0.1 LANGUAGES C)

set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED YES)

# Support Libraries
include(FetchContent)
FetchContent_Declare(cgs
        GIT_REPOSITORY  https://github.com/Chrinkus/libcgs.git
        GIT_TAG         main
)
FetchContent_Declare(fruity
        GIT_REPOSITORY  https://github.com/Chrinkus/fruity.git
        GIT_TAG         main
)
FetchContent_MakeAvailable(cgs fruity)

# snip

So now that I’ve deleted the previously installed libs and am trying to run from my build dir, my include statements are failing. Is there a better, more idiomatic way to resolve include paths than adding:

include_directories(_deps/cgs-src/src)

Perhaps using some defined variables like ‘CGS_INCLUDE’ or something?

The repo with the full file and links to the libs in the README is here.

Just use targets. Your support libraries should have targets that you use like:

target_link_libraries (aoc-2022 PRIVATE cgs fruity)

and that should be it. The cgs and fruity targets should set their own include directories, which propagate to targets that link against them.

The libraries are linking fine, I just can’t include the headers. I also have written the support libraries and I’m not sure how to export include directories. I have declared some Public Headers in libcgs but I’ve gone through all of the build output and can’t find any variables set.

This has been an issue I’ve had for a while but I’ve always just adjusted my path to fix it. Now I have some people trying to build my code and I don’t want them to have to muck around. So how do I make my support libraries more consumable?

The simplest way to do this is like this:

add_library (cgs)

target_include_directories (cgs PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include") # or whatever path

with that code, any target who links against the cgs library using target_link_libraries will get that include directory transitively.

Often you need to differentiate between include directories when building vs when installing, for example if you have generated files. In that case you do something like:

add_library (cgs)

include (GNUInstallDirs)

target_include_directories (cgs 
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>" # these dirs are only used when building inside the build tree
        "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" # these dirs are only used when linking against a prebuilt version of your package
)
1 Like

This made sense as soon as I read it. Thank you for your time and advice!

1 Like

I suggest using origin/main so that it updates to the remote’s main instead of “freezing” at whatever your local main is on the first clone.

1 Like