我正在使用 CMake 构建一个 C++ 项目(在 Linux 上)。该项目由许多子项目组成,每个子项目都可以调用一个函数来创建一个有用的link_date.c
源文件,其中包含链接发生时的时间戳。我使用它作为一种可靠地将构建时间嵌入到二进制文件中的方法,而不管自上次构建以来发生了哪些源更改。
这个函数是这样声明的:
function(add_link_date TARGET)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/link_date.c.in "
const char *link_date() { return(\"@LINK_DATE@\"); }
")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/link_date.cmake "
EXECUTE_PROCESS(
COMMAND date
OUTPUT_VARIABLE LINK_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
CONFIGURE_FILE(\${SRC} \${DST} @ONLY)
")
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/link_date.c
COMMAND ${CMAKE_COMMAND} -DSRC=link_date.c.in -DDST=link_date.c
-P link_date.cmake
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/link_date.c.in)
add_library(link_date-${TARGET} STATIC EXCLUDE_FROM_ALL link_date.c)
target_link_libraries(${TARGET} link_date-${TARGET})
add_custom_command(
TARGET ${TARGET}
PRE_LINK
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/link_date.c.in
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR} --target link_date-${TARGET})
endfunction()
该函数为调用它的每个目标创建一个link_date.c.in
模板,然后使用该模板link_date.c
为该目标创建。然后将其添加到特定于目标的库中,然后将其与目标可执行文件链接。finaladd_custom_command
用于确保每次 CMake 即将链接目标可执行文件时都重建 link_date 库。我从这里得到了这个的原始代码。
关键是它总是将构建时间戳注入到可执行文件中,无论是谁构建它——开发人员、CI 管道等。它与 Makefiles 生成器配合得非常好,我已经使用它超过 12 个月了,没有任何问题.
最近我一直在考虑更新我们的构建以使用 Ninja,因为它在我的大多数管道中都明显更快,但是在这个项目中它遇到了一个问题,特别是最后COMMAND
一个add_custom_command
(PRE_LINK) 语句的最后一个,它运行子构建。这有cd
ing 到调用的子项目的 build 子目录的效果add_link_date
,但是因为 CMake 只build.ninja
在 build 目录的顶部生成了一个 Ninja 文件,所以 childcmake --build
失败了,因为build.ninja
这个子项目目录中没有。
有没有办法修改这个过程以与忍者一起工作?
我知道并不是每个 CMake 项目都可以从 Makefiles 迁移到 Ninja,但是这是我在这个特定项目中遇到的唯一真正的障碍,所以很高兴找到一个解决方法。