[Cmake-commits] CMake branch, next, updated. v3.5.0-rc2-208-g52b66a9

Brad King brad.king at kitware.com
Thu Feb 18 10:31:11 EST 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  52b66a98c130825d7e84381a84528f794b3ec9d3 (commit)
       via  6727270b75eec4e379acd4a39f5003a316249c73 (commit)
      from  5887e756f47e5bf0ce6c4f077b4cbaec790c22b0 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=52b66a98c130825d7e84381a84528f794b3ec9d3
commit 52b66a98c130825d7e84381a84528f794b3ec9d3
Merge: 5887e75 6727270
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Feb 18 10:31:11 2016 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Thu Feb 18 10:31:11 2016 -0500

    Merge topic 'unix-timestamps' into next
    
    6727270b CMake: Extend TIMESTAMP sub-commands with new unix time format specifier


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6727270b75eec4e379acd4a39f5003a316249c73
commit 6727270b75eec4e379acd4a39f5003a316249c73
Author:     Jose-Luis Blanco-Claraco <joseluisblancoc at gmail.com>
AuthorDate: Tue Feb 16 21:48:56 2016 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Feb 18 10:30:13 2016 -0500

    CMake: Extend TIMESTAMP sub-commands with new unix time format specifier
    
    The new `%s` format specifier is substituted by file()/string()
    `TIMESTAMP` sub-commands with the number of seconds since unix-epoch
    (1970-01-01 00:00:00 UTC).
    
    Co-Author: Nils Gladitz <nilsgladitz at gmail.com>

diff --git a/Help/command/string.rst b/Help/command/string.rst
index 0361c74..3f4050e 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -277,6 +277,7 @@ specifiers:
    %j        The day of the current year (001-366).
    %m        The month of the current year (01-12).
    %M        The minute of the current hour (00-59).
+   %s        Seconds since midnight (UTC) 1-Jan-1970 (UNIX time).
    %S        The second of the current minute.
              60 represents a leap second. (00-60)
    %U        The week number of the current year (00-53).
diff --git a/Help/release/dev/unix-timestamps.rst b/Help/release/dev/unix-timestamps.rst
new file mode 100644
index 0000000..cdb0e5b
--- /dev/null
+++ b/Help/release/dev/unix-timestamps.rst
@@ -0,0 +1,6 @@
+unix-timestamps
+---------------
+
+* The :command:`string(TIMESTAMP)` and :command:`file(TIMESTAMP)`
+  commands gained support for the ``%s`` placeholder.  This is
+  the number of seconds since the UNIX Epoch.
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 6fd6ab7..1c795c4 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -12,9 +12,11 @@
 #include "cmTimestamp.h"
 
 #include <cstring>
+#include <cstdlib>
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sstream>
 
 //----------------------------------------------------------------------------
 std::string cmTimestamp::CurrentTime(
@@ -44,7 +46,7 @@ std::string cmTimestamp::FileModificationTime(const char* path,
 
 //----------------------------------------------------------------------------
 std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
-    std::string formatString, bool utcFlag)
+  std::string formatString, bool utcFlag) const
 {
   if(formatString.empty())
     {
@@ -79,12 +81,12 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
   for(std::string::size_type i = 0; i < formatString.size(); ++i)
     {
     char c1 = formatString[i];
-    char c2 = (i+1 < formatString.size()) ?
-      formatString[i+1] : static_cast<char>(0);
+    char c2 = (i + 1 < formatString.size()) ?
+      formatString[i + 1] : static_cast<char>(0);
 
     if(c1 == '%' && c2 != 0)
       {
-      result += AddTimestampComponent(c2, timeStruct);
+      result += AddTimestampComponent(c2, timeStruct, timeT);
       ++i;
       }
     else
@@ -97,8 +99,40 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
 }
 
 //----------------------------------------------------------------------------
+time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm &tm) const
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+  return _mkgmtime(&tm);
+#else
+  // From Linux timegm() manpage.
+
+  std::string tz_old = "TZ=";
+  if (const char* tz = cmSystemTools::GetEnv("TZ"))
+    {
+    tz_old += tz;
+    }
+
+  // The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
+  // It seems that "TZ=" does NOT work, at least under Windows
+  // with neither MSVC nor MinGW, so let's use explicit "TZ=UTC"
+
+  cmSystemTools::PutEnv("TZ=UTC");
+
+  tzset();
+
+  time_t result = mktime(&tm);
+
+  cmSystemTools::PutEnv(tz_old);
+
+  tzset();
+
+  return result;
+#endif
+}
+
+//----------------------------------------------------------------------------
 std::string cmTimestamp::AddTimestampComponent(
-  char flag, struct tm& timeStruct)
+  char flag, struct tm& timeStruct, const time_t timeT) const
 {
   std::string formatString = "%";
   formatString += flag;
@@ -117,6 +151,26 @@ std::string cmTimestamp::AddTimestampComponent(
     case 'y':
     case 'Y':
       break;
+    case 's': // Seconds since UNIX epoch (midnight 1-jan-1970)
+      {
+      // Build a time_t for UNIX epoch and substract from the input "timeT":
+      struct tm tmUnixEpoch;
+      memset(&tmUnixEpoch, 0, sizeof(tmUnixEpoch));
+      tmUnixEpoch.tm_mday = 1;
+      tmUnixEpoch.tm_year = 1970-1900;
+
+      const time_t unixEpoch = this->CreateUtcTimeTFromTm(tmUnixEpoch);
+      if (unixEpoch == -1)
+        {
+        cmSystemTools::Error("Error generating UNIX epoch in "
+          "STRING(TIMESTAMP ...). Please, file a bug report aginst CMake");
+        return std::string();
+        }
+
+      std::stringstream ss;
+      ss << static_cast<long int>(difftime(timeT, unixEpoch));
+      return ss.str();
+      }
     default:
       {
       return formatString;
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
index 24c1869..7c4b216 100644
--- a/Source/cmTimestamp.h
+++ b/Source/cmTimestamp.h
@@ -16,7 +16,7 @@
 #include <time.h>
 
 /** \class cmTimestamp
- * \brief Utility class to generate sting representation of a timestamp
+ * \brief Utility class to generate string representation of a timestamp
  *
  */
 class cmTimestamp
@@ -30,10 +30,13 @@ public:
     const std::string& formatString, bool utcFlag);
 
 private:
-  std::string CreateTimestampFromTimeT(time_t timeT,
-      std::string formatString, bool utcFlag);
+  time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
 
-  std::string AddTimestampComponent(char flag, struct tm& timeStruct);
+  std::string CreateTimestampFromTimeT(
+    time_t timeT, std::string formatString, bool utcFlag) const;
+
+  std::string AddTimestampComponent(
+    char flag, struct tm& timeStruct, time_t timeT) const;
 };
 
 
diff --git a/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake b/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake
new file mode 100644
index 0000000..a93e7f5
--- /dev/null
+++ b/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake
@@ -0,0 +1,22 @@
+string(TIMESTAMP timestamp "[%Y-%m-%d %H:%M:%S] %s" UTC)
+
+string(TIMESTAMP unix_time "%s")
+
+string(TIMESTAMP year "%Y" UTC)
+string(TIMESTAMP days "%j" UTC)
+
+# Doing proper date calculations here to verify unix timestamps
+# could be error prone.
+# At the very least use some safe lower and upper bounds to
+# see if we are somewhere in the right region.
+
+math(EXPR years_since_epoch "${year} - 1970")
+math(EXPR lower_bound "((${years_since_epoch} * 365) + ${days}) * 86400")
+math(EXPR upper_bound "((${years_since_epoch} * 366) + ${days}) * 86400")
+
+
+if(unix_time GREATER lower_bound AND unix_time LESS upper_bound)
+  message("~${unix_time}~")
+else()
+  message(FATAL_ERROR "${timestamp} unix time not in expected range [${lower_bound}, ${upper_bound}]")
+endif()
diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in
index 92e70c3..aba35fe 100644
--- a/Tests/CMakeTests/StringTest.cmake.in
+++ b/Tests/CMakeTests/StringTest.cmake.in
@@ -36,6 +36,8 @@ set(TIMESTAMP-IncompleteSpecifier-RESULT 0)
 set(TIMESTAMP-IncompleteSpecifier-STDERR "~foobar%~")
 set(TIMESTAMP-AllSpecifiers-RESULT 0)
 set(TIMESTAMP-AllSpecifiers-STDERR "~[0-9]+(;[0-9]+)*~")
+set(TIMESTAMP-UnixTime-RESULT 0)
+set(TIMESTAMP-UnixTime-STDERR "~[1-9][0-9]+~")
 
 include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake")
 check_cmake_test(String
@@ -58,6 +60,7 @@ check_cmake_test(String
   TIMESTAMP-UnknownSpecifier
   TIMESTAMP-IncompleteSpecifier
   TIMESTAMP-AllSpecifiers
+  TIMESTAMP-UnixTime
   )
 
 # Execute each test listed in StringTestScript.cmake:
@@ -68,9 +71,12 @@ set(number_of_tests_expected 70)
 include("@CMAKE_CURRENT_SOURCE_DIR@/ExecuteScriptTests.cmake")
 execute_all_script_tests(${scriptname} number_of_tests_executed)
 
+string(TIMESTAMP timestamp "[%Y-%m-%d %H:%M:%S] UTC %s" UTC)
+
 # And verify that number_of_tests_executed is at least as many as we know
 # about as of this writing...
 #
+message(STATUS "timestamp='${timestamp}'")
 message(STATUS "scriptname='${scriptname}'")
 message(STATUS "number_of_tests_executed='${number_of_tests_executed}'")
 message(STATUS "number_of_tests_expected='${number_of_tests_expected}'")

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list