add_subdirectory vs ExternalProject_Add vs include(path/to/ProjectConfig.cmake)

This is a great, general question. There are multiple ways to approach this, each with their own tradeoffs. The way I understand it is the following (I would greatly appreciate clarity/correction from others too):

  • add_subdirectory: can be used if the other project is a Git submodule or similar of your main project. Intermingles scope like a conventional subdirectory
  • FetchContent: instead of a Git submodule, use Git or cURL or similar to download other Cmake project. Intermingles scope as well–better for external projects that you control or understand thoroughly
  • ExternalProject: Can build other project (autotools, makefile, etc) without mingling scope. Requires extra code in your project to declare libraries from the other project.

I do follow like your pattern:

find_package(Foo)
if(NOT Foo_FOUND)
  # fetchcontent, external project, or git submodule update
  # if external project, additional code to specify targets from that project
endif()

I have a few types of examples. This one uses two externalProjects to build Zlib and HDF5, if they’re not found: h5fortran/CMakeLists.txt at main · geospace-code/h5fortran (github.com)

Another example using Git submodule: p4est/CMakeLists.txt at prev3-develop · cburstedde/p4est (github.com)

FetchContent if lapack not found: scalapack/lapack.cmake at master · scivision/scalapack (github.com)

These examples could be further optimized, but give examples of each in somewhat widely used projects.

1 Like