installationcmakebuildbuild-dependenciesfetchcontent

Why does FetchContent prefer subdirectory-subsumption vs installation of dependencies?


Consider two software projects, proj_a and proj_b, with the latter depending on the former; and with both using CMake.

When reading about modern CMake, one gets the message that the "appropriate" way to express dependencies is via target dependencies; and one should arrange it so that dependent projects are represented as (imported) targets you can depend on. More specifically, in our example, proj_b will idiomatically have:

find_package(proj_a)

# etc etc.

target_link_library(bar proj_a::foo)

and proj_a will need to have been installed, utilizing the CMake installation-and-export-related commands, someplace where proj_b's CMake invocation will search for proj_a-config.cmake.

I like this approach and encourage others to adapt to it. It offers flexibility in the choice of your own version of proj_a vs the system version; and also allows for non-CMake proj_a's via a Findproj_a.cmake script (which again, can be system-level or part of proj_b).

So far so good, right? However, there are people who want to "take matters into their own hands" in terms of dependencies - and CMake officially condones this, with commands such as ExternalProject and more recently, FetchContent: This allows proj_b's configuration stage to actually download a (built, or in our case source-form) version of proj_a.

The puzzling part to me is that, after proj_a is downloaded, say to an external/proj_a directory, CMake's default behavior will be to

add_subdirectory(external/proj_a)

that is, to use proj_a as a subproject of proj_b and build them together. This, while the idiomatic use above allows the maintainer of proj_a to "do their own thing" in my CMakeFile, and only keep things neat and tidy for others via what I export/install.

My questions:

  1. Why does it make sense to add_subdirectory(), rather than to build, install, and perform the equivalent of find_package() to meet the dependency? Or rather, why should the former, rather than the latter, be the default?
  2. Should I really have to write my project-level CMakeLists.txt to be compatible with being add_subdirectory()'ed?

Note: Just to give some concrete examples of how this use constrains proj_a:


Solution

  • Following the discussion in comments, I decided to post a bug report about this:

    #22904: Support FetchContent_MakeAvailable performing build+install+find_package rather than add_subdirectory

    So maybe this will change and the question becomes moot.