我想使用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__
)?
答案 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之前脱机的情况下,此解决方案的想法是:
BUILD_TIME
创建一个string(TIMESTAMP ...
CMake变量。BUILD_TIME
记录到程序中的全局变量(您可以打印或其他内容)中。cmake -U BUILD_TIME
从CMake缓存中删除该变量。这意味着每次您构建项目时,都将检查依赖项,并清除CMake缓存,从而导致针对此时间戳库重新运行CMake。 该解决方案的缺点是,如果您有CI系统,则传递给CMake步骤的任何参数都需要记住也传递给构建步骤。