FetchContent with Boost

Hi there,

I have been trying to make sense of the FetchContent documentation at:

However I must say I totally fail to understand the documentation in my simple case:

cmake_minimum_required(VERSION 3.24)
project(p)

set(BOOST_INCLUDE_LIBRARIES math filesystem system program_options)
set(BOOST_ENABLE_CMAKE ON)
include(FetchContent)
FetchContent_Declare(
  Boost
  GIT_REPOSITORY https://github.com/boostorg/boost.git
  GIT_TAG boost-1.80.0
)
FetchContent_MakeAvailable(Boost)

add_executable(boost_test boost_test.cpp)
target_link_libraries(boost_test PRIVATE Boost::filesystem
                                         Boost::program_options)

If I compile my code I get:

boost_test.cpp:2:10: fatal error: boost/math/special_functions/round.hpp: No such file or directory
    2 | #include <boost/math/special_functions/round.hpp>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

For some reason FetchContent_MakeAvailable did construct an almost working set of include directories, but for some reason did not add the math directories.

What did I misunderstood from FetchContent documentation ?

Thanks

Hi there,

Seeing the code it seems you are correctly calling boost and the modules you want. In the target_link_libraries I think you miss to add Boost::math, you are linking just to filesystem and program_options.

1 Like

I was hoping to get a more detailed answer in this case. The correct solution is indeed

target_link_libraries(boost_test PRIVATE Boost::math ...)

But when I read the documentation for target_link_libraries, here is what I see:

Specify libraries or flags to use when linking a given target and/or its dependents.

Could someone explain why target_link_libraries would have an influence target_include_directories ?

That’s because in CMake targets carry their dependencies when linking. Boost::math is a target, so it carries the information about needed defines, location of the libraries, and needed include directories. Those pieces of information will be added to your target when using target_link_libraries

1 Like

Thanks for the quick answer. Here is the documentation I am reading:

Each <item> may be:

  • A library target name: The generated link line will have the full path to the linkable library file associated with the target. The buildsystem will have a dependency to re-link <target> if the library file changes.

ref:

Would you mind sharing a link to the cmake documentation where you found this hint ? Thanks much

I’d love to give u a link, but I cannot find it either. It is one of the things that I have organically learned by using CMake and reading answers on SO, and MailingList.
If it’s written in the documentation in clear text, someone more familiar with the docu would have to point to it. Sorry.

Chapter 3 of the tutorial might be a good starting point.

1 Like

I was not expecting to get that much attention for my silly issue :smiley:

So given the interest, could someone please confirm what is the expected behavior of FetchContent for another cmake based project.

cmake_minimum_required(VERSION 3.24)
project(p)

include(FetchContent)
FetchContent_Declare(
  Log4CPP
  URL https://sourceforge.net/projects/log4cpp/files/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
  DOWNLOAD_EXTRACT_TIMESTAMP TRUE
  )
FetchContent_MakeAvailable(Log4CPP)
if(TARGET log4cpp)
        message("I am a target")
endif()
add_executable(main main.cpp)
target_link_libraries(main PRIVATE log4cpp)

Short answer: the include_directory is not setup as in the previous example.

So where is the issue: in my code ? in cmake/FetchContent ? In log4cpp cmake project ?

Thanks

None of this is really specific to FetchContent. Your queries would be the same if you simply downloaded Boost sources yourself or added Boost as a git submodule, then brought those sources into your build with add_subdirectory(). The same applies to any other project you might choose to absorb into your build.

So to directly answer your last question, the expected behavior is: if log4cpp is a target that is being defined by the sources you’re downloading and absorbing into your build, then it should work fine as long as that target correctly adds its usage requirements. It would usually do that using things like target_include_directories(), target_compile_definitions(), etc. If the build doesn’t work, I would be looking into the log4cpp project to see why. Not all projects expect to be absorbed into a larger parent build this way, so you can’t always use FetchContent, git submodules, etc. to bring every project into your own.

Excuse the brevity, I’m answering queries between other obligations. :wink: