FetchContent: Allow ignoring CMAKE_PROJECT_INCLUDE_BEFORE and CMAKE_PROJECT_INCLUDE
FetchContent
is a great and very useful module for fetching and incorporating external projects into one's own CMake build. (Thanks for it!)
Problem
However, because the external CMake project is incorporated into one's own CMake build it will be affected by variables CMAKE_PROJECT_INCLUDE_BEFORE
and CMAKE_PROJECT_INCLUDE
. And this might not be desirable.
Example which shows the problem
For example, if CMAKE_PROJECT_INCLUDE_BEFORE
points to a file which always includes another file which is assumed to be located relative to the currently being processed CMakeLists.txt
file, then when processing the CMakeLists.txt
file of the incorporated external project this specific file will probably not be found and CMake will fail.
Example
# rootdir/CMakeLists.txt
...
set( CMAKE_PROJECT_INCLUDE_BEFORE ${CMAKE_CURRENT_LIST_DIR}/LoadAlwaysBeforeProject.cmake )
...
# rootdir/LoadAlwaysBeforeProject.cmake
include( ${CMAKE_CURRENT_SOURCE_DIR}/SettingsForThisProject.cmake )
# rootdir/some/subdir/SettingsForThisProject.cmake
# Some local settings for the CMakeLists.txt of the same directory.
...
# rootdir/some/subdir/CMakeLists.txt
...
FetchContent_MakeAvailable( some_external_project ) # Fails here!
Error-Message
CMake Error at .../rootdir/LoadAlwaysBeforeProject.cmake:3 (include):
include could not find load file:
.../rootdir/some/subdir/_deps/some_external_project-src/SettingsForThisProject.cmake
Call Stack (most recent call first):
.../rootdir/some/subdir/_deps/some_external_project-src/CMakeLists.txt:3 (project)
(The same problem I demonstrated with GoogleTest as the external project in my talk at Meeting C++ 2019. See slide 42 (page 148 in the PDF).)
Recommendation
I would therefore recommend to provide a boolean option to FetchContent_Declare()
which results in these variables to be ignored when later used with FetchContent_MakeAvailable()
. (Possibly, individual options for each of these variables would be even better.)
The implementation of FetchContent_MakeAvailable()
should then probably backup these variables, unset them, call add_subdirectory()
and afterwards reset the variables from the backups and remove the backups again. Of course, all this should only be done if the aforementioned boolean option(s) have been set.
Care should probably be taken when choosing the name of the backup to prevent overriding former backups when in a nested FetchContent_MakeAvailable()
call (that is when the external project itself uses FetchContent
).
But that might probably not be a problem because of directory-scope of variables. (Otherwise the backup could be set as properties to a local target or similar?)