From c5b56b35c264664e897a2895e2561a5fb8287703 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Fri, 22 Apr 2022 18:13:55 -0400
Subject: cmInstallExportGenerator: expose the temporary directory

This needs to be known so that C++ module properties for the install can
be staged beside the other files.

Always perform the MD5 transformation (in non-bootstrap builds) so that
the path can be computed prior to generation (where it used the longest
configuration name to detect too-long paths). Update tests to expect the
always-present MD5 value. Note that this improves robustness of the test
suite as testing in a too-long path may have triggered the MD5
conversion anyways.
---
 Source/cmInstallExportGenerator.cxx                | 76 ++++++----------------
 Source/cmInstallExportGenerator.h                  |  4 +-
 Tests/RunCMake/AndroidMK/AndroidMK-check.cmake     |  2 +-
 .../FileAPI/codemodel-v2-data/directories/top.json |  2 +-
 .../install/EXPORT-TargetTwice-check.cmake         |  4 +-
 5 files changed, 25 insertions(+), 63 deletions(-)

diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index eb7537d..f1ac656 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallExportGenerator.h"
 
-#include <algorithm>
 #include <map>
 #include <sstream>
 #include <utility>
@@ -54,73 +53,36 @@ bool cmInstallExportGenerator::Compute(cmLocalGenerator* lg)
   return true;
 }
 
-void cmInstallExportGenerator::ComputeTempDir()
+std::string cmInstallExportGenerator::TempDirCalculate() const
 {
   // Choose a temporary directory in which to generate the import
   // files to be installed.
-  this->TempDir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
-                           "/CMakeFiles/Export");
+  std::string path = cmStrCat(
+    this->LocalGenerator->GetCurrentBinaryDirectory(), "/CMakeFiles/Export");
   if (this->Destination.empty()) {
-    return;
-  }
-  this->TempDir += "/";
-
-  // Enforce a maximum length.
-  bool useMD5 = false;
-#if defined(_WIN32) || defined(__CYGWIN__)
-  std::string::size_type const max_total_len = 250;
-#else
-  std::string::size_type const max_total_len = 1000;
-#endif
-  // Will generate files of the form "<temp-dir>/<base>-<config>.<ext>".
-  std::string::size_type const len = this->TempDir.size() + 1 +
-    this->FileName.size() + 1 + this->GetMaxConfigLength();
-  if (len < max_total_len) {
-    // Keep the total path length below the limit.
-    std::string::size_type const max_len = max_total_len - len;
-    if (this->Destination.size() > max_len) {
-      useMD5 = true;
-    }
-  } else {
-    useMD5 = true;
+    return path;
   }
-  if (useMD5) {
-    // Replace the destination path with a hash to keep it short.
+
 #ifndef CMAKE_BOOTSTRAP
-    this->TempDir += cmSystemTools::ComputeStringMD5(this->Destination);
+  path += '/';
+  // Replace the destination path with a hash to keep it short.
+  path += cmSystemTools::ComputeStringMD5(this->Destination);
 #endif
-  } else {
-    std::string dest = this->Destination;
-    // Avoid unix full paths.
-    if (dest[0] == '/') {
-      dest[0] = '_';
-    }
-    // Avoid windows full paths by removing colons.
-    std::replace(dest.begin(), dest.end(), ':', '_');
-    // Avoid relative paths that go up the tree.
-    cmSystemTools::ReplaceString(dest, "../", "__/");
-    // Avoid spaces.
-    std::replace(dest.begin(), dest.end(), ' ', '_');
-    this->TempDir += dest;
-  }
+
+  return path;
 }
 
-size_t cmInstallExportGenerator::GetMaxConfigLength() const
+void cmInstallExportGenerator::ComputeTempDir()
 {
-  // Always use at least 8 for "noconfig".
-  size_t len = 8;
-  if (this->ConfigurationTypes->empty()) {
-    if (this->ConfigurationName.size() > 8) {
-      len = this->ConfigurationName.size();
-    }
-  } else {
-    for (std::string const& c : *this->ConfigurationTypes) {
-      if (c.size() > len) {
-        len = c.size();
-      }
-    }
+  this->TempDir = this->TempDirCalculate();
+}
+
+std::string cmInstallExportGenerator::GetTempDir() const
+{
+  if (this->TempDir.empty()) {
+    return this->TempDirCalculate();
   }
-  return len;
+  return this->TempDir;
 }
 
 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 54c59f1..dc07d36 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -4,7 +4,6 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cstddef>
 #include <iosfwd>
 #include <memory>
 #include <string>
@@ -50,6 +49,7 @@ public:
   std::string const& GetDestination() const { return this->Destination; }
   std::string GetDestinationFile() const;
   std::string GetFileName() const { return this->FileName; }
+  std::string GetTempDir() const;
 
 protected:
   void GenerateScript(std::ostream& os) override;
@@ -57,8 +57,8 @@ protected:
   void GenerateScriptActions(std::ostream& os, Indent indent) override;
   void GenerateImportFile(cmExportSet const* exportSet);
   void GenerateImportFile(const char* config, cmExportSet const* exportSet);
+  std::string TempDirCalculate() const;
   void ComputeTempDir();
-  size_t GetMaxConfigLength() const;
 
   cmExportSet* const ExportSet;
   std::string const FilePermissions;
diff --git a/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake b/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake
index 691e326..03221c5 100644
--- a/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake
+++ b/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake
@@ -26,5 +26,5 @@ compare_file_to_expected(
 "${RunCMake_BINARY_DIR}/AndroidMK-build/Android.mk"
 "${RunCMake_TEST_SOURCE_DIR}/expectedBuildAndroidMK.txt")
 compare_file_to_expected(
-"${RunCMake_BINARY_DIR}/AndroidMK-build/CMakeFiles/Export/share/ndk-modules/Android.mk"
+"${RunCMake_BINARY_DIR}/AndroidMK-build/CMakeFiles/Export/c8a72b7cccded047a31c221a6b84dd48/Android.mk"
 "${RunCMake_TEST_SOURCE_DIR}/expectedInstallAndroidMK.txt")
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
index 22b4536..e7b146f 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
@@ -496,7 +496,7 @@
             "type": "export",
             "destination": "lib/cmake/foo",
             "paths": [
-                "^CMakeFiles/Export/lib/cmake/foo/FooTargets\\.cmake$"
+                "^CMakeFiles/Export/22ecfa717ccadd33cf3e4bcbabcbde6b/FooTargets\\.cmake$"
             ],
             "isExcludeFromAll": null,
             "isForAllComponents": null,
diff --git a/Tests/RunCMake/install/EXPORT-TargetTwice-check.cmake b/Tests/RunCMake/install/EXPORT-TargetTwice-check.cmake
index 97677ca..f1438dd 100644
--- a/Tests/RunCMake/install/EXPORT-TargetTwice-check.cmake
+++ b/Tests/RunCMake/install/EXPORT-TargetTwice-check.cmake
@@ -1,4 +1,4 @@
-set(pkg1_cmake "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/pkg1/pkg1.cmake")
+set(pkg1_cmake "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/59965f5e1aafdb63698f8ae505daf864/pkg1.cmake")
 file(STRINGS "${pkg1_cmake}" pkg1_includes REGEX INTERFACE_INCLUDE_DIRECTORIES)
 set(pkg1_expect [[INTERFACE_INCLUDE_DIRECTORIES "\${_IMPORT_PREFIX}/pkg1/inc"]])
 if(NOT pkg1_includes MATCHES "${pkg1_expect}")
@@ -8,7 +8,7 @@ It does not match:
   ${pkg1_expect}")
 endif()
 
-set(pkg2_cmake "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/pkg2/pkg2.cmake")
+set(pkg2_cmake "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/72c00a5f9d34b6649110956cfc9f27e6/pkg2.cmake")
 file(STRINGS "${pkg2_cmake}" pkg2_includes REGEX INTERFACE_INCLUDE_DIRECTORIES)
 set(pkg2_expect [[INTERFACE_INCLUDE_DIRECTORIES "\${_IMPORT_PREFIX}/pkg2/inc"]])
 if(NOT pkg2_includes MATCHES "${pkg2_expect}")
-- 
cgit v0.12