【问题标题】:Output compile time stamp in Visual C++ executable?在 Visual C++ 可执行文件中输出编译时间戳?
【发布时间】:2010-09-06 17:57:20
【问题描述】:

如何将编译时间戳信息插入到使用 Visual C++ 2005 构建的可执行文件中?我希望在执行程序时能够输出这样的内容:

这个版本 XXXX 是在 dd-mm-yy, hh:mm 编译的。

其中日期和时间反映了项目的构建时间。它们不应随着程序的每次连续调用而改变,除非重新编译。

【问题讨论】:

标签: c++ visual-c++ execution compile-time


【解决方案1】:
__DATE__ 
__TIME__

预定义为 C99 标准的一部分,因此您应该可以使用。它们与预处理器一起运行一次。

【讨论】:

  • 请注意,对于像我这样想要在 VERSIONINFO 结构中添加日期的人来说,资源编译器无法使用这些定义。
【解决方案2】:

Visual C++ 还支持__TIMESTAMP__,这几乎正是您所需要的。话虽如此,关于构建时间戳的难点在于让它们保持最新,这意味着编译每次重建时都使用__TIMESTAMP__ 的文件。不过不确定是否有办法在 Visual C++ 中进行设置。

【讨论】:

    【解决方案3】:

    虽然不是您的确切格式,但 DATE 的格式为 Mmm dd yyyy,而 TIME 的格式为 hh:mm:ss。您可以像这样创建一个字符串,并在任何对您有意义的打印例程中使用它:

    const char *buildString = "This build XXXX was compiled at " __DATE__ ", " __TIME__ ".";
    

    (注意另一个答案:TIMESTAMP 只吐出源文件的修改日期/时间,而不是构建日期/时间。)

    【讨论】:

      【解决方案4】:

      我认为,使用 DATETIMETIMESTAMP 的建议解决方案就足够了。我确实建议获取一个包含在预构建步骤中的触摸程序,以便触摸包含预处理器变量使用的文件。触摸文件可确保其时间戳比上次编译时更新。这样,编译文件中的日期/时间也会随着每次重建而改变。

      【讨论】:

        【解决方案5】:

        __TIME____DATE__ 可以工作,但是有一些复杂性。

        如果您将这些定义放在一个 .h 文件中,并包含来自多个 .c/.cpp 文件的定义,则每个文件将根据其编译时间具有不同版本的日期/时间。因此,如果您希望在两个不同的地方使用日期/时间并且它们应该始终匹配,那么您就有麻烦了。如果您正在进行增量构建,其中一个文件可能会被重新构建,而另一个则不会,这再次导致时间戳可能大不相同。

        更好的方法是在 .h 文件中制作 GetBuildTimeStamp() 原型,并将 __TIME____DATE__ 宏放入 implementation(.c/.cpp) 文件中。这样,您可以在代码中的多个位置使用时间戳,并且它们将始终匹配。但是,您需要确保每次执行构建时都重新构建 .c/.cpp 文件。如果您正在进行干净的构建,那么此解决方案可能适合您。

        如果您正在进行增量构建,那么您需要确保每次构建都更新构建标记。在 Visual C++ 中,您可以使用 PreBuild 步骤来执行此操作 - 但是在这种情况下,我建议您不要在编译的 .c/.cpp 文件中使用 __DATE____TIME__,而是使用在以下位置读取的基于文本的文件程序执行期间的运行时。这使您的构建脚本可以快速更新时间戳(无需编译或链接),并且不需要您的 PreBuild 步骤来了解您的编译器标志或选项。

        【讨论】:

        • 另一种方法是拥有一个包含时间戳的特殊文件,并确保每次重建程序时用于构建的 makefile 都会重建该特定文件。这是我见过的大型软件项目最常见的解决方案。
        • 在我在预构建中涉及的 cpp 文件中创建时间戳函数,因为我希望它适用于增量构建。只是在标头中有一个宏并不会每次都更新我的应用程序中的时间戳。
        【解决方案6】:

        嗯...对于 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 日开始的秒数。

        【讨论】:

          猜你喜欢
          • 2011-08-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-03
          • 2020-10-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多