Makefiles: Factor out makefile target path escaping and quoting

Code paths that write makefile target paths use a combination of
`cmSystemTools::ConvertToOutputPath` and `cmMakeSafe`.  Some were
missing the latter.  Wrap these two steps up into a dedicated
`ConvertToMakefilePath` method provided on both the local and global
generators.
This commit is contained in:
Brad King 2020-04-10 12:08:20 -04:00
parent ca343dad07
commit 031bfaa865
5 changed files with 49 additions and 41 deletions

View File

@ -212,12 +212,12 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// written by the original local generator for this directory
// convert the dependencies to paths relative to the home output
// directory. We must do the same here.
std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
std::string obj_m = this->LocalGenerator->ConvertToMakefilePath(obj_i);
internalDepends << obj_i << '\n';
for (std::string const& dep : dependencies) {
makeDepends << obj_m << ": "
<< cmSystemTools::ConvertToOutputPath(
<< this->LocalGenerator->ConvertToMakefilePath(
this->LocalGenerator->MaybeConvertToRelativePath(binDir,
dep))
<< '\n';

View File

@ -486,6 +486,25 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
}
}
std::string cmGlobalUnixMakefileGenerator3::ConvertToMakefilePath(
std::string const& path) const
{
std::string const& out = cmSystemTools::ConvertToOutputPath(path);
std::string result;
result.reserve(out.size());
for (char c : out) {
switch (c) {
case '=':
result.append("$(EQUALS)");
break;
default:
result.push_back(c);
break;
}
}
return result;
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
const std::string& makeProgram, const std::string& /*projectName*/,

View File

@ -136,6 +136,12 @@ public:
or dependencies. */
std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
/**
* Convert a file path to a Makefile target or dependency with
* escaping and quoting suitable for the generator's make tool.
*/
std::string ConvertToMakefilePath(std::string const& path) const;
// change the build command for speed
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,

View File

@ -48,37 +48,6 @@
# include "cmDependsJava.h"
#endif
// Escape special characters in Makefile dependency lines
class cmMakeSafe
{
public:
cmMakeSafe(const char* s)
: Data(s)
{
}
cmMakeSafe(std::string const& s)
: Data(s.c_str())
{
}
private:
const char* Data;
friend std::ostream& operator<<(std::ostream& os, cmMakeSafe const& self)
{
for (const char* c = self.Data; *c; ++c) {
switch (*c) {
case '=':
os << "$(EQUALS)";
break;
default:
os << *c;
break;
}
}
return os;
}
};
// Helper function used below.
static std::string cmSplitExtension(std::string const& in, std::string& base)
{
@ -498,6 +467,14 @@ const std::string& cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
return this->HomeRelativeOutputPath;
}
std::string cmLocalUnixMakefileGenerator3::ConvertToMakefilePath(
std::string const& path) const
{
cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
return gg->ConvertToMakefilePath(path);
}
void cmLocalUnixMakefileGenerator3::WriteMakeRule(
std::ostream& os, const char* comment, const std::string& target,
const std::vector<std::string>& depends,
@ -528,7 +505,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
}
// Construct the left hand side of the rule.
std::string tgt = cmSystemTools::ConvertToOutputPath(
std::string tgt = this->ConvertToMakefilePath(
this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target));
const char* space = "";
@ -542,30 +519,30 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
if (symbolic) {
if (const char* sym =
this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE")) {
os << cmMakeSafe(tgt) << space << ": " << sym << "\n";
os << tgt << space << ": " << sym << "\n";
}
}
// Write the rule.
if (depends.empty()) {
// No dependencies. The commands will always run.
os << cmMakeSafe(tgt) << space << ":\n";
os << tgt << space << ":\n";
} else {
// Split dependencies into multiple rule lines. This allows for
// very long dependency lists even on older make implementations.
std::string binDir = this->GetBinaryDirectory();
for (std::string const& depend : depends) {
replace = depend;
replace = cmSystemTools::ConvertToOutputPath(
this->MaybeConvertToRelativePath(binDir, replace));
os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n";
os << tgt << space << ": "
<< this->ConvertToMakefilePath(
this->MaybeConvertToRelativePath(binDir, depend))
<< '\n';
}
}
// Write the list of commands.
os << cmWrap("\t", commands, "", "\n") << "\n";
if (symbolic && !this->IsWatcomWMake()) {
os << ".PHONY : " << cmMakeSafe(tgt) << "\n";
os << ".PHONY : " << tgt << "\n";
}
os << "\n";
// Add the output to the local help if requested.

View File

@ -46,6 +46,12 @@ public:
// local generators StartOutputDirectory
const std::string& GetHomeRelativeOutputPath();
/**
* Convert a file path to a Makefile target or dependency with
* escaping and quoting suitable for the generator's make tool.
*/
std::string ConvertToMakefilePath(std::string const& path) const;
// Write out a make rule
void WriteMakeRule(std::ostream& os, const char* comment,
const std::string& target,