如何节省 C++ DLL 的构建时间

How to save the build time of a C++ DLL

我的项目是一个 C++ DLL(cmake 项目),它将方法从 c 接口公开到另一个 C# 项目, 我想在 c 接口中添加一个 methode getBuildTime() return 构建时间(确切的日期和时间),以便从 C# 项目中我们可以知道 DLL 的构建时间。
有办法做到这一点吗?
我不知道这是否有用,但我正在使用 git 作为版本控制系统

C++ 预处理器预定义了几个宏(向后兼容 C),包括 __DATE____TIME__。这些扩展为包含构建日期和时间的字符串文字(特别是预处理器在该特定文件上运行的日期和时间)。

您可能需要在每次更改时强制重建包含它们的编译单元。使用 make 可以用 .PHONY 完成,使用 cmake 看起来 add_custom_target 是票。

Add a target with no output so it will always be built.


除了使用 __DATE____TIME__ 来捕获编译器 运行 时,链接器还会在它创建的 DLL 的 PE header 中存储一个时间戳。无需配置即可实现此目的,但随后您必须编写代码来读取 PE header 并将时间戳转换为您喜欢的日期和时间格式。

C/C++ 代码中的构建时间可以通过 built-in 宏 __DATE____TIME__ 获得,例如做类似 string build_time = __DATE__ " " __TIME__;.

的事情

还需要在每次构建之前 touch 编辑包含这些宏用法的文件,以更改文件的修改时间。 touch is a unix command, which can be avaialble in Windows too through Cygwin 或其他方式。这是强制它重新编译以使用新日期所必需的。通过将 touch build_time.cpp 命令添加到 Pre-Build 事件来进行文件接触,它们应该位于项目配置中的某处。或者,您可以将 touching 添加到您的 make 文件中。或者,一些编译环境和可能的 MSVC 也可以配置始终重建哪些文件,这些文件在项目设置中进行了调整。

此外,如果您使用 git 版本控制系统,那么您可能希望同时使用上次 git 提交哈希和时间,或者代替上面的构建时间。 Git 提交哈希和时间有时比使用上面建议的构建时间更好,因为 git 哈希和时间在下一次提交之前的每个 re-compile 上保持相同,这确保了您的 DLL 构建时间仅在代码 changes/committed 时更改,这可能有助于编译可重现的 DLL。要支持 git 哈希和时间,请执行以下操作:

如果您的系统中有 unix echobash 以及 git 命令,例如通过为 Linux 安装 Cygwin 或新的本机 Windows 子系统,然后您可以在命令脚本 before_build.cmd 中执行下一步操作,您 运行 在构建之前,还有这个 shell 脚本在 Unix 系统上可以 运行 几乎无需修改:

linux_echo -n "" > cfg.h

linux_echo -n "#define GIT_COMMIT """ >> cfg.h
linux_bash -c "echo -n $(git rev-parse --short=8 HEAD)" >> cfg.h
linux_echo """" >> cfg.h

linux_echo -n "#define GIT_COMMIT_TIME """ >> cfg.h
linux_bash -c "echo -n $(git show -s --format=%%ci $(git rev-parse --short=8 HEAD) | tr -d '\n')" >> cfg.h
linux_echo """" >> cfg.h

linux_echo -n "#define COMPILE_TIME """ >> cfg.h
linux_bash -c 'echo -n $(date +"%%Y-%%m-%%d %%H:%%M:%%S %%z")' >> cfg.h
linux_echo """" >> cfg.h

你会得到 cfg.h 比如:

#define GIT_COMMIT "fe0a7891"
#define GIT_COMMIT_TIME "2020-05-13 17:42:55 +0100"
#define COMPILE_TIME "2020-05-13 18:20:28 +0100"

您可以在代码中使用这些配置文件和宏。

预处理器解决方案更简单,但如果您还需要提供构建系统的其他属性,则以下方法可能更方便。

创建生成源文件的cmake脚本文件。使用此脚本生成提供以下信息的源文件:

generate_timestamp.cmake

#parameter: OUTPUT_FILE
string(TIMESTAMP _TIMESTAMP "%Y-%m-%dT%H:%M:%S")
file(WRITE ${OUTPUT_FILE} "#include \"buildtime.h\"
const char* getBuildTime() {
    return \"${_TIMESTAMP}\";
}")

CMakeLists.txt

set(_BUILD_TIME_FILE buildtime.cpp)

add_library(mylib ${_BUILD_TIME_FILE} ...)
set_source_files_properties(${_BUILD_TIME_FILE} PROPERTIES GENERATED 1)

get_filename_component(_BUILD_TIME_FILE_ABSOLUTE ${_BUILD_TIME_FILE} ABSOLUTE)

# generate source using cmake script file
add_custom_target(buildtime_info COMMAND "${CMAKE_BUILD_TOOL}" -D "OUTPUT_FILE=${_BUILD_TIME_FILE_ABSOLUTE}" -P generate_timestamp.cmake)

# generate file before building mylib
add_dependencies(mylib buildtime_info)