使用cmake编译日期和时间

时间:2014-06-18 18:44:10

标签: c++ c 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__)?

5 个答案:

答案 0 :(得分: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")

答案 1 :(得分: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_DIRECTORIES (${CMAKE_BINARY_DIR})),并且每当使用_TIMEZ_时你想拥有ISO 8601格式的构建时间戳(或者,事实上,无论你喜欢什么:你可以自己指定,see CMake documentation for STRING command usage)。

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

您可以通过支持我的功能请求发布一些评论来显示您需要的内容,从而帮助实现这一目标。

答案 2 :(得分:2)

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

答案 3 :(得分: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"));

答案 4 :(得分:0)

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

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

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

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