如何存储CMake构建设置

12

在尝试构建使用CMake的项目时,通常需要启用/禁用许多开关。

如何存储某个用户所做的构建设置,以使得在另一台机器上能够重现构建?是否有一些导出功能,或者你只需复制构建(缓存)文件夹?


2
我会在cmake文件中设置默认值。我怀疑是否有一般的方法,而且我认为复制缓存并不是一个好主意:因为缓存变量通常包含本地路径。不过这是个好问题! - Antonio
@Antonio 但我不想更改第三方依赖的CMakeLists.txt。我可以通过命令行更改设置,但是保留它们并开始自动化构建的最佳实践是什么? - Beachwalker
@Antonio,你给出的使用参数-C的.cmake文件提示很有效。我之前不知道这个参数。谢谢! - Beachwalker
3个回答

18

使用cmake预加载脚本以填充缓存文件有一个选项。

cmake -C <initial-cache>

initial-cache是一个包含变量的文件,这些变量以以下方式设置,例如安装前缀:

set(CMAKE_INSTALL_PREFIX "/my/install/prefix" CACHE PATH "")

只需在使用cmake填充缓存时传递此文件即可。 这很简单,但是我不知道这个,并且没有找到好的示例。此外,这是一种独立于平台的方法,而不是编写脚本或批处理文件。

我在生成的源码构建文件夹之外创建了一个单独的脚本文件夹。 我将每个要构建的库/可执行文件的设置存储在其中。

您可以将所有设置放入单独的文件中,最后只剩下几个调用:

cmake -E make_directory build/somelib
cmake -E chdir build/somelib cmake -C ../../script/cmake/somelib.cmake ../../source/somelib/src
cmake --build build/somelib --target install

很简单,对吧?

自动生成initial-cache文件:

如果您使用的是*nix系统,可以在构建目录内运行以下命令:

cmake -N -LA | tail -n+2 | sed -r 's/([A-Za-z_0-9]+):([A-Z]+)=(.*)/set(\1 "\3" CACHE \2 "")/' >cmake-init.txt

在Windows上,类似下面这样的cmake脚本应该能够工作:
# list all cache variables
# this should be run in your build dir

set(filename ${CMAKE_ARGV3})
message(STATUS "Writing to ${filename}")
if(NOT filename)
    message(FATAL_ERROR "Must provide an output filename")
    return()
endif()

execute_process(COMMAND "${CMAKE_COMMAND}" "-N" "-LA" OUTPUT_VARIABLE cacheVars)
string(REPLACE "\n" ";" cacheVars ${cacheVars})
file(WRITE ${filename} "")

foreach (variable ${cacheVars})
    string(REGEX REPLACE "([A-Za-z_0-9]+):([A-Z]+)=(.*)$" "set(\\1 \"\\3\" CACHE \\2 \"\")\n" output ${variable})
    if(CMAKE_MATCH_0)
        file(APPEND ${filename} ${output})
    endif()
endforeach()

将它保存为,例如get_cache_vars.cmake,并像这样运行它:

cd <your build-dir>
cmake -P path\to\get_cache_vars.cmake <outputfile.txt>

2
好的解决方案,谢谢。但不幸的是,没有简单的方法来创建这个缓存。例如:echo 'cmake -DOPTION1=val <source folder>' > build.sh && bash build.sh 更简单... 如果 cmake 维护者能够创建类似 cmake -<param for dump cache to initial-cache.cmake> <initial-cache> -DOPTION1=val <source folder> 的东西,那将会更清晰明了。 - avtomaton
我有一些带有 . 字符的 CMake 变量。 我使用了 sed -r 's/([A-Za-z_0-9\.]+):([A-Z]+)=(.*)/set(\1 "\3" CACHE \2 "")/' - Benjamin
不得不修改一个使用分号作为分隔符的cmake项目。 从CMakeCache.txt文件中: CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo我的修改:`execute_process(COMMAND "${CMAKE_COMMAND}" "-N" "-LA" OUTPUT_VARIABLE cacheVars)` `string(REPLACE ";" "\;" cacheVars "${cacheVars}")` `string(REPLACE "\n" ";" cacheVars "${cacheVars}")` `string(REGEX REPLACE "([A-Za-z_0-9]+):([A-Z]+)=(.*)" "set(\\1 \"\\3\" CACHE \\2 \"\")\n" output "${variable}") if(CMAKE_MATCH_0) file(APPEND ${filename} "${output}")` - undefined

2

CMake 3.19 增加了对项目和用户级别的preset files支持。例如,如果您的顶层源目录中的CMakeUserPresets.json包含以下内容:

{
  "version: 4,
  "configurePresets": [
    {
      "name": "localdev",
      "displayName": "Local development",
      "description": "Local development",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "ENABLE_CCACHE": "ON",
        "GO_FASTER": "ON",
        "MY_LIB_INCLUDEDIR": "/usr/local/my-lib/include",
        "MY_LIB_LIBDIR": "/usr/local/my-lib/lib",
      },
      "environment": {
        "CMAKE_PREFIX_PATH": "/usr/local/foo"
      }
    }
  ]
}

您可以通过运行cmake --preset localdev来使用“localdev”预设。在撰写本文时,该格式仍在每个版本中发生变化,但它比-C <initial cache>选项更灵活和全面。


2

在另一台机器上复制此操作的最佳方法是使用-DSETTING=TRUE/FALSE参数。

如果您有很多与默认值不同的选项,可以使用脚本构建cmake调用。

例如:

#!/bin/bash
cmake -G "Unix Makefiles \
   -DOPTION1=TRUE
   -DOPTION2=FALSE

将帮助程序Bash脚本分发到其他机器。

3
我已经知道这种方法,但在调用期间输入的命令行值存储在哪里才能使其可再现?Bash脚本…无法在其他环境(例如Windows)中使用,因此这不是一个跨平台的解决方案。我找到了一种选项来预加载一个脚本以使用“cmake -C <initial-cache>”填充缓存文件。这些文件包含set()调用而不是命令行变量,并且似乎更容易以跨平台的方式处理许多设置。尽管如此,“+1”并感谢您的答案。 - Beachwalker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接