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

56 c++ build-process build cmake

我试图在我的源代码树中包含几个第三方库,只需对其构建系统进行最小的更改,以便于升级.他们都像我一样使用CMake,因此在我自己的CMakeLists.txt中我可以使用add_subdirectory(extern/foo)libfoo.

但是foo CMakeLists.txt编译测试工具,构建文档,我不需要的共享库,等等.libfoo作者有远见控制这些via选项 - option(FOO_BUILD_SHARED "Build libfoo shared library" ON)例如 - 这意味着我可以通过CMake命令行设置它们.但是我希望默认情况下关闭它并通过命令行覆盖.

我以前尝试set(FOO_BUILD_SHARED OFF)add_subdirectory(extern/foo).这样做的结果是在第二次和后续构建尝试期间不尝试构建共享库,而不是在第一次构建期间构建共享库,这是我真正需要加速的那个.

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

pki*_*kit 74

尝试在CACHE中设置变量

SET(FOO_BUILD_SHARED OFF CACHE BOOL "Build libfoo shared library")
Run Code Online (Sandbox Code Playgroud)

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

  • 将它放在add_subdirectory命令之前,因此它将设置变量的默认值. (11认同)
  • 有时您需要使用`FORCE` (8认同)
  • @Rajish如果变量已经由于先前的`OPTION`或`SET(CACHE)`调用或来自先前configure的CMakeCache.txt而被缓存,则必须使用`SET(FOO_BUILD_SHARED OFF CACHE BOOL"构建libfoo共享库" FORCE)`.[源(https://cmake.org/cmake/help/v3.0/command/set.html) (7认同)
  • 专业提示(对我自己):`FORCE`在doc字符串之后,而不是在中间随机... (3认同)

小智 6

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

问题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)
Run Code Online (Sandbox Code Playgroud)

现在我有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)
Run Code Online (Sandbox Code Playgroud)

优点是我不需要修改ParentLibrary,我可以只为那个项目设置选项。

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


Mar*_*arc 5

为了给出更新的答案,因为较新的项目使用较新的 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)
Run Code Online (Sandbox Code Playgroud)