20
20
#include " tools/common/file_system.h"
21
21
#include " tools/common/process.h"
22
22
#include " tools/common/temp_file.h"
23
+ #include " tools/worker/output_file_map.h"
23
24
24
25
namespace {
25
26
@@ -129,29 +130,105 @@ int SwiftRunner::Run(std::ostream *stderr_stream, bool stdout_to_stderr) {
129
130
exit_code = RunSubProcess (rewriter_args, stderr_stream, stdout_to_stderr);
130
131
}
131
132
133
+ auto enable_global_index_store = global_index_store_import_path_ != " " ;
134
+ if (enable_global_index_store) {
135
+ OutputFileMap output_file_map;
136
+ output_file_map.ReadFromPath (output_file_map_path_);
137
+
138
+ auto outputs = output_file_map.incremental_outputs ();
139
+ std::map<std::string, std::string>::iterator it;
140
+
141
+ std::vector<std::string> ii_args;
142
+ // The index-import runfile path is passed as a define
143
+ #if defined(INDEX_IMPORT_PATH)
144
+ ii_args.push_back (INDEX_IMPORT_PATH);
145
+ #else
146
+ // Logical error
147
+ std::cerr << " Incorrectly compiled work_processor.cc" ;
148
+ exit_code = EXIT_FAILURE;
149
+ return exit_code;
150
+ #endif
151
+
152
+ for (it = outputs.begin (); it != outputs.end (); it++) {
153
+ // Need the actual output paths of the compiler - not bazel
154
+ auto output_path = it->first ;
155
+ auto file_type = output_path.substr (output_path.find_last_of (" ." ) + 1 );
156
+ if (file_type == " o" ) {
157
+ ii_args.push_back (" -import-output-file" );
158
+ ii_args.push_back (output_path);
159
+ }
160
+ }
161
+
162
+ auto exec_root = GetCurrentDirectory ();
163
+ // Copy back from the global index store to bazel's index store
164
+ ii_args.push_back (exec_root + " /" + global_index_store_import_path_);
165
+ ii_args.push_back (exec_root + " /" + index_store_path_);
166
+ exit_code =
167
+ RunSubProcess (ii_args, stderr_stream, /* stdout_to_stderr=*/ true );
168
+ }
132
169
return exit_code;
133
170
}
134
171
172
+ // Marker for end of iteration
173
+ class StreamIteratorEnd {};
174
+
175
+ // Basic iterator over an ifstream
176
+ class StreamIterator {
177
+ public:
178
+ StreamIterator (std::ifstream &file) : file_{file} { next (); }
179
+
180
+ const std::string &operator *() const { return str_; }
181
+
182
+ StreamIterator &operator ++() {
183
+ next ();
184
+ return *this ;
185
+ }
186
+
187
+ bool operator !=(StreamIteratorEnd) const { return !!file_; }
188
+
189
+ private:
190
+ void next () { std::getline (file_, str_); }
191
+
192
+ std::ifstream &file_;
193
+ std::string str_;
194
+ };
195
+
196
+ class ArgsFile {
197
+ public:
198
+ ArgsFile (std::ifstream &file) : file_(file) {}
199
+
200
+ StreamIterator begin () { return StreamIterator{file_}; }
201
+
202
+ StreamIteratorEnd end () { return StreamIteratorEnd{}; }
203
+
204
+ private:
205
+ std::ifstream &file_;
206
+ };
207
+
135
208
bool SwiftRunner::ProcessPossibleResponseFile (
136
209
const std::string &arg, std::function<void (const std::string &)> consumer) {
137
210
auto path = arg.substr (1 );
138
211
std::ifstream original_file (path);
212
+ ArgsFile args_file (original_file);
213
+
139
214
// If we couldn't open it, maybe it's not a file; maybe it's just some other
140
215
// argument that starts with "@" such as "@loader_path/..."
141
216
if (!original_file.good ()) {
142
217
consumer (arg);
143
218
return false ;
144
219
}
145
220
221
+ // Read the file to a vector to prevent double I/O
222
+ auto args = ParseArguments (args_file);
223
+
146
224
// If we're forcing response files, process and send the arguments from this
147
225
// file directly to the consumer; they'll all get written to the same response
148
226
// file at the end of processing all the arguments.
149
227
if (force_response_file_) {
150
- std::string arg_from_file;
151
- while (std::getline (original_file, arg_from_file)) {
228
+ for (auto it = args.begin (); it != args.end (); ++it) {
152
229
// Arguments in response files might be quoted/escaped, so we need to
153
230
// unescape them ourselves.
154
- ProcessArgument (Unescape (arg_from_file ), consumer);
231
+ ProcessArgument (it, Unescape (*it ), consumer);
155
232
}
156
233
return true ;
157
234
}
@@ -161,12 +238,10 @@ bool SwiftRunner::ProcessPossibleResponseFile(
161
238
bool changed = false ;
162
239
std::string arg_from_file;
163
240
std::vector<std::string> new_args;
164
-
165
- while (std::getline (original_file, arg_from_file)) {
166
- changed |=
167
- ProcessArgument (arg_from_file, [&](const std::string &processed_arg) {
168
- new_args.push_back (processed_arg);
169
- });
241
+ for (auto it = args.begin (); it != args.end (); ++it) {
242
+ changed |= ProcessArgument (it, *it, [&](const std::string &processed_arg) {
243
+ new_args.push_back (processed_arg);
244
+ });
170
245
}
171
246
172
247
if (changed) {
@@ -182,10 +257,11 @@ bool SwiftRunner::ProcessPossibleResponseFile(
182
257
return changed;
183
258
}
184
259
260
+ template <typename Iterator>
185
261
bool SwiftRunner::ProcessArgument (
186
- const std::string &arg, std::function<void (const std::string &)> consumer) {
262
+ Iterator &itr, const std::string &arg,
263
+ std::function<void (const std::string &)> consumer) {
187
264
bool changed = false ;
188
-
189
265
if (arg[0 ] == ' @' ) {
190
266
changed = ProcessPossibleResponseFile (arg, consumer);
191
267
} else {
@@ -198,8 +274,8 @@ bool SwiftRunner::ProcessArgument(
198
274
consumer (GetCurrentDirectory () + " =." );
199
275
changed = true ;
200
276
} else if (new_arg == " -coverage-prefix-pwd-is-dot" ) {
201
- // Get the actual current working directory (the workspace root), which we
202
- // didn't know at analysis time.
277
+ // Get the actual current working directory (the workspace root), which
278
+ // we didn't know at analysis time.
203
279
consumer (" -coverage-prefix-map" );
204
280
consumer (GetCurrentDirectory () + " =." );
205
281
changed = true ;
@@ -213,14 +289,37 @@ bool SwiftRunner::ProcessArgument(
213
289
temp_directories_.push_back (std::move (module_cache_dir));
214
290
changed = true ;
215
291
} else if (StripPrefix (" -generated-header-rewriter=" , new_arg)) {
216
- generated_header_rewriter_path_ = new_arg;
292
+ changed = true ;
293
+ } else if (StripPrefix (" -global-index-store-import-path=" , new_arg)) {
217
294
changed = true ;
218
295
} else {
219
296
// TODO(allevato): Report that an unknown wrapper arg was found and give
220
297
// the caller a way to exit gracefully.
221
298
changed = true ;
222
299
}
223
300
} else {
301
+ // Process default arguments
302
+ if (arg == " -index-store-path" ) {
303
+ consumer (" -index-store-path" );
304
+ ++itr;
305
+
306
+ // If there was a global index store set, pass that to swiftc.
307
+ // Otherwise, pass the users. We later copy index data onto the users.
308
+ if (global_index_store_import_path_ != " " ) {
309
+ new_arg = global_index_store_import_path_;
310
+ } else {
311
+ new_arg = index_store_path_;
312
+ }
313
+ changed = true ;
314
+ } else if (arg == " -output-file-map" ) {
315
+ // Save the output file map to the value proceeding
316
+ // `-output-file-map`
317
+ consumer (" -output-file-map" );
318
+ ++itr;
319
+ new_arg = output_file_map_path_;
320
+ changed = true ;
321
+ }
322
+
224
323
// Apply any other text substitutions needed in the argument (i.e., for
225
324
// Apple toolchains).
226
325
//
@@ -236,6 +335,36 @@ bool SwiftRunner::ProcessArgument(
236
335
return changed;
237
336
}
238
337
338
+ template <typename Iterator>
339
+ std::vector<std::string> SwiftRunner::ParseArguments (Iterator itr) {
340
+ std::vector<std::string> out_args;
341
+ for (auto it = itr.begin (); it != itr.end (); ++it) {
342
+ auto arg = *it;
343
+ out_args.push_back (arg);
344
+
345
+ if (StripPrefix (" -Xwrapped-swift=" , arg)) {
346
+ if (StripPrefix (" -global-index-store-import-path=" , arg)) {
347
+ global_index_store_import_path_ = arg;
348
+ } else if (StripPrefix (" -generated-header-rewriter=" , arg)) {
349
+ generated_header_rewriter_path_ = arg;
350
+ }
351
+ } else {
352
+ if (arg == " -output-file-map" ) {
353
+ ++it;
354
+ arg = *it;
355
+ output_file_map_path_ = arg;
356
+ out_args.push_back (arg);
357
+ } else if (arg == " -index-store-path" ) {
358
+ ++it;
359
+ arg = *it;
360
+ index_store_path_ = arg;
361
+ out_args.push_back (arg);
362
+ }
363
+ }
364
+ }
365
+ return out_args;
366
+ }
367
+
239
368
std::vector<std::string> SwiftRunner::ProcessArguments (
240
369
const std::vector<std::string> &args) {
241
370
std::vector<std::string> new_args;
@@ -248,16 +377,19 @@ std::vector<std::string> SwiftRunner::ProcessArguments(
248
377
#endif
249
378
250
379
// The tool is assumed to be the first argument. Push it directly.
251
- auto it = args.begin ();
380
+ auto parsed_args = ParseArguments (args);
381
+
382
+ auto it = parsed_args.begin ();
252
383
new_args.push_back (*it++);
253
384
254
385
// If we're forcing response files, push the remaining processed args onto a
255
386
// different vector that we write out below. If not, push them directly onto
256
387
// the vector being returned.
257
388
auto &args_destination = force_response_file_ ? response_file_args : new_args;
258
- while (it != args.end ()) {
259
- ProcessArgument (
260
- *it, [&](const std::string &arg) { args_destination.push_back (arg); });
389
+ while (it != parsed_args.end ()) {
390
+ ProcessArgument (it, *it, [&](const std::string &arg) {
391
+ args_destination.push_back (arg);
392
+ });
261
393
++it;
262
394
}
263
395
0 commit comments