CMake中FetchContent配合find_package仍调用系统GTest的问题咨询
学习CMake中FetchContent与find_package集成时,编写了如下CMakeLists.txt:
cmake_minimum_required(VERSION 3.24) project(p) include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 FIND_PACKAGE_ARGS NAMES gtest ) # 预期这里会调用find_package() FetchContent_MakeAvailable(googletest) find_package(GTest) message(${GTest_DIR})
执行cmake后输出:
$ cmake .. [...] /usr/lib/x86_64-linux-gnu/cmake/GTest
发现find_package(GTest)仍在查找系统中的GTest,而非FetchContent声明的版本。原本以为FetchContent是用来解决ExternalProject无法与find_package集成的场景,CMake版本为3.24.1,想知道误解了文档中哪部分内容?
你误解了FIND_PACKAGE_ARGS的作用逻辑,以及FetchContent_MakeAvailable和后续find_package的交互方式:
FIND_PACKAGE_ARGS的实际作用
这个参数是让FetchContent先尝试调用find_package(gtest)(对应你写的NAMES gtest)查找系统已安装的包,只有当查找失败时,才会从你指定的Git仓库拉取代码并构建。你的系统里已经存在GTest,所以FetchContent直接复用了系统版本,没有去拉取你指定的Git版本。后续
find_package(GTest)的行为
即使FetchContent拉取了包,默认情况下find_package还是会按照标准查找顺序(系统路径优先)去查找。要让它优先使用FetchContent引入的包,需要让FetchContent把引入包的配置路径加入CMake查找路径,或者直接使用FetchContent提供的目标。修正方案
如果你想强制使用FetchContent指定的版本、忽略系统已安装的包,需要在FetchContent_Declare中添加OVERRIDE_FIND_PACKAGE参数:FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 FIND_PACKAGE_ARGS NAMES gtest OVERRIDE_FIND_PACKAGE # 强制用FetchContent的版本覆盖find_package查找 )添加该参数后,后续调用
find_package(GTest)就会优先使用FetchContent引入的版本。另外,FetchContent_MakeAvailable已经完成了包的配置,你可以直接使用GTest::GTest等目标,无需再手动调用find_package(GTest)。
内容的提问来源于stack exchange,提问作者malat

