1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-19 11:18:40 +08:00

Makefiles: Re-implement makefile target path escaping and quoting

Previously we used `cmSystemTools::ConvertToOutputPath` which internally
used KWSys methods

* SystemTools::ConvertToUnixOutputPath
* SystemTools::ConvertToWindowsOutputPath

These were written in very early days of CMake and have some
limitations:

* They do not encode all characters.  E.g. '#' is left out.
* They attempt to do some path cleanup and handle existing quotes.
  These days CMake has clean unquoted paths already.
* They attempted to encode paths both for makefile targets and
  for shell command lines.  The latter use has mostly been replaced.
* Choosing between the two methods depends on a global variable!
  Several code paths in CMake have to copy the global generator's
  member ForceUnixPaths variable over to the cmSystemTools global.

Re-implement the `ConvertToMakefilePath` method to drop use of those
methods.  Compute suitable makefile target path escaping and quoting
via local logic.  Add support for more characters like '#'.

Fixes: #20555
This commit is contained in:
Brad King
2020-04-10 15:15:21 -04:00
parent 031bfaa865
commit d74e651b78

View File

@@ -486,17 +486,25 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
}
}
std::string cmGlobalUnixMakefileGenerator3::ConvertToMakefilePath(
std::string const& path) const
namespace {
std::string ConvertToMakefilePathForUnix(std::string const& path)
{
std::string const& out = cmSystemTools::ConvertToOutputPath(path);
std::string result;
result.reserve(out.size());
for (char c : out) {
result.reserve(path.size());
for (char c : path) {
switch (c) {
case '=':
// We provide 'EQUALS = =' to encode '=' in a non-assignment case.
result.append("$(EQUALS)");
break;
case '$':
result.append("$$");
break;
case '\\':
case ' ':
case '#':
result.push_back('\\');
CM_FALLTHROUGH;
default:
result.push_back(c);
break;
@@ -505,6 +513,51 @@ std::string cmGlobalUnixMakefileGenerator3::ConvertToMakefilePath(
return result;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
std::string ConvertToMakefilePathForWindows(std::string const& path)
{
bool const quote = path.find_first_of(" #") != std::string::npos;
std::string result;
result.reserve(path.size() + (quote ? 2 : 0));
if (quote) {
result.push_back('"');
}
for (char c : path) {
switch (c) {
case '=':
// We provide 'EQUALS = =' to encode '=' in a non-assignment case.
result.append("$(EQUALS)");
break;
case '$':
result.append("$$");
break;
case '/':
result.push_back('\\');
break;
default:
result.push_back(c);
break;
}
}
if (quote) {
result.push_back('"');
}
return result;
}
#endif
}
std::string cmGlobalUnixMakefileGenerator3::ConvertToMakefilePath(
std::string const& path) const
{
#if defined(_WIN32) && !defined(__CYGWIN__)
if (!this->ForceUnixPaths) {
return ConvertToMakefilePathForWindows(path);
}
#endif
return ConvertToMakefilePathForUnix(path);
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
const std::string& makeProgram, const std::string& /*projectName*/,