|
21 | 21 | //===----------------------------------------------------------------------===//
|
22 | 22 |
|
23 | 23 | #include "swift/FrontendTool/FrontendTool.h"
|
24 |
| -#include "ImportedModules.h" |
| 24 | +#include "Dependencies.h" |
25 | 25 | #include "ScanDependencies.h"
|
26 | 26 | #include "TBD.h"
|
27 | 27 |
|
@@ -107,132 +107,12 @@ static std::string displayName(StringRef MainExecutablePath) {
|
107 | 107 | return Name;
|
108 | 108 | }
|
109 | 109 |
|
110 |
| -StringRef |
111 |
| -swift::frontend::utils::escapeForMake(StringRef raw, |
112 |
| - llvm::SmallVectorImpl<char> &buffer) { |
113 |
| - buffer.clear(); |
114 |
| - |
115 |
| - // The escaping rules for GNU make are complicated due to the various |
116 |
| - // subsitutions and use of the tab in the leading position for recipes. |
117 |
| - // Various symbols have significance in different contexts. It is not |
118 |
| - // possible to correctly quote all characters in Make (as of 3.7). Match |
119 |
| - // gcc and clang's behaviour for the escaping which covers only a subset of |
120 |
| - // characters. |
121 |
| - for (unsigned I = 0, E = raw.size(); I != E; ++I) { |
122 |
| - switch (raw[I]) { |
123 |
| - case '#': // Handle '#' the broken GCC way |
124 |
| - buffer.push_back('\\'); |
125 |
| - break; |
126 |
| - |
127 |
| - case ' ': |
128 |
| - for (unsigned J = I; J && raw[J - 1] == '\\'; --J) |
129 |
| - buffer.push_back('\\'); |
130 |
| - buffer.push_back('\\'); |
131 |
| - break; |
132 |
| - |
133 |
| - case '$': // $ is escaped by $ |
134 |
| - buffer.push_back('$'); |
135 |
| - break; |
136 |
| - } |
137 |
| - buffer.push_back(raw[I]); |
138 |
| - } |
139 |
| - buffer.push_back('\0'); |
140 |
| - |
141 |
| - return buffer.data(); |
142 |
| -} |
143 |
| - |
144 |
| -/// This sorting function is used to stabilize the order in which dependencies |
145 |
| -/// are emitted into \c .d files that are consumed by external build systems. |
146 |
| -/// This serves to eliminate order as a source of non-determinism in these |
147 |
| -/// outputs. |
148 |
| -/// |
149 |
| -/// The exact sorting predicate is not important. Currently, it is a |
150 |
| -/// lexicographic comparison that reverses the provided strings before applying |
151 |
| -/// the sorting predicate. This has the benefit of being somewhat |
152 |
| -/// invariant with respect to the installation location of various system |
153 |
| -/// components. e.g. on two systems, the same file identified by two different |
154 |
| -/// paths differing only in their relative install location such as |
155 |
| -/// |
156 |
| -/// /Applications/MyXcode.app/Path/To/A/Framework/In/The/SDK/Header.h |
157 |
| -/// /Applications/Xcodes/AnotherXcode.app/Path/To/A/Framework/In/The/SDK/Header.h |
158 |
| -/// |
159 |
| -/// should appear in roughly the same order relative to other paths. Ultimately, |
160 |
| -/// this makes it easier to test the contents of the emitted files with tools |
161 |
| -/// like FileCheck. |
162 |
| -static std::vector<std::string> |
163 |
| -reversePathSortedFilenames(const ArrayRef<std::string> elts) { |
164 |
| - std::vector<std::string> tmp(elts.begin(), elts.end()); |
165 |
| - std::sort(tmp.begin(), tmp.end(), [](const std::string &a, |
166 |
| - const std::string &b) -> bool { |
167 |
| - return std::lexicographical_compare(a.rbegin(), a.rend(), |
168 |
| - b.rbegin(), b.rend()); |
169 |
| - }); |
170 |
| - return tmp; |
171 |
| -} |
172 |
| - |
173 |
| -/// Emits a Make-style dependencies file. |
174 |
| -static bool emitMakeDependenciesIfNeeded(DiagnosticEngine &diags, |
175 |
| - DependencyTracker *depTracker, |
176 |
| - const FrontendOptions &opts, |
177 |
| - const InputFile &input) { |
178 |
| - const std::string &dependenciesFilePath = input.dependenciesFilePath(); |
179 |
| - if (dependenciesFilePath.empty()) |
180 |
| - return false; |
181 |
| - |
182 |
| - std::error_code EC; |
183 |
| - llvm::raw_fd_ostream out(dependenciesFilePath, EC, llvm::sys::fs::F_None); |
184 |
| - |
185 |
| - if (out.has_error() || EC) { |
186 |
| - diags.diagnose(SourceLoc(), diag::error_opening_output, |
187 |
| - dependenciesFilePath, EC.message()); |
188 |
| - out.clear_error(); |
189 |
| - return true; |
190 |
| - } |
191 |
| - |
192 |
| - llvm::SmallString<256> buffer; |
193 |
| - |
194 |
| - // collect everything in memory to avoid redundant work |
195 |
| - // when there are multiple targets |
196 |
| - std::string dependencyString; |
197 |
| - |
198 |
| - // First include all other files in the module. Make-style dependencies |
199 |
| - // need to be conservative! |
200 |
| - auto inputPaths = |
201 |
| - reversePathSortedFilenames(opts.InputsAndOutputs.getInputFilenames()); |
202 |
| - for (auto const &path : inputPaths) { |
203 |
| - dependencyString.push_back(' '); |
204 |
| - dependencyString.append(frontend::utils::escapeForMake(path, buffer).str()); |
205 |
| - } |
206 |
| - // Then print dependencies we've picked up during compilation. |
207 |
| - auto dependencyPaths = |
208 |
| - reversePathSortedFilenames(depTracker->getDependencies()); |
209 |
| - for (auto const &path : dependencyPaths) { |
210 |
| - dependencyString.push_back(' '); |
211 |
| - dependencyString.append(frontend::utils::escapeForMake(path, buffer).str()); |
212 |
| - } |
213 |
| - auto incrementalDependencyPaths = |
214 |
| - reversePathSortedFilenames(depTracker->getIncrementalDependencies()); |
215 |
| - for (auto const &path : incrementalDependencyPaths) { |
216 |
| - dependencyString.push_back(' '); |
217 |
| - dependencyString.append(frontend::utils::escapeForMake(path, buffer).str()); |
218 |
| - } |
219 |
| - |
220 |
| - // FIXME: Xcode can't currently handle multiple targets in a single |
221 |
| - // dependency line. |
222 |
| - opts.forAllOutputPaths(input, [&](const StringRef targetName) { |
223 |
| - auto targetNameEscaped = frontend::utils::escapeForMake(targetName, buffer); |
224 |
| - out << targetNameEscaped << " :" << dependencyString << '\n'; |
225 |
| - }); |
226 |
| - |
227 |
| - return false; |
228 |
| -} |
229 |
| - |
230 | 110 | static void emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
|
231 | 111 | DependencyTracker *depTracker,
|
232 | 112 | const FrontendOptions &opts) {
|
233 | 113 | opts.InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
234 | 114 | [&](const InputFile &f) -> bool {
|
235 |
| - return emitMakeDependenciesIfNeeded(diags, depTracker, opts, f); |
| 115 | + return swift::emitMakeDependenciesIfNeeded(diags, depTracker, opts, f); |
236 | 116 | });
|
237 | 117 | }
|
238 | 118 |
|
|
0 commit comments