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.