我正在尝试将构建日期嵌入到源文件中,以便每次构建特定目标时,都会刷新嵌入的日期,而无需在每次构建整个项目时重新生成。
即我有一个头文件builddate.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
自定义命令听起来是个好主意,但文档指出,在为Visual Studio以外的生成器PRE_LINK
命令之前,即在编译源代码之后,会调用该命令。这似乎使这不适合此目的,因为在编译源代码时需要标头。
在 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
作为生成标头的命令。
前段时间,我写了一个cmake makro。它通过执行 Cversion.cmake 在当前构建目录中添加自定义命令以生成版本.cpp。 仅当依赖项发生更改时,才会执行文件的生成。 使用 cmake-generator-expressions 时,依赖项设置为目标减去其自身(文件(的依赖项。
可以通过添加 libs 依赖项来生成新版本文件来改进它。
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()