C++获取程序编译时间
•C++
1297
0
使用C++语言编写的程序,如何获取程序的编译时间呢?
编译时会修改二进制文件的“创建时间”信息,因此该时间可以看作程序编译的时间。
但是,如果将该程序文件复制、网络发送给其他机器,“创建时间”信息可能会发生改变。
__DATE__
和__TIME__
宏是C/C++内置的宏,分别表示进行预处理时的日期和时间。
__DATE__
会预处理为一个日期字符串,例如May 22 2023
。
__TIME__
会预处理为一个时间字符串,例如01:38:46
。
首先定义一些宏,对__DATE__
和__TIME__
进行处理,提取年、月、日、时、分、秒,在此基础上转为unix
时间戳(time_t
)。
/**
* @file build_date_time.h
* @brief 处理宏 __DATE__ 和 __TIME__.
* @author Leopard-C (leopard.c@outlook.com)
* @version 0.1
* @date 2023-05-22
*
* @copyright Copyright (c) 2023-present, Jinbao Chen.
*/
#ifndef IC_MACRO_BUILD_DATE_TIME_H_
#define IC_MACRO_BUILD_DATE_TIME_H_
#include <stdio.h>
#include <time.h>
// Example of __DATE__ string: "May 22 2023"
// 01234567890
#define BUILD_YEAR_CH0 (__DATE__[ 7])
#define BUILD_YEAR_CH1 (__DATE__[ 8])
#define BUILD_YEAR_CH2 (__DATE__[ 9])
#define BUILD_YEAR_CH3 (__DATE__[10])
#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')
#define BUILD_MONTH_CH0 \
((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0')
#define BUILD_MONTH_CH1 \
( \
(BUILD_MONTH_IS_JAN) ? '1' : \
(BUILD_MONTH_IS_FEB) ? '2' : \
(BUILD_MONTH_IS_MAR) ? '3' : \
(BUILD_MONTH_IS_APR) ? '4' : \
(BUILD_MONTH_IS_MAY) ? '5' : \
(BUILD_MONTH_IS_JUN) ? '6' : \
(BUILD_MONTH_IS_JUL) ? '7' : \
(BUILD_MONTH_IS_AUG) ? '8' : \
(BUILD_MONTH_IS_SEP) ? '9' : \
(BUILD_MONTH_IS_OCT) ? '0' : \
(BUILD_MONTH_IS_NOV) ? '1' : \
(BUILD_MONTH_IS_DEC) ? '2' : \
/* error default */ '?' \
)
#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0')
#define BUILD_DAY_CH1 (__DATE__[ 5])
// Example of __TIME__ string: "01:38:46"
// 01234567
#define BUILD_HOUR_CH0 (__TIME__[0])
#define BUILD_HOUR_CH1 (__TIME__[1])
#define BUILD_MIN_CH0 (__TIME__[3])
#define BUILD_MIN_CH1 (__TIME__[4])
#define BUILD_SEC_CH0 (__TIME__[6])
#define BUILD_SEC_CH1 (__TIME__[7])
// DateTime. Example: 2022-05-22 01:38:46
#define BUILD_DATE_TIME \
{\
BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3,\
'-',\
BUILD_MONTH_CH0, BUILD_MONTH_CH1,\
'-',\
BUILD_DAY_CH0, BUILD_DAY_CH1,\
' ',\
BUILD_HOUR_CH0, BUILD_HOUR_CH1,\
':',\
BUILD_MIN_CH0, BUILD_MIN_CH1,\
':',\
BUILD_SEC_CH0, BUILD_SEC_CH1,\
'\0'\
}
extern const char g_build_date_time[];
extern time_t g_build_timestamp;
#endif // IC_MACRO_BUILD_DATE_TIME_H_
// build_date_time.cpp
#include "build_date_time.h"
static time_t get_build_timestamp() {
struct tm tm_;
tm_.tm_year = ((BUILD_YEAR_CH0 - '0') * 1000 + (BUILD_YEAR_CH1 - '0') * 100 + (BUILD_YEAR_CH2 - '0') * 10 + (BUILD_YEAR_CH3 - '0')) - 1900;
tm_.tm_mon = ((BUILD_MONTH_CH0 - '0') * 10 + (BUILD_MONTH_CH1 - '0')) - 1;
tm_.tm_mday = (BUILD_DAY_CH0 - '0') * 10 + (BUILD_DAY_CH1 - '0');
tm_.tm_hour = (BUILD_HOUR_CH0 - '0') * 10 + (BUILD_HOUR_CH1 - '0');
tm_.tm_min = (BUILD_MIN_CH0 - '0') * 10 + (BUILD_MIN_CH1 - '0');
tm_.tm_sec = (BUILD_SEC_CH0 - '0') * 10 + (BUILD_SEC_CH1 - '0');
tm_.tm_isdst = 0;
return mktime(&tm_);
}
const char g_build_date_time[] = BUILD_DATE_TIME;
time_t g_build_timestamp = get_build_timestamp();
定义了两个全局变量 g_build_date_time
和 g_build_timestamp
。
使用示例:
// foo.cpp
#include "build_date_time.h"
void Foo() {
std::cout << g_build_date_time << std::endl; // 2022-05-22 01:38:46
std::cout << g_build_timestamp << std::endl; // 1653154726
}
现在还有一个问题,如何确保每次(增量/全量)编译的时候,都会更新这个时间呢?
一个可行的方法时,每次需要编译前,就更新build_date_time.cpp
(也可以更新build_date_time.h
)文件的时间戳,使该文件被重新编译。
# 项目属性 -> 生成事件 -> 生成前事件 -> 命令行
# 注意:路径必须使用反斜杠
copy /b src\util\build_date_time.cpp +,, src\util\build_date_time.cpp
$(shell touch src/util/build_date_time.cpp)
before_build(function (target)
os.exec("touch src/util/build_date_time.cpp")
end)
Thanks for reading!
作者:iCrystal
邮箱:leopard.c@outlook.com
博客:https://blog.icrystal.top
GitHub: https://github.com/Leopard-C