Skip to content

Commit 20cb3e3

Browse files
committed
[driver] Add -working-directory option
Adds a -working-directory option which can be used to modify how relative paths are resolved. It affects all other paths used in driver options (controlled by a new ArgumentIsPath flag on options) as well as the contents of output file maps and auxilliary file paths generated implicitly by the compiler itself. rdar://37713856
1 parent 642cbba commit 20cb3e3

File tree

9 files changed

+388
-117
lines changed

9 files changed

+388
-117
lines changed

include/swift/Driver/Driver.h

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,11 @@ class Driver {
205205
std::unique_ptr<llvm::opt::InputArgList>
206206
parseArgStrings(ArrayRef<const char *> Args);
207207

208-
/// Translate the input arguments into a DerivedArgList.
209-
llvm::opt::DerivedArgList *translateInputArgs(
210-
const llvm::opt::InputArgList &ArgList) const;
208+
/// Resolve path arguments if \p workingDirectory is non-empty, and translate
209+
/// inputs from -- arguments into a DerivedArgList.
210+
llvm::opt::DerivedArgList *
211+
translateInputAndPathArgs(const llvm::opt::InputArgList &ArgList,
212+
StringRef workingDirectory) const;
211213

212214
/// Construct the list of inputs and their types from the given arguments.
213215
///
@@ -247,20 +249,22 @@ class Driver {
247249

248250
/// Construct the OutputFileMap for the driver from the given arguments.
249251
std::unique_ptr<OutputFileMap>
250-
buildOutputFileMap(const llvm::opt::DerivedArgList &Args) const;
252+
buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
253+
StringRef workingDirectory) const;
251254

252255
/// Add top-level Jobs to Compilation \p C for the given \p Actions and
253256
/// OutputInfo.
254257
///
255258
/// \param TopLevelActions The main Actions to build Jobs for.
256259
/// \param OI The OutputInfo for which Jobs should be generated.
257260
/// \param OFM The OutputFileMap for which Jobs should be generated.
261+
/// \param workingDirectory If non-empty, used to resolve any generated paths.
258262
/// \param TC The ToolChain to build Jobs with.
259263
/// \param C The Compilation containing the Actions for which Jobs should be
260264
/// created.
261265
void buildJobs(ArrayRef<const Action *> TopLevelActions, const OutputInfo &OI,
262-
const OutputFileMap *OFM, const ToolChain &TC,
263-
Compilation &C) const;
266+
const OutputFileMap *OFM, StringRef workingDirectory,
267+
const ToolChain &TC, Compilation &C) const;
264268

265269
/// A map for caching Jobs for a given Action/ToolChain pair
266270
using JobCacheMap =
@@ -280,8 +284,8 @@ class Driver {
280284
/// \returns a Job for the given Action/ToolChain pair
281285
Job *buildJobsForAction(Compilation &C, const JobAction *JA,
282286
const OutputInfo &OI, const OutputFileMap *OFM,
283-
const ToolChain &TC, bool AtTopLevel,
284-
JobCacheMap &JobCache) const;
287+
StringRef workingDirectory, const ToolChain &TC,
288+
bool AtTopLevel, JobCacheMap &JobCache) const;
285289

286290
private:
287291
void computeMainOutput(Compilation &C, const JobAction *JA,
@@ -290,6 +294,7 @@ class Driver {
290294
SmallVectorImpl<const Action *> &InputActions,
291295
SmallVectorImpl<const Job *> &InputJobs,
292296
const TypeToPathMap *OutputMap,
297+
StringRef workingDirectory,
293298
StringRef BaseInput,
294299
StringRef PrimaryInput,
295300
llvm::SmallString<128> &Buf,
@@ -298,38 +303,46 @@ class Driver {
298303
void chooseSwiftModuleOutputPath(Compilation &C, const OutputInfo &OI,
299304
const OutputFileMap *OFM,
300305
const TypeToPathMap *OutputMap,
306+
StringRef workingDirectory,
301307
CommandOutput *Output) const;
302308

303309
void chooseSwiftModuleDocOutputPath(Compilation &C,
304310
const TypeToPathMap *OutputMap,
311+
StringRef workingDirectory,
305312
CommandOutput *Output) const;
306313
void chooseRemappingOutputPath(Compilation &C, const TypeToPathMap *OutputMap,
307314
CommandOutput *Output) const;
308315

309316
void chooseSerializedDiagnosticsPath(Compilation &C, const JobAction *JA,
310317
const OutputInfo &OI,
311318
const TypeToPathMap *OutputMap,
319+
StringRef workingDirectory,
312320
CommandOutput *Output) const;
313321

314322
void chooseDependenciesOutputPaths(Compilation &C, const OutputInfo &OI,
315323
const TypeToPathMap *OutputMap,
324+
StringRef workingDirectory,
316325
llvm::SmallString<128> &Buf,
317326
CommandOutput *Output) const;
318327

319328
void chooseOptimizationRecordPath(Compilation &C, const OutputInfo &OI,
329+
StringRef workingDirectory,
320330
llvm::SmallString<128> &Buf,
321331
CommandOutput *Output) const;
322332

323333
void chooseObjectiveCHeaderOutputPath(Compilation &C, const OutputInfo &OI,
324334
const TypeToPathMap *OutputMap,
335+
StringRef workingDirectory,
325336
CommandOutput *Output) const;
326337

327338
void chooseLoadedModuleTracePath(Compilation &C, const OutputInfo &OI,
339+
StringRef workingDirectory,
328340
llvm::SmallString<128> &Buf,
329341
CommandOutput *Output) const;
330342

331343
void chooseTBDPath(Compilation &C, const OutputInfo &OI,
332-
llvm::SmallString<128> &Buf, CommandOutput *Output) const;
344+
StringRef workingDirectory, llvm::SmallString<128> &Buf,
345+
CommandOutput *Output) const;
333346

334347
public:
335348
/// Handle any arguments which should be treated before building actions or

include/swift/Driver/OutputFileMap.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,23 @@ class OutputFileMap {
3939
~OutputFileMap() = default;
4040

4141
/// Loads an OutputFileMap from the given \p Path, if possible.
42-
static std::unique_ptr<OutputFileMap> loadFromPath(StringRef Path);
42+
///
43+
/// When non-empty, \p workingDirectory is used to resolve relative paths in
44+
/// the output file map.
45+
static std::unique_ptr<OutputFileMap>
46+
loadFromPath(StringRef Path, StringRef workingDirectory);
4347

44-
static std::unique_ptr<OutputFileMap> loadFromBuffer(StringRef Data);
48+
static std::unique_ptr<OutputFileMap>
49+
loadFromBuffer(StringRef Data, StringRef workingDirectory);
4550

4651
/// Loads an OutputFileMap from the given \p Buffer, taking ownership
4752
/// of the buffer in the process.
53+
///
54+
/// When non-empty, \p workingDirectory is used to resolve relative paths in
55+
/// the output file map.
4856
static std::unique_ptr<OutputFileMap>
49-
loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
57+
loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer,
58+
StringRef workingDirectory);
5059

5160
/// Get the map of outputs for the given \p Input, if present in the
5261
/// OutputFileMap. (If not present, returns nullptr.)
@@ -69,8 +78,12 @@ class OutputFileMap {
6978
/// \brief Parses the given \p Buffer into the OutputFileMap, taking ownership
7079
/// of \p Buffer in the process.
7180
///
81+
/// When non-empty, \p workingDirectory is used to resolve relative paths in
82+
/// the output file map.
83+
///
7284
/// \returns true on error, false on success
73-
bool parse(std::unique_ptr<llvm::MemoryBuffer> Buffer);
85+
bool parse(std::unique_ptr<llvm::MemoryBuffer> Buffer,
86+
StringRef workingDirectory);
7487
};
7588

7689
} // end namespace driver

include/swift/Option/Options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace options {
3434
AutolinkExtractOption = (1 << 9),
3535
ModuleWrapOption = (1 << 10),
3636
SwiftFormatOption = (1 << 11),
37+
ArgumentIsPath = (1 << 12),
3738
};
3839

3940
enum ID {

include/swift/Option/Options.td

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ def NoBatchOption : OptionFlag;
4343
// The option should not force a full rebuild if added, changed, or removed.
4444
def DoesNotAffectIncrementalBuild : OptionFlag;
4545

46+
// The option's argument is a file-system path that may be affected by the
47+
// current working directory.
48+
def ArgumentIsPath : OptionFlag;
49+
4650
/////////
4751
// Options
4852

@@ -129,47 +133,51 @@ def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
129133

130134
def o : JoinedOrSeparate<["-"], "o">,
131135
Flags<[FrontendOption, AutolinkExtractOption, ModuleWrapOption,
132-
NoInteractiveOption, SwiftFormatOption]>,
136+
NoInteractiveOption, SwiftFormatOption, ArgumentIsPath]>,
133137
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
134138

135139
def j : JoinedOrSeparate<["-"], "j">, Flags<[DoesNotAffectIncrementalBuild]>,
136140
HelpText<"Number of commands to execute in parallel">, MetaVarName<"<n>">;
137141

138-
def sdk : Separate<["-"], "sdk">, Flags<[FrontendOption]>,
142+
def sdk : Separate<["-"], "sdk">, Flags<[FrontendOption, ArgumentIsPath]>,
139143
HelpText<"Compile against <sdk>">, MetaVarName<"<sdk>">;
140144

141145
def swift_version : Separate<["-"], "swift-version">, Flags<[FrontendOption]>,
142146
HelpText<"Interpret input according to a specific Swift language version number">,
143147
MetaVarName<"<vers>">;
144148

145149
def tools_directory : Separate<["-"], "tools-directory">,
146-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
150+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
151+
ArgumentIsPath]>,
147152
HelpText<"Look for external executables (ld, clang, binutils) in <directory>">, MetaVarName<"<directory>">;
148153

149154
def D : JoinedOrSeparate<["-"], "D">, Flags<[FrontendOption]>,
150155
HelpText<"Marks a conditional compilation flag as true">;
151156

152-
def F : JoinedOrSeparate<["-"], "F">, Flags<[FrontendOption]>,
157+
def F : JoinedOrSeparate<["-"], "F">, Flags<[FrontendOption, ArgumentIsPath]>,
153158
HelpText<"Add directory to framework search path">;
154-
def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption]>, Alias<F>;
159+
def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption, ArgumentIsPath]>,
160+
Alias<F>;
155161

156-
def Fsystem : Separate<["-"], "Fsystem">, Flags<[FrontendOption]>,
162+
def Fsystem : Separate<["-"], "Fsystem">,
163+
Flags<[FrontendOption, ArgumentIsPath]>,
157164
HelpText<"Add directory to system framework search path">;
158165

159-
def I : JoinedOrSeparate<["-"], "I">, Flags<[FrontendOption]>,
166+
def I : JoinedOrSeparate<["-"], "I">, Flags<[FrontendOption, ArgumentIsPath]>,
160167
HelpText<"Add directory to the import search path">;
161-
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption]>, Alias<I>;
168+
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>,
169+
Alias<I>;
162170

163171
def import_underlying_module : Flag<["-"], "import-underlying-module">,
164172
Flags<[FrontendOption, NoInteractiveOption]>,
165173
HelpText<"Implicitly imports the Objective-C half of a module">;
166174

167175
def import_objc_header : Separate<["-"], "import-objc-header">,
168-
Flags<[FrontendOption, HelpHidden]>,
176+
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
169177
HelpText<"Implicitly imports an Objective-C header file">;
170178

171179
def pch_output_dir: Separate<["-"], "pch-output-dir">,
172-
Flags<[FrontendOption, HelpHidden]>,
180+
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
173181
HelpText<"Directory to persist automatically created precompiled bridging headers">;
174182

175183
// FIXME: Unhide this once it doesn't depend on an output file map.
@@ -181,10 +189,11 @@ def nostdimport : Flag<["-"], "nostdimport">, Flags<[FrontendOption]>,
181189
HelpText<"Don't search the standard library import path for modules">;
182190

183191
def output_file_map : Separate<["-"], "output-file-map">,
184-
Flags<[NoInteractiveOption]>,
192+
Flags<[NoInteractiveOption, ArgumentIsPath]>,
185193
HelpText<"A file which specifies the location of outputs">,
186194
MetaVarName<"<path>">;
187195
def output_file_map_EQ : Joined<["-"], "output-file-map=">,
196+
Flags<[NoInteractiveOption, ArgumentIsPath]>,
188197
Alias<output_file_map>;
189198

190199
def save_temps : Flag<["-"], "save-temps">,
@@ -194,7 +203,7 @@ def driver_time_compilation : Flag<["-"], "driver-time-compilation">,
194203
Flags<[NoInteractiveOption,DoesNotAffectIncrementalBuild]>,
195204
HelpText<"Prints the total time it took to execute all compilation tasks">;
196205
def stats_output_dir: Separate<["-"], "stats-output-dir">,
197-
Flags<[FrontendOption, HelpHidden]>,
206+
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
198207
HelpText<"Directory to write unified compilation-statistics files to">;
199208
def trace_stats_events: Flag<["-"], "trace-stats-events">,
200209
Flags<[FrontendOption, HelpHidden]>,
@@ -208,28 +217,30 @@ def emit_loaded_module_trace : Flag<["-"], "emit-loaded-module-trace">,
208217
Flags<[FrontendOption, NoInteractiveOption]>,
209218
HelpText<"Emit a JSON file containing information about what modules were loaded">;
210219
def emit_loaded_module_trace_path : Separate<["-"], "emit-loaded-module-trace-path">,
211-
Flags<[FrontendOption, NoInteractiveOption]>,
220+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
212221
HelpText<"Emit the loaded module trace JSON to <path>">,
213222
MetaVarName<"<path>">;
214223
def emit_loaded_module_trace_path_EQ : Joined<["-"], "emit-loaded-module-trace-path=">,
215-
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_loaded_module_trace_path>;
224+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
225+
Alias<emit_loaded_module_trace_path>;
216226

217227
def emit_tbd : Flag<["-"], "emit-tbd">,
218228
HelpText<"Emit a TBD file">,
219229
Flags<[FrontendOption, NoInteractiveOption]>;
220230
def emit_tbd_path : Separate<["-"], "emit-tbd-path">,
221-
Flags<[FrontendOption, NoInteractiveOption]>,
231+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
222232
HelpText<"Emit the TBD file to <path>">,
223233
MetaVarName<"<path>">;
224234
def emit_tbd_path_EQ : Joined<["-"], "emit-tbd-path=">,
225-
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_tbd_path>;
235+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
236+
Alias<emit_tbd_path>;
226237

227238
def serialize_diagnostics : Flag<["-"], "serialize-diagnostics">,
228239
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
229240
HelpText<"Serialize diagnostics in a binary format">;
230241

231242
def module_cache_path : Separate<["-"], "module-cache-path">,
232-
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
243+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
233244
HelpText<"Specifies the Clang module cache path">;
234245

235246
def module_name : Separate<["-"], "module-name">, Flags<[FrontendOption]>,
@@ -250,17 +261,21 @@ def emit_module : Flag<["-"], "emit-module">,
250261
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
251262
HelpText<"Emit an importable module">;
252263
def emit_module_path : Separate<["-"], "emit-module-path">,
253-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
264+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
265+
ArgumentIsPath]>,
254266
HelpText<"Emit an importable module to <path>">,
255267
MetaVarName<"<path>">;
256268
def emit_module_path_EQ : Joined<["-"], "emit-module-path=">,
257-
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_module_path>;
269+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
270+
ArgumentIsPath]>,
271+
Alias<emit_module_path>;
258272

259273
def emit_objc_header : Flag<["-"], "emit-objc-header">,
260274
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
261275
HelpText<"Emit an Objective-C header file">;
262276
def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
263-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
277+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
278+
ArgumentIsPath]>,
264279
MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;
265280

266281
def import_cf_types : Flag<["-"], "import-cf-types">,
@@ -337,7 +352,7 @@ def save_optimization_record : Flag<["-"], "save-optimization-record">,
337352
Flags<[FrontendOption]>, HelpText<"Generate a YAML optimization record file">;
338353
def save_optimization_record_path :
339354
Separate<["-"], "save-optimization-record-path">,
340-
Flags<[FrontendOption]>,
355+
Flags<[FrontendOption, ArgumentIsPath]>,
341356
HelpText<"Specify the file name of any generated YAML optimization record">;
342357

343358
// Platform options.
@@ -357,9 +372,11 @@ def framework : Separate<["-"], "framework">, Group<linker_option_Group>,
357372
HelpText<"Specifies a framework which should be linked against">;
358373

359374
def L : JoinedOrSeparate<["-"], "L">, Group<linker_option_Group>,
360-
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
375+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
361376
HelpText<"Add directory to library link search path">;
362-
def L_EQ : Joined<["-"], "L=">, Alias<L>;
377+
def L_EQ : Joined<["-"], "L=">,
378+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
379+
Alias<L>;
363380

364381
def link_objc_runtime : Flag<["-"], "link-objc-runtime">,
365382
Flags<[DoesNotAffectIncrementalBuild]>;
@@ -495,12 +512,14 @@ def emit_migrated_file_path: Separate<["-"], "emit-migrated-file-path">,
495512
MetaVarName<"<path>">;
496513

497514
def dump_migration_states_dir: Separate<["-"], "dump-migration-states-dir">,
498-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
515+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
516+
ArgumentIsPath]>,
499517
HelpText<"Dump the input text, output text, and states for migration to <path>">,
500518
MetaVarName<"<path>">;
501519

502520
def api_diff_data_file: Separate<["-"], "api-diff-data-file">,
503-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
521+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
522+
ArgumentIsPath]>,
504523
HelpText<"API migration data is from <path>">,
505524
MetaVarName<"<path>">;
506525

@@ -654,7 +673,7 @@ def Xllvm : Separate<["-"], "Xllvm">,
654673
MetaVarName<"<arg>">, HelpText<"Pass <arg> to LLVM.">;
655674

656675
def resource_dir : Separate<["-"], "resource-dir">,
657-
Flags<[FrontendOption, HelpHidden]>,
676+
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
658677
MetaVarName<"</usr/lib/swift>">,
659678
HelpText<"The directory that holds the compiler resource files">;
660679

@@ -672,7 +691,8 @@ def profile_generate : Flag<["-"], "profile-generate">,
672691
HelpText<"Generate instrumented code to collect execution counts">;
673692

674693
def profile_use : CommaJoined<["-"], "profile-use=">,
675-
Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"<profdata>">,
694+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
695+
MetaVarName<"<profdata>">,
676696
HelpText<"Supply a profdata file to enable profile-guided optimization">;
677697

678698
def profile_coverage_mapping : Flag<["-"], "profile-coverage-mapping">,
@@ -705,16 +725,22 @@ def index_file : Flag<["-"], "index-file">,
705725
HelpText<"Produce index data for a source file">, ModeOpt,
706726
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
707727
def index_file_path : Separate<["-"], "index-file-path">,
708-
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
728+
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
709729
HelpText<"Produce index data for file <path>">,
710730
MetaVarName<"<path>">;
711731

712732
def index_store_path : Separate<["-"], "index-store-path">,
713-
Flags<[FrontendOption]>, MetaVarName<"<path>">,
733+
Flags<[FrontendOption, ArgumentIsPath]>, MetaVarName<"<path>">,
714734
HelpText<"Store indexing data to <path>">;
715735

716736
def enforce_exclusivity_EQ : Joined<["-"], "enforce-exclusivity=">,
717737
Flags<[FrontendOption]>, MetaVarName<"<enforcement>">,
718738
HelpText<"Enforce law of exclusivity">;
719739

740+
def working_directory : Separate<["-"], "working-directory">,
741+
HelpText<"Resolve file paths relative to the specified directory">,
742+
MetaVarName<"<path>">;
743+
def working_directory_EQ : Joined<["-"], "working-directory=">,
744+
Alias<working_directory>;
745+
720746
include "FrontendOptions.td"

0 commit comments

Comments
 (0)