Makefile dependencies: ensure long paths are used on Windows

This commit is contained in:
Marc Chevrier
2021-01-06 13:52:53 +01:00
parent ce874fbcd6
commit 8ec7408d74
5 changed files with 44 additions and 24 deletions

View File

@@ -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);
}
}

View File

@@ -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 = {});

View File

@@ -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__)

View File

@@ -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

View File

@@ -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;
}