【发布时间】:2010-09-06 17:57:20
【问题描述】:
如何将编译时间戳信息插入到使用 Visual C++ 2005 构建的可执行文件中?我希望在执行程序时能够输出这样的内容:
这个版本 XXXX 是在 dd-mm-yy, hh:mm 编译的。
其中日期和时间反映了项目的构建时间。它们不应随着程序的每次连续调用而改变,除非重新编译。
【问题讨论】:
标签: c++ visual-c++ execution compile-time
如何将编译时间戳信息插入到使用 Visual C++ 2005 构建的可执行文件中?我希望在执行程序时能够输出这样的内容:
这个版本 XXXX 是在 dd-mm-yy, hh:mm 编译的。
其中日期和时间反映了项目的构建时间。它们不应随着程序的每次连续调用而改变,除非重新编译。
【问题讨论】:
标签: c++ visual-c++ execution compile-time
__DATE__
__TIME__
预定义为 C99 标准的一部分,因此您应该可以使用。它们与预处理器一起运行一次。
【讨论】:
Visual C++ 还支持__TIMESTAMP__,这几乎正是您所需要的。话虽如此,关于构建时间戳的难点在于让它们保持最新,这意味着编译每次重建时都使用__TIMESTAMP__ 的文件。不过不确定是否有办法在 Visual C++ 中进行设置。
【讨论】:
虽然不是您的确切格式,但 DATE 的格式为 Mmm dd yyyy,而 TIME 的格式为 hh:mm:ss。您可以像这样创建一个字符串,并在任何对您有意义的打印例程中使用它:
const char *buildString = "This build XXXX was compiled at " __DATE__ ", " __TIME__ ".";
(注意另一个答案:TIMESTAMP 只吐出源文件的修改日期/时间,而不是构建日期/时间。)
【讨论】:
我认为,使用 DATE、TIME 或 TIMESTAMP 的建议解决方案就足够了。我确实建议获取一个包含在预构建步骤中的触摸程序,以便触摸包含预处理器变量使用的文件。触摸文件可确保其时间戳比上次编译时更新。这样,编译文件中的日期/时间也会随着每次重建而改变。
【讨论】:
__TIME__ 和 __DATE__ 可以工作,但是有一些复杂性。
如果您将这些定义放在一个 .h 文件中,并包含来自多个 .c/.cpp 文件的定义,则每个文件将根据其编译时间具有不同版本的日期/时间。因此,如果您希望在两个不同的地方使用日期/时间并且它们应该始终匹配,那么您就有麻烦了。如果您正在进行增量构建,其中一个文件可能会被重新构建,而另一个则不会,这再次导致时间戳可能大不相同。
更好的方法是在 .h 文件中制作 GetBuildTimeStamp() 原型,并将 __TIME__ 和 __DATE__ 宏放入 implementation(.c/.cpp) 文件中。这样,您可以在代码中的多个位置使用时间戳,并且它们将始终匹配。但是,您需要确保每次执行构建时都重新构建 .c/.cpp 文件。如果您正在进行干净的构建,那么此解决方案可能适合您。
如果您正在进行增量构建,那么您需要确保每次构建都更新构建标记。在 Visual C++ 中,您可以使用 PreBuild 步骤来执行此操作 - 但是在这种情况下,我建议您不要在编译的 .c/.cpp 文件中使用 __DATE__ 和 __TIME__,而是使用在以下位置读取的基于文本的文件程序执行期间的运行时。这使您的构建脚本可以快速更新时间戳(无需编译或链接),并且不需要您的 PreBuild 步骤来了解您的编译器标志或选项。
【讨论】:
嗯...对于 Visual C++,有一个名为 __ImageBase 的内置符号。具体来说:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
您可以在运行时检查以确定 PE 标头中的时间戳:
const IMAGE_NT_HEADERS *nt_header= (const IMAGE_NT_HEADERS *)((char *)&__ImageBase + __ImageBase.e_lfanew);
并使用nt_header->FileHeader.TimeDateStamp 获取时间戳,即从 1970 年 1 月 1 日开始的秒数。
【讨论】: