configure_file

将文件复制到另一个位置并修改其内容。

configure_file(<input> <output>
               [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
                FILE_PERMISSIONS <permissions>...]
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF]])

<input> 文件复制到 <output> 文件,同时对输入文件内容执行 转换

如果输入文件被修改,构建系统将重新运行 CMake 以重新配置该文件并再次生成构建系统。生成的文件的修改时间戳仅在后续 cmake 运行且内容发生变化时才会更新。

选项

选项包括

<input>

输入文件的路径。相对路径是相对于 CMAKE_CURRENT_SOURCE_DIR 的值来处理的。输入路径必须是一个文件,不能是目录。

<output>

输出文件或目录的路径。相对路径是相对于 CMAKE_CURRENT_BINARY_DIR 的值来处理的。如果路径命名了一个已存在的目录,输出文件将被置于该目录中,并使用与输入文件相同的文件名。如果路径中包含不存在的目录,它们将被创建。

NO_SOURCE_PERMISSIONS

3.19 版本新增。

不将输入文件的权限转移到输出文件。复制文件的权限默认为标准的 644 值 (-rw-r--r--)。

USE_SOURCE_PERMISSIONS

在 3.20 版本中添加。

将输入文件的权限转移到输出文件。如果没有指定这三个与权限相关的关键字(NO_SOURCE_PERMISSIONSUSE_SOURCE_PERMISSIONSFILE_PERMISSIONS),这已经是默认行为。USE_SOURCE_PERMISSIONS 关键字主要用于在调用处使预期行为更清晰。

FILE_PERMISSIONS <permissions>...

在 3.20 版本中添加。

忽略输入文件的权限,改用指定的 <permissions> 作为输出文件的权限。

COPYONLY

仅复制文件,不替换任何变量引用或其他内容。此选项不能与 NEWLINE_STYLE 一起使用。

ESCAPE_QUOTES

用反斜杠转义任何被替换的引号(C 风格)。

@ONLY

将变量替换限制为 @VAR@ 形式的引用。这对于配置使用 ${VAR} 语法的脚本非常有用。

NEWLINE_STYLE <style>

指定输出文件的换行符样式。对于 \n 换行,指定 UNIXLF;对于 \r\n 换行,指定 DOSWIN32CRLF。此选项不能与 COPYONLY 一起使用。

转换

输入文件内容中引用为 @VAR@${VAR}$CACHE{VAR} 以及引用为 $ENV{VAR}环境变量,将分别被替换为变量的当前值;如果变量未定义,则替换为空字符串。此外,以下形式的输入行

#cmakedefine VAR ...

将被替换为

#define VAR ...

/* #undef VAR */

具体取决于 VAR 在 CMake 中是否被设置为任何未被 if() 命令视为假常数的值。变量名之后(如果有)的 "..." 内容将按上述方式处理。

#cmakedefine VAR ... 形式的行不同,在 #cmakedefine01 VAR 形式的行中,VAR 本身将展开为 VAR 0VAR 1,而不是被赋值为 ...。因此,以下形式的输入行

#cmakedefine01 VAR

将被替换为

#define VAR 0

#define VAR 1

#cmakedefine01 VAR ... 形式的输入行将展开为 #cmakedefine01 VAR ... 0#cmakedefine01 VAR ... 1,这可能会导致未定义的行为。

3.10 版本新增:结果行(#undef 注释除外)可以在 # 字符与 cmakedefinecmakedefine01 单词之间使用空格和/或制表符进行缩进。这种空白缩进将保留在输出行中

#  cmakedefine VAR
#  cmakedefine01 VAR

如果定义了 VAR,则会被替换为

#  define VAR
#  define VAR 1

示例

考虑一个包含 foo.h.in 文件的源树

#cmakedefine FOO_ENABLE
#cmakedefine FOO_STRING "@FOO_STRING@"

相邻的 CMakeLists.txt 可以使用 configure_file 来配置头文件

option(FOO_ENABLE "Enable Foo" ON)
if(FOO_ENABLE)
  set(FOO_STRING "foo")
endif()
configure_file(foo.h.in foo.h @ONLY)

这将在对应此源目录的构建目录中创建一个 foo.h。如果 FOO_ENABLE 选项开启,配置后的文件将包含

#define FOO_ENABLE
#define FOO_STRING "foo"

否则它将包含

/* #undef FOO_ENABLE */
/* #undef FOO_STRING */

然后可以使用 target_include_directories() 命令将输出目录指定为包含目录

target_include_directories(<target> [SYSTEM] {INTERFACE|PUBLIC|PRIVATE} "${CMAKE_CURRENT_BINARY_DIR}")

以便源文件可以使用 #include <foo.h> 来包含该头文件。

另请参阅