From 8ec7408d745a9e17a1e35a4e97e9ab33044832c9 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Wed, 6 Jan 2021 13:52:53 +0100 Subject: Makefile dependencies: ensure long paths are used on Windows --- Source/cmGccDepfileReader.cxx | 23 ++++++++--------------- Source/cmGccDepfileReader.h | 6 ++---- Source/cmSystemTools.cxx | 24 ++++++++++++++++++++++++ Source/cmSystemTools.h | 6 ++++++ Source/cmcmd.cxx | 9 ++++----- 5 files changed, 44 insertions(+), 24 deletions(-) diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx index 96a562e..8253375 100644 --- a/Source/cmGccDepfileReader.cxx +++ b/Source/cmGccDepfileReader.cxx @@ -12,40 +12,33 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -cm::optional cmReadGccDepfile(const char* filePath) -{ - cmGccDepfileLexerHelper helper; - if (helper.readFile(filePath)) { - return cm::make_optional(std::move(helper).extractContent()); - } - return cm::nullopt; -} - cm::optional 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); } } diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h index 66ff75d..c8a3748 100644 --- a/Source/cmGccDepfileReader.h +++ b/Source/cmGccDepfileReader.h @@ -8,10 +8,8 @@ #include "cmGccDepfileReaderTypes.h" -cm::optional cmReadGccDepfile(const char* filePath); - /* * Read dependencies file and append prefix to all relative paths */ -cm::optional cmReadGccDepfile(const char* filePath, - const std::string& prefix); +cm::optional cmReadGccDepfile( + const char* filePath, const std::string& prefix = {}); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 6a705f4..024356f 100644 --- a/Source/cmSystemTools.cxx +++ b/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 buffer(ret); + if (ret != 0) { + ret = GetLongPathNameW(wPath.c_str(), buffer.data(), + static_cast(buffer.size())); + } + + if (ret != 0) { + path = cmsys::Encoding::ToNarrow(buffer.data()); + } +#else + static_cast(path); +#endif +} + std::string cmSystemTools::ConvertToRunCommandPath(const std::string& path) { #if defined(_WIN32) && !defined(__CYGWIN__) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 1100f05..5bbbb0c 100644 --- a/Source/cmSystemTools.h +++ b/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 diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 4c0fbeb..851205e 100644 --- a/Source/cmcmd.cxx +++ b/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; } -- cgit v0.12 From bb64ea5741f599567bf282b32431e852b28e31bc Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 28 Dec 2020 12:00:05 +0100 Subject: Makefiles: ensure transparent switch between dependencies strategies --- Source/cmMakefileTargetGenerator.cxx | 63 ++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index c33fabd..adf40b0 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -345,27 +345,51 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->LocalGenerator->GetBinaryDirectory(), compilerDependFile)) << "\n\n"; - if (!cmSystemTools::FileExists(compilerDependFile)) { - // Write an empty dependency file. - cmGeneratedFileStream depFileStream( - compilerDependFile, false, - this->GlobalGenerator->GetMakefileEncoding()); - depFileStream << "# Empty compiler generated dependencies file for " - << this->GeneratorTarget->GetName() << ".\n" - << "# This may be replaced when dependencies are built.\n"; - } + // Write an empty dependency file. + cmGeneratedFileStream depFileStream( + compilerDependFile, false, this->GlobalGenerator->GetMakefileEncoding()); + depFileStream << "# Empty compiler generated dependencies file for " + << this->GeneratorTarget->GetName() << ".\n" + << "# This may be replaced when dependencies are built.\n"; + // remove internal dependency file + cmSystemTools::RemoveFile( + cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.internal")); std::string compilerDependTimestamp = cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"); if (!cmSystemTools::FileExists(compilerDependTimestamp)) { // Write a dependency timestamp file. - cmGeneratedFileStream depFileStream( + cmGeneratedFileStream timestampFileStream( compilerDependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding()); - depFileStream << "# CMAKE generated file: DO NOT EDIT!\n" - << "# Timestamp file for compiler generated dependencies " - "management for " - << this->GeneratorTarget->GetName() << ".\n"; + timestampFileStream + << "# CMAKE generated file: DO NOT EDIT!\n" + << "# Timestamp file for compiler generated dependencies " + "management for " + << this->GeneratorTarget->GetName() << ".\n"; + } + + // deactivate no longer needed legacy dependency files + // Write an empty dependency file. + cmGeneratedFileStream legacyDepFileStream( + dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); + legacyDepFileStream + << "# Empty dependencies file for " << this->GeneratorTarget->GetName() + << ".\n" + << "# This may be replaced when dependencies are built.\n"; + // remove internal dependency file + cmSystemTools::RemoveFile( + cmStrCat(this->TargetBuildDirectoryFull, "/depend.internal")); + } else { + // make sure the depend file exists + if (!cmSystemTools::FileExists(dependFileNameFull)) { + // Write an empty dependency file. + cmGeneratedFileStream depFileStream( + dependFileNameFull, false, + this->GlobalGenerator->GetMakefileEncoding()); + depFileStream << "# Empty dependencies file for " + << this->GeneratorTarget->GetName() << ".\n" + << "# This may be replaced when dependencies are built.\n"; } } @@ -381,16 +405,6 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << "\n\n"; } - // make sure the depend file exists - if (!cmSystemTools::FileExists(dependFileNameFull)) { - // Write an empty dependency file. - cmGeneratedFileStream depFileStream( - dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); - depFileStream << "# Empty dependencies file for " - << this->GeneratorTarget->GetName() << ".\n" - << "# This may be replaced when dependencies are built.\n"; - } - // Open the flags file. This should be copy-if-different because the // rules may depend on this file itself. this->FlagFileNameFull = @@ -855,6 +869,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( shellDependencyFile = this->LocalGenerator->ConvertToOutputFormat( depFile, cmOutputConverter::SHELL); vars.DependencyFile = shellDependencyFile.c_str(); + this->CleanFiles.insert(depFile); dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetBinaryDirectory(), -- cgit v0.12