Merge topic 'fix-find-make-program' into release-3.19

ef91fb02f3 cmGlobalGenerator: FindMakeProgram() at a generator-specific time

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Frank Dana <ferdnyc@gmail.com>
Merge-request: !5529
diff --git a/Source/cmFileTime.cxx b/Source/cmFileTime.cxx
index 96c70fe..0606baf 100644
--- a/Source/cmFileTime.cxx
+++ b/Source/cmFileTime.cxx
@@ -24,13 +24,13 @@
   }
 #  if CMake_STAT_HAS_ST_MTIM
   // Nanosecond resolution
-  this->NS = fst.st_mtim.tv_sec * NsPerS + fst.st_mtim.tv_nsec;
+  this->Time = fst.st_mtim.tv_sec * UtPerS + fst.st_mtim.tv_nsec;
 #  elif CMake_STAT_HAS_ST_MTIMESPEC
   // Nanosecond resolution
-  this->NS = fst.st_mtimespec.tv_sec * NsPerS + fst.st_mtimespec.tv_nsec;
+  this->Time = fst.st_mtimespec.tv_sec * UtPerS + fst.st_mtimespec.tv_nsec;
 #  else
   // Second resolution
-  this->NS = fst.st_mtime * NsPerS;
+  this->Time = fst.st_mtime * UtPerS;
 #  endif
 #else
   // Windows version.  Get the modification time from extended file attributes.
@@ -41,10 +41,11 @@
   }
 
   // Copy the file time to the output location.
-  this->NS = (static_cast<NSC>(fdata.ftLastWriteTime.dwHighDateTime) << 32) |
-    static_cast<NSC>(fdata.ftLastWriteTime.dwLowDateTime);
-  // The file time resolution is 100 ns.
-  this->NS *= 100;
+  using uint64 = unsigned long long;
+
+  this->Time = static_cast<TimeType>(
+    (uint64(fdata.ftLastWriteTime.dwHighDateTime) << 32) +
+    fdata.ftLastWriteTime.dwLowDateTime);
 #endif
   return true;
 }
diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h
index f496cdc..4419880 100644
--- a/Source/cmFileTime.h
+++ b/Source/cmFileTime.h
@@ -13,9 +13,15 @@
 class cmFileTime
 {
 public:
-  using NSC = long long;
-  static constexpr NSC NsPerS = 1000000000;
-
+  using TimeType = long long;
+  // unit time per second
+#if !defined(_WIN32) || defined(__CYGWIN__)
+  // unit time is one nanosecond
+  static constexpr TimeType UtPerS = 1000000000;
+#else
+  // unit time is 100 nanosecond
+  static constexpr TimeType UtPerS = 10000000;
+#endif
   cmFileTime() = default;
   ~cmFileTime() = default;
 
@@ -28,22 +34,28 @@
   /**
    * @brief Return true if this is older than ftm
    */
-  bool Older(cmFileTime const& ftm) const { return (this->NS - ftm.NS) < 0; }
+  bool Older(cmFileTime const& ftm) const
+  {
+    return (this->Time - ftm.Time) < 0;
+  }
 
   /**
    * @brief Return true if this is newer than ftm
    */
-  bool Newer(cmFileTime const& ftm) const { return (ftm.NS - this->NS) < 0; }
+  bool Newer(cmFileTime const& ftm) const
+  {
+    return (ftm.Time - this->Time) < 0;
+  }
 
   /**
    * @brief Return true if this is the same as ftm
    */
-  bool Equal(cmFileTime const& ftm) const { return this->NS == ftm.NS; }
+  bool Equal(cmFileTime const& ftm) const { return this->Time == ftm.Time; }
 
   /**
    * @brief Return true if this is not the same as ftm
    */
-  bool Differ(cmFileTime const& ftm) const { return this->NS != ftm.NS; }
+  bool Differ(cmFileTime const& ftm) const { return this->Time != ftm.Time; }
 
   /**
    * @brief Compare file modification times.
@@ -51,7 +63,7 @@
    */
   int Compare(cmFileTime const& ftm) const
   {
-    NSC const diff = this->NS - ftm.NS;
+    TimeType const diff = this->Time - ftm.Time;
     if (diff == 0) {
       return 0;
     }
@@ -65,7 +77,7 @@
    */
   bool OlderS(cmFileTime const& ftm) const
   {
-    return (ftm.NS - this->NS) >= cmFileTime::NsPerS;
+    return (ftm.Time - this->Time) >= cmFileTime::UtPerS;
   }
 
   /**
@@ -73,7 +85,7 @@
    */
   bool NewerS(cmFileTime const& ftm) const
   {
-    return (this->NS - ftm.NS) >= cmFileTime::NsPerS;
+    return (this->Time - ftm.Time) >= cmFileTime::UtPerS;
   }
 
   /**
@@ -81,11 +93,11 @@
    */
   bool EqualS(cmFileTime const& ftm) const
   {
-    NSC diff = this->NS - ftm.NS;
+    TimeType diff = this->Time - ftm.Time;
     if (diff < 0) {
       diff = -diff;
     }
-    return (diff < cmFileTime::NsPerS);
+    return (diff < cmFileTime::UtPerS);
   }
 
   /**
@@ -93,11 +105,11 @@
    */
   bool DifferS(cmFileTime const& ftm) const
   {
-    NSC diff = this->NS - ftm.NS;
+    TimeType diff = this->Time - ftm.Time;
     if (diff < 0) {
       diff = -diff;
     }
-    return (diff >= cmFileTime::NsPerS);
+    return (diff >= cmFileTime::UtPerS);
   }
 
   /**
@@ -107,21 +119,21 @@
    */
   int CompareS(cmFileTime const& ftm) const
   {
-    NSC const diff = this->NS - ftm.NS;
-    if (diff <= -cmFileTime::NsPerS) {
+    TimeType const diff = this->Time - ftm.Time;
+    if (diff <= -cmFileTime::UtPerS) {
       return -1;
     }
-    if (diff >= cmFileTime::NsPerS) {
+    if (diff >= cmFileTime::UtPerS) {
       return 1;
     }
     return 0;
   }
 
   /**
-   * @brief The file modification time in nanoseconds
+   * @brief The file modification time in unit time per second
    */
-  NSC GetNS() const { return this->NS; }
+  TimeType GetTime() const { return this->Time; }
 
 private:
-  NSC NS = 0;
+  TimeType Time = 0;
 };
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index b40d8ea..7ee94b2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1965,6 +1965,15 @@
   return buildPhase;
 }
 
+namespace {
+void ReplaceScriptVars(std::string& cmd)
+{
+  cmSystemTools::ReplaceString(cmd, "$(CONFIGURATION)", "$CONFIGURATION");
+  cmSystemTools::ReplaceString(cmd, "$(EFFECTIVE_PLATFORM_NAME)",
+                               "$EFFECTIVE_PLATFORM_NAME");
+}
+}
+
 std::string cmGlobalXCodeGenerator::ConstructScript(
   cmCustomCommandGenerator const& ccg)
 {
@@ -1975,6 +1984,7 @@
     wd = lg->GetCurrentBinaryDirectory();
   }
   wd = lg->ConvertToOutputFormat(wd, cmOutputConverter::SHELL);
+  ReplaceScriptVars(wd);
   script = cmStrCat(script, "  cd ", wd, "\n");
   for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
     std::string cmd = ccg.GetCommand(c);
@@ -1984,9 +1994,7 @@
     cmSystemTools::ReplaceString(cmd, "/./", "/");
     cmd = lg->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
     ccg.AppendArguments(c, cmd);
-    cmSystemTools::ReplaceString(cmd, "$(CONFIGURATION)", "$CONFIGURATION");
-    cmSystemTools::ReplaceString(cmd, "$(EFFECTIVE_PLATFORM_NAME)",
-                                 "$EFFECTIVE_PLATFORM_NAME");
+    ReplaceScriptVars(cmd);
     script = cmStrCat(script, "  ", cmd, '\n');
   }
   return script;
diff --git a/Tests/RunCMake/add_custom_command/PrintDir.cmake b/Tests/RunCMake/add_custom_command/PrintDir.cmake
new file mode 100644
index 0000000..0a7b646
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/PrintDir.cmake
@@ -0,0 +1 @@
+message(STATUS "WorkingDir='${CMAKE_CURRENT_BINARY_DIR}'")
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index 96642fa..aac085d 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -27,3 +27,18 @@
 run_cmake_command(AssigningMultipleTargets-build ${CMAKE_COMMAND} --build .)
 unset(RunCMake_TEST_BINARY_DIR)
 unset(RunCMake_TEST_NO_CLEAN)
+
+if(NOT RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
+  run_cmake(WorkingDirectory)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/WorkingDirectory-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+    set(RunCMake-stdout-file WorkingDirectory-build-multi-config-stdout.txt)
+  else()
+    set(RunCMake-stdout-file WorkingDirectory-build-single-config-stdout.txt)
+  endif()
+  run_cmake_command(WorkingDirectory-build ${CMAKE_COMMAND} --build . --config Debug)
+  unset(RunCMake-stdout-file)
+  unset(RunCMake_TEST_BINARY_DIR)
+  unset(RunCMake_TEST_NO_CLEAN)
+endif()
diff --git a/Tests/RunCMake/add_custom_command/WorkingDirectory-build-multi-config-stdout.txt b/Tests/RunCMake/add_custom_command/WorkingDirectory-build-multi-config-stdout.txt
new file mode 100644
index 0000000..95ecf42
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/WorkingDirectory-build-multi-config-stdout.txt
@@ -0,0 +1 @@
+-- WorkingDir='[^']*/Tests/RunCMake/add_custom_command/WorkingDirectory-build/Debug'
diff --git a/Tests/RunCMake/add_custom_command/WorkingDirectory-build-single-config-stdout.txt b/Tests/RunCMake/add_custom_command/WorkingDirectory-build-single-config-stdout.txt
new file mode 100644
index 0000000..1db56ae
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/WorkingDirectory-build-single-config-stdout.txt
@@ -0,0 +1 @@
+-- WorkingDir='[^']*/Tests/RunCMake/add_custom_command/WorkingDirectory-build'
diff --git a/Tests/RunCMake/add_custom_command/WorkingDirectory.cmake b/Tests/RunCMake/add_custom_command/WorkingDirectory.cmake
new file mode 100644
index 0000000..65b7250
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/WorkingDirectory.cmake
@@ -0,0 +1,9 @@
+add_custom_target(mkdir COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
+add_custom_command(
+  OUTPUT out.txt
+  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/PrintDir.cmake
+  WORKING_DIRECTORY ${CMAKE_CFG_INTDIR}
+  )
+set_property(SOURCE out.txt PROPERTY SYMBOLIC 1)
+add_custom_target(drive ALL DEPENDS out.txt)
+add_dependencies(drive mkdir)