2

我正在尝试将构建日期嵌入到源文件中,以便每次构建特定目标时都会刷新嵌入日期,而不会在每次构建整个项目时重新生成。

即我有一个由具有一组sbuilddate.h的命令生成的头文件。#define然后从其他源文件中包含此头文件。

我的第一次尝试是这样的:

add_custom_target(builddate COMMAND <command that generates header file>)
add_library(mylibrary ...)
add_dependencies(mylibrary builddate)

这样可以正确生成头文件,但是每次都会生成头文件,无论mylibrary目标是否需要重建。

尝试使用自定义命令,即

add_custom_command(OUTPUT builddate.h COMMAND <command that generates header file>)
add_library(mylibrary ... builddate.h)

正确生成一次标头,但如果mylibrary重新构建目标,则不会重新生成标头,因为builddate.h它已经是最新的。

这感觉应该是相当普遍的事情,但我无法弄清楚自定义命令和目标的什么咒语会给我想要的效果。我想要的是每次mylibrary构建目标时调用该命令,如果没有任何更改或构建不相关的目标(例如使用 的可执行文件mylibrary),则不会进行虚假重建。

使用PRE_BUILD自定义命令听起来是个好主意,但文档声明这会在PRE_LINKVisual Studio 以外的生成器的命令之前调用,即编译源代码之后。这似乎会使这不适合此目的,因为在编译源代码时需要标头。

4

2 回答 2

2

在https://cmake.org/pipermail/cmake/2010-October/040247.html找到一个旧线程,建议调用 CMake 的--build目标作为PRE_LINK命令:

# This is the library that I want to build
add_library(mylibrary ...)

# Set up a library that contains the code depending on the build date
# Use an OBJECT library because we don't need it to be a full static lib
# we just want to build some source that would "normally" have been part of mylibrary
add_library(builddate OBJECT EXCLUDE_FROM_ALL codethatusesbuilddate.cpp)

# Add a PRE_LINK command for mylibrary so that prior to linking we
# 1. Generate the builddate.h header
# 2. Call CMake to build the builddate library we just set up
add_custom_command(
    TARGET mylibrary PRE_LINK
    COMMAND <command that generates builddate.h>
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target builddate
)

# We also need to link with the library
# NOTE: uses the generator expression to link with the output files rather than the target
# to avoid CMake setting up a dependency from builddate to mylibrary which I think
# would cause builddate to be built prior to building mylibrary, but at that point we
# haven't generated the header yet. Which we could fix, but then we'd just build it twice
target_link_libraries(mylibrary PRIVATE $<TARGET_OBJECTS:builddate>)


这感觉有点尴尬,但它似乎工作。

脚注:使用 CMake 很容易生成标头,即首先configure_file或类似地创建一个 CMake 脚本来进行生成,然后${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/generated_cmake_file.cmake作为命令调用以生成标头。

于 2020-05-15T07:44:16.003 回答
1

前段时间,我写了一个cmake makro。它添加了自定义命令,通过执行 Cversion.cmake 在当前构建目录中生成 version.cpp。只有在依赖关系发生变化时才会执行文件的生成。使用 cmake-generator-expressions 依赖项设置为目标的依赖项减去它自己的(文件)。

可以通过添加库依赖项来生成新的版本文件来改进它。

macro(add_versioning T)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
        COMMAND ${CMAKE_COMMAND} "-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
        -P "${PROJECT_SOURCE_DIR}/Version/CVersion.cmake"
        MAIN_DEPENDENCY "${PROJECT_SOURCE_DIR}/Version/version.cpp.in"
        DEPENDS "$<FILTER:$<TARGET_OBJECTS:${T}>,EXCLUDE,version.cpp.+$>")

target_include_directories(${T} PUBLIC "${PROJECT_SOURCE_DIR}/Version")
target_sources(${T} PUBLIC "${PROJECT_SOURCE_DIR}/Version/version.h" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")

endmacro()
于 2020-08-05T20:33:40.883 回答