从父 CMakeLists.txt 覆盖 CMake 中的默认选项(...)值

问题描述 投票:0回答:3

我试图在我的源代码树中包含几个第三方库,对它们的构建系统进行最小的更改以便于升级。他们都使用 CMake,我也是,所以在我自己的 CMakeLists.txt 中我可以使用

add_subdirectory(extern/foo)
for libfoo.

但是 foo CMakeLists.txt 编译了一个测试工具,构建了文档,一个我不需要的共享库,等等。 libfoo 的作者有远见地通过选项来控制它们——例如

option(FOO_BUILD_SHARED "Build libfoo shared library" ON)
——这意味着我可以通过 CMake 命令行设置它们。但我想默认关闭它并通过命令行覆盖它。

我试过在

set(FOO_BUILD_SHARED OFF)
之前做
add_subdirectory(extern/foo)
。这具有在第二次和后续构建尝试期间不尝试构建共享库的效果,但在第一次尝试期间不会尝试构建共享库,这是我真正需要加速的。

这可能吗,或者我是否需要为这些项目维护分叉的 CMakeLists.txt?

c++ build build-process cmake
3个回答
91
投票

尝试在缓存中设置变量

SET(FOO_BUILD_SHARED OFF CACHE BOOL "Build libfoo shared library")

注意:您需要指定变量类型和描述,以便 CMake 知道如何在 GUI 中显示此条目。


10
投票

这个问题很老了,但是谷歌把我带到了这里。

SET(<variable name> <value> CACHE BOOL "" FORCE)
的问题是它会在项目范围内设置选项。如果你想使用一个子项目,它是一个库,并且你想使用
BUILD_STATIC_LIBS
为子项目(
ParentLibrary
)设置
SET(... CACHE BOOL "" FORCE)
,它将为所有项目设置值。

我正在使用以下项目结构:

|CMakeLists.txt (root)
|- dependencies
   | CMakeLists.txt (dependencies)
   |- ParentLibrary
      | CMakeLists.txt (parent)
|- lib
   | CMakeLists.txt (lib)

现在我有

CMakeLists.txt (dependencies)
看起来像这样:

# Copy the option you want to change from ParentLibrary here
option (BUILD_SHARED_LIBS "Build shared libraries" ON)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(ParentLibrary)

优点是我不需要修改

ParentLibrary
而且我可以只为那个项目设置选项。

有必要从

option
中显式复制
ParentLibrary
命令,否则在最初执行 CMake 配置时,变量的值将首先由
set
命令设置,然后该值将被
option 
命令,因为缓存中没有值。当第二次执行 CMake 配置时,
option
命令将被忽略,因为缓存中已经有一个值,并且将使用
set
命令的值。这会导致一些奇怪的行为,即两次 CMake 运行之间的配置会有所不同。


1
投票

为了给出更新的答案,因为较新的项目使用较新的 CMake 版本(可能使用旧 CMake 版本的库)。

从 CMake 3.13 开始,有一个选项可以简单地在父项目中设置一个变量,这会在所有子项目中设置变量。这基本上是您尝试过的,但现在是可能的。引入了 3.13 版CMP0077:

option() 命令通常用于创建缓存条目以允许用户设置选项。但是,在某些情况下,项目可能会在调用 option() 命令之前定义与选项同名的普通(非缓存)变量。例如,一个将另一个项目作为子目录嵌入的项目可能希望对子项目的选项进行硬编码以构建它需要的方式。
...
在 CMake 3.13 及更高版本中,当给定名称的普通变量已经存在时,option() 命令倾向于不执行任何操作。它不会创建或更新缓存条目或删除普通变量。新行为在构建树中的第一次和后来的运行之间是一致的。此政策提供与尚未更新以期待新行为的项目的兼容性。

所以你可以简单地使用

set
在父项目中硬编码一个选项,通过在
add_subdirectory
之前添加以下内容:

set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(FOO_BUILD_SHARED OFF)

...

add_subdirectory(extern/foo)
© www.soinside.com 2019 - 2024. All rights reserved.