In very simple form: The option FIND_PACKAGE_ARGS
makes FetchContent
to use results of find_package
. But for make find_package
to use results of FetchContent
, you need to pass another option: OVERRIDE_FIND_PACKAGE
.
Both FetchContent
and find_package
are intended to introduce a 3d-party project for use it during the build of main project. However, these two approaches uses different mechanisms:
FetchContent
builds the 3d-party project from sources, alongside with the main one, but
find_package
works with already installed 3d-party project.
CMake provides two "directions" of integration between FetchContent
and find_package
; each "direction" has its own, independent purposes.
1. Write a new project equally consuming a 3d-party project both in sources and installed.
Assume you write a project, which uses some 3d-party project. Assume you want to support two variants:
- Use installed variant of the 3d-party project, if it is already available, or
- Build the 3d-party project from sources alongside with your main project.
Parameter FIND_PACKAGE_ARGS
for FetchContent_Declare
tells CMake to use find_package
for locate installed 3d-party project, and, if it is available, do not build it from sources.
Such integration will work only if the main project uses the 3d-party project via interface, provided both by 3d-party project's sources and by find_package
.
E.g. GTest's sources create ALIAS targets in namespace GTest
(like GTest::gtest_main
) and find_package(GTest)
creates IMPORTED targets with the same namespace. So, the outer project can safely link with GTest::gtest_main
and this will work whenever GTest is already installed or is being built from sources.
2. Make an existing project to work with a 3d-party project built from sources
Assume you are creating a superproject, which combines several already existed subprojects. One of this subprojects executes find_package
for the 3d-party project and uses its results. Assume you want that 3d-party project to be built from the sources.
Most of project-specific scripts, consumed by find_package
, work only with the installed packages and doesn't work with the one which is currently being built. Some special power is needed..
Ignore 'find_package'
Parameter OVERRIDE_FIND_PACKAGE
for FetchContent_Declare
means to ignore further find_package
calls because the 3d-party project is being built from sources.
This approach works if the subproject uses only those results from find_package
, which are available from the 3d-party project's sources too.
E.g. it will work if the subproject uses target GTest::gtest_main
for link with. But it won't work if the subproject uses GTEST_MAIN_LIBRARIES
variable, which is not set in the GTest sources.
Change a script executed by 'find_package'
But what if the subproject uses a part of interface, which is available only from find_package
(and its project-specific script), but is not available from the sources of the 3d-party project? In that case it is possible to create a fake script, which will be executed by find_package
instead of the normal one.
file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-extra.cmake
[=[
set(GTEST_MAIN_LIBRARIES GTest::gtest_main)
]=])
Lines between [=[
and ]=]
becomes part of the created script, which defines
GTEST_MAIN_LIBRARIES
variable suitable for link in a subproject.
(Note, that the file gtest-extra.cmake
has a sence only when OVERRIDE_FIND_PACKAGE
parameter has been specified for FetchContent_Declare
.)