首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >cmake:将FetchContent与find_package()集成

cmake:将FetchContent与find_package()集成
EN

Stack Overflow用户
提问于 2022-09-06 11:36:36
回答 1查看 150关注 0票数 1

我正在努力理解以下文件:

因此,我尝试了一个简单的cmakelists.txt文件,如:

代码语言:javascript
复制
% cat 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
)

# This will try calling find_package()
FetchContent_MakeAvailable(googletest)
find_package(GTest)
message(${GTest_DIR})

如果我运行它,我得到的是:

代码语言:javascript
复制
$ cmake ..
[...]
/usr/lib/x86_64-linux-gnu/cmake/GTest

出于某种原因,find_package(GTest)仍然试图检查系统中的GTest,而不是在FetchContent代码块中声明的系统。

我从cmake文档中误解了什么?我假设函数FetchContent正是用于用户不能使用ExternalProject的情况,因为它是不会find_package集成的。

供参考:

代码语言:javascript
复制
% cmake --version
cmake version 3.24.1
EN

回答 1

Stack Overflow用户

发布于 2022-09-06 14:41:56

以非常简单的形式:选项FIND_PACKAGE_ARGS使FetchContent使用find_package的结果。但是要使find_package使用FetchContent的结果,您需要传递另一个选项:OVERRIDE_FIND_PACKAGE

FetchContentfind_package都打算引入一个3D派对项目,以便在主项目构建过程中使用它。然而,这两种方法使用不同的机制:

  1. FetchContent从源构建3d派对项目,并与主要的项目一起构建,但是
  2. find_package与已经安装的3D派对项目一起工作。

CMake为FetchContentfind_package之间的集成提供了两个“方向”;每个“方向”都有自己独立的目的。

1.编写一个新的项目,无论是在源中还是在安装上,都同样地消耗了3d方项目。

假设您编写了一个项目,其中使用了一些3D派对项目。假设您想支持两个变体:

  1. 如果已可用,则使用已安装的3d派对项目变体,或
  2. 与你的主要项目一起从资源中构建3D派对项目。

参数FIND_PACKAGE_ARGS for FetchContent_Declare告诉CMake使用find_package定位已安装的3d派对项目,如果可用,则不要从源构建它。

只有当主项目通过界面使用3d方项目时,这种集成才能工作,并提供由3d方项目的来源和find_package提供。

例如,GTest的源代码、创建别名、名称空间中的GTest (如GTest::gtest_main)和find_package(GTest) 创建导入了具有相同名称空间的目标。因此,外部项目可以安全地与GTest::gtest_main链接,这将在GTest已经安装或正在从源构建时工作。

2.使现有的项目与从来源构建的3d方项目一起工作。

假设您正在创建一个超级项目,它结合了几个已经存在的子项目。其中一个子项目为3D派对项目执行find_package并使用其结果。假设您希望从资源中构建3D派对项目。

find_package使用的大多数特定于项目的脚本只与安装的包一起工作,而不使用当前正在构建的包。需要一些特殊的力量。

忽略“find_package”

参数OVERRIDE_FIND_PACKAGE for FetchContent_Declare意味着忽略进一步的find_package调用,因为3D派对项目是从源构建的。

如果子项目只使用来自find_package的结果,那么这种方法是可行的,这些结果也可以从3d方项目的资源中获得。例如,如果子项目使用目标GTest::gtest_main进行链接,它就会工作。但是,如果子项目使用GTEST_MAIN_LIBRARIES变量( GTest源中没有设置该变量),它将无法工作。

更改由“find_package”执行的脚本

但是,如果子项目使用接口的一部分,这部分接口只能从find_package (及其特定于项目的脚本)获得,但不能从3d方项目的源中获得呢?在这种情况下,可以创建一个假脚本,它将由find_package而不是普通脚本执行。

代码语言:javascript
复制
file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-extra.cmake
[=[
  set(GTEST_MAIN_LIBRARIES GTest::gtest_main)
]=])

[=[]=]之间的行成为创建脚本的一部分,脚本定义了适合子项目中链接的GTEST_MAIN_LIBRARIES变量。

(请注意,只有当为gtest-extra.cmake指定了OVERRIDE_FIND_PACKAGE参数时,文件FetchContent_Declare才有意义。)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73621403

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档