configure_file中的生成器表达式

时间:2018-07-11 10:22:00

标签: cmake

我们正在移植一些相当老的代码,当然我们现在想使用生成器表达式。 由configure_file生成的.pc文件现在包含-I$<INSTALL_INTERFACE:include>。 关于如何解析生成器表达式的唯一提示是使用

file(GENERATE 

这当然是在配置步骤中执行的,因此上面的表达式被解析为空字符串。

编辑: 这是一个例子 CMakeLists.txt:

cmake_minimum_required(VERSION 3.11)
project(test CXX)

add_library(foo SHARED main.cpp)

target_include_directories(foo PUBLIC $<INSTALL_INTERFACE:include>)

# now later buried deep in some functions

get_property( _include_dirs TARGET foo PROPERTY INCLUDE_DIRECTORIES )

configure_file(config.in config.out @ONLY)
# content of config.out is "include = -I$<INSTALL_INTERFACE:include>"

file(GENERATE OUTPUT config.out2 INPUT ${CMAKE_CURRENT_BINARY_DIR}/config.out)
# content of config.out2 is "include = -I"
# most likely because the INSTALL_INTERFACE isn't used when the file is generated

config.in:

include = @_include_dirs@

而main.cpp只是空的。

1 个答案:

答案 0 :(得分:5)

正如CMake文档所述,file (GENERATE ...)命令可以使用由生成器评估的生成器表达式。

生成文件

您可以让CMake直接使用自定义代码生成文件,而无需使用configure_file命令的解决方法。

单配置生成器

对于像 Makefiles 这样的单配置生成器,可以使用:

file (GENERATE
    OUTPUT "config.out" 
    CONTENT "include = -I$<INSTALL_INTERFACE:include>"
)

由于我的CMake代码必须与多配置生成器和单配置生成器一起使用,所以我没有专门测试代码。

单配置和多配置生成器

通常对于所有生成器,可以使用以下签名:

file (GENERATE
    OUTPUT "config_$<CONFIG>.out" 
    CONTENT "include = -I$<INSTALL_INTERFACE:include>"
)

由于与诸如 Visual Studio 之类的多配置生成器有关的命令的性质,这将在此变量CMAKE_CONFIGURATION_TYPES中指定的每种构建类型的构建文件夹中生成多个文件:

  • config_Debug.out
  • config_Release.out
  • config_RelWithDebInfo.out
  • ...
  • config_ .out

如果您未指定唯一的文件名,而CMake尝试生成文件,则会因错误而停止执行。

使用生成的文件

要使用以前生成的文件,取决于您的需要。首先,文件将在 configuration 阶段之后存在。

单配置生成器

要在具有常量名称(例如config.out)的单配置生成器方案中使用生成的文件,则无需进行其他工作。

单配置和多配置生成器

对于多配置生成器,它略有不同。由于您必须在构建时使用generator expressions来访问适当的文件。如果您有支持生成器表达式的CMake指令,则只需使用文件名config_$<CONFIG>.out

但是,如果无论构建类型(例如config.out)如何都需要将文件命名为完全相同的文件,它将变得有些棘手。

首先,您必须通过使用add_custom_command并指定 OUTPUT 参数来告诉CMake应该有一个名为config.out的文件:

add_custom_command (
    COMMAND ${CMAKE_COMMAND} "-E" "copy_if_different" "config_$<CONFIG>.out" "config.out"
    VERBATIM
    PRE_BUILD
    DEPENDS  "config_$<CONFIG>.out"
    OUTPUT   "config.out"
    COMMENT  "creating config.out file ({event: PRE_BUILD}, {filename: config.out})"
)

CMake将在内部创建一个文件依赖项,每次引用文件名config.out时,它将确保执行 add_custom_command

但这并不是在每种情况下都可行,因为这取决于应使用该文件的进一步说明。

根据所使用的命令,现在可以将文件config.out指定为某些命令(例如target_sources等)的输入,并且CMake将在文件依赖级别上进行检测,以确保config.out的存在。

如果要生成未在文件依赖级别上引用的文件(例如versioninfo.txt),则必须确保每次执行构建目标时CMake都执行 add_custom_command 通过目标依赖性:

add_custom_target ("generate_config_out" DEPENDS "config.out")
add_dependencies ("MY_LIBRARY_TARGET" "generate_config_out")

每次CMake构建MY_LIBRARY_TARGET目标时,它都会先前构建generate_config_out目标,而目标又取决于CMake将在文件依赖级别上处理的config.out