diff options
author | Brad King <brad.king@kitware.com> | 2022-01-28 14:38:57 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2022-01-28 14:39:03 (GMT) |
commit | 4ff6ea0f2fcbac87c3317623e7de41cdd506ab17 (patch) | |
tree | bdc2b26ab7879bcd5c3610a355c954b975e197bd /Source | |
parent | c2f75492fa78d321dbd8909571672e654d4213a1 (diff) | |
parent | c050d6a01e14500903619589e69a973f1215d109 (diff) | |
download | CMake-4ff6ea0f2fcbac87c3317623e7de41cdd506ab17.zip CMake-4ff6ea0f2fcbac87c3317623e7de41cdd506ab17.tar.gz CMake-4ff6ea0f2fcbac87c3317623e7de41cdd506ab17.tar.bz2 |
Merge topic 'timestamp-microseconds'
c050d6a01e string(TIMESTAMP): add %f specifier for microseconds
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !6910
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmTimestamp.cxx | 60 | ||||
-rw-r--r-- | Source/cmTimestamp.h | 8 |
2 files changed, 57 insertions, 11 deletions
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 3826577..e2b6c20 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -17,18 +17,27 @@ #include <cstdlib> #include <cstring> #include <sstream> +#include <utility> #ifdef __MINGW32__ # include <libloaderapi.h> #endif +#include <cm3p/uv.h> + #include "cmStringAlgorithms.h" #include "cmSystemTools.h" std::string cmTimestamp::CurrentTime(const std::string& formatString, bool utcFlag) const { - time_t currentTimeT = time(nullptr); + // get current time with microsecond resolution + uv_timeval64_t timeval; + uv_gettimeofday(&timeval); + auto currentTimeT = static_cast<time_t>(timeval.tv_sec); + auto microseconds = static_cast<uint32_t>(timeval.tv_usec); + + // check for override via SOURCE_DATE_EPOCH for reproducible builds std::string source_date_epoch; cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch); if (!source_date_epoch.empty()) { @@ -38,12 +47,15 @@ std::string cmTimestamp::CurrentTime(const std::string& formatString, cmSystemTools::Error("Cannot parse SOURCE_DATE_EPOCH as integer"); exit(27); } + // SOURCE_DATE_EPOCH has only a resolution in the seconds range + microseconds = 0; } if (currentTimeT == time_t(-1)) { return std::string(); } - return this->CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); + return this->CreateTimestampFromTimeT(currentTimeT, microseconds, + formatString, utcFlag); } std::string cmTimestamp::FileModificationTime(const char* path, @@ -57,11 +69,32 @@ std::string cmTimestamp::FileModificationTime(const char* path, return std::string(); } - time_t mtime = cmsys::SystemTools::ModifiedTime(real_path); - return this->CreateTimestampFromTimeT(mtime, formatString, utcFlag); + // use libuv's implementation of stat(2) to get the file information + time_t mtime = 0; + uint32_t microseconds = 0; + uv_fs_t req; + if (uv_fs_stat(nullptr, &req, real_path.c_str(), nullptr) == 0) { + mtime = static_cast<time_t>(req.statbuf.st_mtim.tv_sec); + // tv_nsec has nanosecond resolution, but we truncate it to microsecond + // resolution in order to be consistent with cmTimestamp::CurrentTime() + microseconds = static_cast<uint32_t>(req.statbuf.st_mtim.tv_nsec / 1000); + } + uv_fs_req_cleanup(&req); + + return this->CreateTimestampFromTimeT(mtime, microseconds, formatString, + utcFlag); +} + +std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, + std::string formatString, + bool utcFlag) const +{ + return this->CreateTimestampFromTimeT(timeT, 0, std::move(formatString), + utcFlag); } std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, + const uint32_t microseconds, std::string formatString, bool utcFlag) const { @@ -95,7 +128,8 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, : static_cast<char>(0); if (c1 == '%' && c2 != 0) { - result += this->AddTimestampComponent(c2, timeStruct, timeT); + result += + this->AddTimestampComponent(c2, timeStruct, timeT, microseconds); ++i; } else { result += c1; @@ -144,9 +178,9 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const #endif } -std::string cmTimestamp::AddTimestampComponent(char flag, - struct tm& timeStruct, - const time_t timeT) const +std::string cmTimestamp::AddTimestampComponent( + char flag, struct tm& timeStruct, const time_t timeT, + const uint32_t microseconds) const { std::string formatString = cmStrCat('%', flag); @@ -180,13 +214,19 @@ std::string cmTimestamp::AddTimestampComponent(char flag, const time_t unixEpoch = this->CreateUtcTimeTFromTm(tmUnixEpoch); if (unixEpoch == -1) { cmSystemTools::Error( - "Error generating UNIX epoch in " - "STRING(TIMESTAMP ...). Please, file a bug report against CMake"); + "Error generating UNIX epoch in string(TIMESTAMP ...) or " + "file(TIMESTAMP ...). Please, file a bug report against CMake"); return std::string(); } return std::to_string(static_cast<long int>(difftime(timeT, unixEpoch))); } + case 'f': // microseconds + { + // clip number to 6 digits and pad with leading zeros + std::string microsecs = std::to_string(microseconds % 1000000); + return std::string(6 - microsecs.length(), '0') + microsecs; + } default: { return formatString; } diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h index 0e2c200..ada5006 100644 --- a/Source/cmTimestamp.h +++ b/Source/cmTimestamp.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstdint> #include <ctime> #include <string> @@ -23,9 +24,14 @@ public: std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString, bool utcFlag) const; + std::string CreateTimestampFromTimeT(time_t timeT, uint32_t microseconds, + std::string formatString, + bool utcFlag) const; + private: time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const; std::string AddTimestampComponent(char flag, struct tm& timeStruct, - time_t timeT) const; + time_t timeT, + uint32_t microseconds = 0) const; }; |