@@ -99,6 +99,40 @@ static std::string displayName(StringRef MainExecutablePath) {
99
99
return Name;
100
100
}
101
101
102
+ StringRef
103
+ swift::frontend::utils::escapeForMake (StringRef raw,
104
+ llvm::SmallVectorImpl<char > &buffer) {
105
+ buffer.clear ();
106
+
107
+ // The escaping rules for GNU make are complicated due to the various
108
+ // subsitutions and use of the tab in the leading position for recipes.
109
+ // Various symbols have significance in different contexts. It is not
110
+ // possible to correctly quote all characters in Make (as of 3.7). Match
111
+ // gcc and clang's behaviour for the escaping which covers only a subset of
112
+ // characters.
113
+ for (unsigned I = 0 , E = raw.size (); I != E; ++I) {
114
+ switch (raw[I]) {
115
+ case ' #' : // Handle '#' the broken GCC way
116
+ buffer.push_back (' \\ ' );
117
+ break ;
118
+
119
+ case ' ' :
120
+ for (unsigned J = I; J && raw[J - 1 ] == ' \\ ' ; --J)
121
+ buffer.push_back (' \\ ' );
122
+ buffer.push_back (' \\ ' );
123
+ break ;
124
+
125
+ case ' $' : // $ is escaped by $
126
+ buffer.push_back (' $' );
127
+ break ;
128
+ }
129
+ buffer.push_back (raw[I]);
130
+ }
131
+ buffer.push_back (' \0 ' );
132
+
133
+ return buffer.data ();
134
+ }
135
+
102
136
// / Emits a Make-style dependencies file.
103
137
static bool emitMakeDependenciesIfNeeded (DiagnosticEngine &diags,
104
138
DependencyTracker *depTracker,
@@ -118,39 +152,21 @@ static bool emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
118
152
return true ;
119
153
}
120
154
121
- // Declare a helper for escaping file names for use in Makefiles.
122
- llvm::SmallString<256 > pathBuf;
123
- auto escape = [&](StringRef raw) -> StringRef {
124
- pathBuf.clear ();
125
-
126
- static const char badChars[] = " $#:\n " ;
127
- size_t prev = 0 ;
128
- for (auto index = raw.find_first_of (badChars); index != StringRef::npos;
129
- index = raw.find_first_of (badChars, index+1 )) {
130
- pathBuf.append (raw.slice (prev, index));
131
- if (raw[index] == ' $' )
132
- pathBuf.push_back (' $' );
133
- else
134
- pathBuf.push_back (' \\ ' );
135
- prev = index;
136
- }
137
- pathBuf.append (raw.substr (prev));
138
- return pathBuf;
139
- };
155
+ llvm::SmallString<256 > buffer;
140
156
141
157
// FIXME: Xcode can't currently handle multiple targets in a single
142
158
// dependency line.
143
159
opts.forAllOutputPaths (input, [&](const StringRef targetName) {
144
- out << escape (targetName) << " :" ;
160
+ out << swift::frontend::utils::escapeForMake (targetName, buffer ) << " :" ;
145
161
// First include all other files in the module. Make-style dependencies
146
162
// need to be conservative!
147
163
for (auto const &path :
148
164
reversePathSortedFilenames (opts.InputsAndOutputs .getInputFilenames ()))
149
- out << ' ' << escape (path);
165
+ out << ' ' << swift::frontend::utils::escapeForMake (path, buffer );
150
166
// Then print dependencies we've picked up during compilation.
151
167
for (auto const &path :
152
168
reversePathSortedFilenames (depTracker->getDependencies ()))
153
- out << ' ' << escape (path);
169
+ out << ' ' << swift::frontend::utils::escapeForMake (path, buffer );
154
170
out << ' \n ' ;
155
171
});
156
172
0 commit comments