瀏覽代碼

Makefile dependencies: ensure long paths are used on Windows

Marc Chevrier 4 年之前
父節點
當前提交
8ec7408d74
共有 5 個文件被更改,包括 44 次插入24 次删除
  1. 8 15
      Source/cmGccDepfileReader.cxx
  2. 2 4
      Source/cmGccDepfileReader.h
  3. 24 0
      Source/cmSystemTools.cxx
  4. 6 0
      Source/cmSystemTools.h
  5. 4 5
      Source/cmcmd.cxx

+ 8 - 15
Source/cmGccDepfileReader.cxx

@@ -12,40 +12,33 @@
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
-cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath)
-{
-  cmGccDepfileLexerHelper helper;
-  if (helper.readFile(filePath)) {
-    return cm::make_optional(std::move(helper).extractContent());
-  }
-  return cm::nullopt;
-}
-
 cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
                                                    const std::string& prefix)
 {
-  auto deps = cmReadGccDepfile(filePath);
-
-  if (prefix.empty() || !deps) {
-    return deps;
+  cmGccDepfileLexerHelper helper;
+  if (!helper.readFile(filePath)) {
+    return cm::nullopt;
   }
+  auto deps = cm::make_optional(std::move(helper).extractContent());
 
   for (auto& dep : *deps) {
     for (auto& rule : dep.rules) {
-      if (!cmSystemTools::FileIsFullPath(rule)) {
+      if (!prefix.empty() && !cmSystemTools::FileIsFullPath(rule)) {
         rule = cmStrCat(prefix, rule);
       }
       if (cmSystemTools::FileIsFullPath(rule)) {
         rule = cmSystemTools::CollapseFullPath(rule);
       }
+      cmSystemTools::ConvertToLongPath(rule);
     }
     for (auto& path : dep.paths) {
-      if (!cmSystemTools::FileIsFullPath(path)) {
+      if (!prefix.empty() && !cmSystemTools::FileIsFullPath(path)) {
         path = cmStrCat(prefix, path);
       }
       if (cmSystemTools::FileIsFullPath(path)) {
         path = cmSystemTools::CollapseFullPath(path);
       }
+      cmSystemTools::ConvertToLongPath(path);
     }
   }
 

+ 2 - 4
Source/cmGccDepfileReader.h

@@ -8,10 +8,8 @@
 
 #include "cmGccDepfileReaderTypes.h"
 
-cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath);
-
 /*
  * Read dependencies file and append prefix to all relative paths
  */
-cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
-                                                   const std::string& prefix);
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(
+  const char* filePath, const std::string& prefix = {});

+ 24 - 0
Source/cmSystemTools.cxx

@@ -1255,6 +1255,30 @@ void cmSystemTools::ConvertToOutputSlashes(std::string& path)
 #endif
 }
 
+void cmSystemTools::ConvertToLongPath(std::string& path)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Try to convert path to a long path only if the path contains character '~'
+  if (path.find('~') == std::string::npos) {
+    return;
+  }
+
+  std::wstring wPath = cmsys::Encoding::ToWide(path);
+  DWORD ret = GetLongPathNameW(wPath.c_str(), nullptr, 0);
+  std::vector<wchar_t> buffer(ret);
+  if (ret != 0) {
+    ret = GetLongPathNameW(wPath.c_str(), buffer.data(),
+                           static_cast<DWORD>(buffer.size()));
+  }
+
+  if (ret != 0) {
+    path = cmsys::Encoding::ToNarrow(buffer.data());
+  }
+#else
+  static_cast<void>(path);
+#endif
+}
+
 std::string cmSystemTools::ConvertToRunCommandPath(const std::string& path)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)

+ 6 - 0
Source/cmSystemTools.h

@@ -287,6 +287,12 @@ public:
   // running cmake needs paths to be in its format
   static std::string ConvertToRunCommandPath(const std::string& path);
 
+  /**
+   * For windows computes the long path for the given path,
+   * For Unix, it is a noop
+   */
+  static void ConvertToLongPath(std::string& path);
+
   /** compute the relative path from local to remote.  local must
       be a directory.  remote can be a file or a directory.
       Both remote and local must be full paths.  Basically, if

+ 4 - 5
Source/cmcmd.cxx

@@ -231,11 +231,10 @@ private:
   bool ProcessLine() override
   {
     if (cmHasPrefix(this->Line, this->IncludePrefix)) {
-      this->DepFile << cmCMakePath(
-                         cmTrimWhitespace(this->Line.c_str() +
-                                          this->IncludePrefix.size()))
-                         .GenericString()
-                    << std::endl;
+      auto path =
+        cmTrimWhitespace(this->Line.c_str() + this->IncludePrefix.size());
+      cmSystemTools::ConvertToLongPath(path);
+      this->DepFile << cmCMakePath(path).GenericString() << std::endl;
     } else {
       this->Output << this->Line << std::endl << std::flush;
     }