+-
使用cmake编译日期和时间

我想使用cmake在发布版本的情况下将VERSION设置为发布版本,否则使用编译时。

使用make进行开发构建时,很容易获得编译时间

-DVERSION=`date +%Y-%m-%d_%H:%M`

这可以通过c / c ++源代码直接使用。不幸的是,我还没有发现使用cmake时是如何实现的。

string(TIMESTAMP VERSION "%Y-%m-%d %H:%M")
add_definitions(-DVERSION="${VERSION}")

将VERSION设置为执行cmake的时间。如何在使用cmake时将VERSION设置为编译时间(以避免在没有RELEASE标志的情况下不得不使用__DATE____TIME__)?

19
投票

对于相对较新版本的CMake(> = 2.8.11):

string(TIMESTAMP {output variable} [{format string}] [UTC])

(见http://www.cmake.org/cmake/help/v3.0/command/string.html)。例如:

string(TIMESTAMP TODAY "%Y%m%d")
6
投票

我在第一次运行CMake时的跨平台解决方案在二进制目录中创建了一个文件timestamp.cmake,并定义了运行生成文件的目标timestamp。文件timestamp.cmake使用STRING CMake命令形成ISO 8601时间戳字符串,并将其写入文件timestamp.h,前面加上#define _TIMEZ_预处理器指令(使用一个前导下划线定义是可以的;定义两个前导下划线不应该是用户定义的)。

在主CMake文件中包含以下内容。

# build time in UTC ISO 8601
FILE (WRITE ${CMAKE_BINARY_DIR}/timestamp.cmake "STRING(TIMESTAMP TIMEZ UTC)\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(WRITE timestamp.h \"#ifndef TIMESTAMP_H\\n\")\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(APPEND timestamp.h \"#define TIMESTAMP_H\\n\\n\")\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(APPEND timestamp.h \"#define _TIMEZ_ \\\"\${TIMEZ}\\\"\\n\\n\")\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(APPEND timestamp.h \"#endif // TIMESTAMP_H\\n\")\n")
ADD_CUSTOM_TARGET (
    timestamp
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/timestamp.cmake
    ADD_DEPENDENCIES ${CMAKE_BINARY_DIR}/timestamp.cmake)

然后使用ADD_DEPENDENCIES CMake命令使您的主目标(可能是主可执行文件)依赖于timestamp目标。它始终被CMake视为过时,因此每次主目标重建时都会刷新它,并根据请求刷新构建时间。

ADD_DEPENDENCIES (${CMAKE_BINARY_DIR}/${BINARY_NAME} timestamp)

如果需要,可以使用此命令指定由空格分隔的多个其他依赖项。

然后你可以只是#include "timestamp.h"(假设CMake二进制目录在include路径中,通常是。如果不是,那很简单:INCLUDE_DIRECTORIES (${CMAKE_BINARY_DIR})),并且每当你想要ISO 8601格式的构建时间戳时使用_TIMEZ_(或者,事实上,无论你喜欢什么:你可以自己指定,see CMake documentation for STRING command usage)。

这可以通过直接(手动)创建文件timestamp.cmake并将其添加到您的代码存储库来简化,但我认为它不够干净。 CMake的一般缺点是你不能在CMake后端的阶段访问时间戳字符串形成过程(STRING CMake命令中使用的那个),无论它是什么(例如,GNU make)运行所以必须使用单独的CMake文件并在该阶段调用它。如果您可以在“CMake命令模式”(cmake -E类型的调用)中调用CMake时间戳字符串形成过程,例如,像这样:cmake -E date [format] [UTC],但是唉,这可以做得更简单和更清晰。我有filed a ticket in the CMake's Mantis bug tracker。

您可以通过支持我的功能请求发布一些评论来显示您需要多少这样的信息来帮助实现这一目标。

2
投票

也许您可以在代码中使用编译器宏__DATE__ __TIME__而不是从cmake获取它。值得一提的是你需要做clean / make来更新这些值(因为GCC嵌入它,如果对象已经被编译,它不会再次编译,所以没有日期/时间更改)

0
投票

我最终得到以下解决方案:

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    add_custom_target(
        "linktimestamp"
        ALL
        COMMAND date +'%Y-%m-%d %H:%M:%S' > "linktimestamp.txt"
        COMMAND objcopy --input binary --output elf64-x86-64 --binary-architecture i386:x86-64 --rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA "linktimestamp.txt" "linktimestamp.o"
        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
        COMMENT "link timestamp: ${LINK_TIMESTAMP}"
        )
else()
    add_custom_target(
        "linktimestamp"
        ALL
        COMMAND date +'%Y-%m-%d %H:%M:%S' > "linktimestamp.txt"
        COMMAND objcopy --input binary --output elf32-i386 --binary-architecture i386 --rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA "linktimestamp.txt" "linktimestamp.o"
        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
        COMMENT "link timestamp: ${LINK_TIMESTAMP}"
        )
endif()
#add_dependencies(${PROJECT_NAME} "linktimestamp")
target_link_libraries(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/linktimestamp.o")

二进制目标${PROJECT_NAME}每次都与更新的部分相关联。

获取此时间戳的Qt代码:

extern char _binary_linktimestamp_txt_start[];
//extern char _binary_linktimestamp_txt_end[];
extern char _binary_linktimestamp_txt_size[];
const auto text = QByteArray::fromRawData(_binary_linktimestamp_txt_start, reinterpret_cast< std::intptr_t >(_binary_linktimestamp_txt_size));
qDebug() << QDateTime::fromString(QString::fromUtf8(text), "yyyy-MM-dd HH:mm:ss\n"));
0
投票

我不久前遇到了同样的问题,最后写了this repo作为解决方案。只需将其添加为CMake子目录,build_date_str将包含程序的链接时间。

在github在stackoverflow之前脱机的情况下,这个解决方案的想法是:

使用 BUILD_TIME创建 string(TIMESTAMP ... CMake变量,如上述解决方案中所述。 编译一个小型库,将 BUILD_TIME记录到程序中的全局变量(可以打印或其他)。 使该库的构建依赖于使用 cmake -U BUILD_TIME从CMake缓存中删除变量的自定义目标。

这意味着每次构建项目时,都会检查依赖项,并清除CMake缓存,从而导致为此时间戳库重新运行CMake。此解决方案的缺点是,如果您有CI系统,您传递到CMake步骤的任何参数都需要记住也要传递给构建步骤。