Skip to content

[driver] Add -working-directory option #14746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions include/swift/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,11 @@ class Driver {
std::unique_ptr<llvm::opt::InputArgList>
parseArgStrings(ArrayRef<const char *> Args);

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

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

/// Construct the OutputFileMap for the driver from the given arguments.
std::unique_ptr<OutputFileMap>
buildOutputFileMap(const llvm::opt::DerivedArgList &Args) const;
buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
StringRef workingDirectory) const;

/// Add top-level Jobs to Compilation \p C for the given \p Actions and
/// OutputInfo.
///
/// \param TopLevelActions The main Actions to build Jobs for.
/// \param OI The OutputInfo for which Jobs should be generated.
/// \param OFM The OutputFileMap for which Jobs should be generated.
/// \param workingDirectory If non-empty, used to resolve any generated paths.
/// \param TC The ToolChain to build Jobs with.
/// \param C The Compilation containing the Actions for which Jobs should be
/// created.
void buildJobs(ArrayRef<const Action *> TopLevelActions, const OutputInfo &OI,
const OutputFileMap *OFM, const ToolChain &TC,
Compilation &C) const;
const OutputFileMap *OFM, StringRef workingDirectory,
const ToolChain &TC, Compilation &C) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer to make this a field on the Compilation object. It's of a similar provenance to the other things stored there and it looks like you're having to thread it through lots of calls that already take a Compilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh fun. I was following the example of OutputFileMap, OutputInfo and ToolChain. Now that I look more carefully at Compilation, I see we have fields for all three of those (and they appear to me to be the same objects), so I don't know why we also thread them through every call too. I'm happy to move working dir into Compilation assuming @jrose-apple agrees.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love it because it seems like something that's only used while building up the Compilation, and not something you need once it's fully-built and ready to, well, compile things. But maybe that distinction's only in my head.

(Originally, none of the three things you mentioned were in Compilation. They've all migrated there because of batch mode, which needs to construct jobs "late".)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OutputFileMap held in the compilation is a derived one (holding all the aux and intermediates in a compilation), whereas the one being passed around as args here is an input. This is a somewhat recent development and perhaps not ideal, but they're not the same object.

The ToolChain and OutputInfo args are the same as those being threaded around though, it's true; I guess we can just pull them out of Compilation now (they're new arrivals).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, ok. On matters of taste here I'm happy to defer to @jrose-apple, passed-as-an-arg it is!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll admit I don't love another argument being passed around either. I'm just not sure Compilation is the place to put it. And Ben doesn't have to be the one to clean this up.


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

private:
void computeMainOutput(Compilation &C, const JobAction *JA,
Expand All @@ -290,6 +294,7 @@ class Driver {
SmallVectorImpl<const Action *> &InputActions,
SmallVectorImpl<const Job *> &InputJobs,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
StringRef BaseInput,
StringRef PrimaryInput,
llvm::SmallString<128> &Buf,
Expand All @@ -298,38 +303,46 @@ class Driver {
void chooseSwiftModuleOutputPath(Compilation &C, const OutputInfo &OI,
const OutputFileMap *OFM,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
CommandOutput *Output) const;

void chooseSwiftModuleDocOutputPath(Compilation &C,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
CommandOutput *Output) const;
void chooseRemappingOutputPath(Compilation &C, const TypeToPathMap *OutputMap,
CommandOutput *Output) const;

void chooseSerializedDiagnosticsPath(Compilation &C, const JobAction *JA,
const OutputInfo &OI,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
CommandOutput *Output) const;

void chooseDependenciesOutputPaths(Compilation &C, const OutputInfo &OI,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
llvm::SmallString<128> &Buf,
CommandOutput *Output) const;

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

void chooseObjectiveCHeaderOutputPath(Compilation &C, const OutputInfo &OI,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
CommandOutput *Output) const;

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

void chooseTBDPath(Compilation &C, const OutputInfo &OI,
llvm::SmallString<128> &Buf, CommandOutput *Output) const;
StringRef workingDirectory, llvm::SmallString<128> &Buf,
CommandOutput *Output) const;

public:
/// Handle any arguments which should be treated before building actions or
Expand Down
21 changes: 17 additions & 4 deletions include/swift/Driver/OutputFileMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,23 @@ class OutputFileMap {
~OutputFileMap() = default;

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

static std::unique_ptr<OutputFileMap> loadFromBuffer(StringRef Data);
static std::unique_ptr<OutputFileMap>
loadFromBuffer(StringRef Data, StringRef workingDirectory);

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

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

} // end namespace driver
Expand Down
1 change: 1 addition & 0 deletions include/swift/Option/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace options {
AutolinkExtractOption = (1 << 9),
ModuleWrapOption = (1 << 10),
SwiftFormatOption = (1 << 11),
ArgumentIsPath = (1 << 12),
};

enum ID {
Expand Down
84 changes: 55 additions & 29 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ def NoBatchOption : OptionFlag;
// The option should not force a full rebuild if added, changed, or removed.
def DoesNotAffectIncrementalBuild : OptionFlag;

// The option's argument is a file-system path that may be affected by the
// current working directory.
def ArgumentIsPath : OptionFlag;

/////////
// Options

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

def o : JoinedOrSeparate<["-"], "o">,
Flags<[FrontendOption, AutolinkExtractOption, ModuleWrapOption,
NoInteractiveOption, SwiftFormatOption]>,
NoInteractiveOption, SwiftFormatOption, ArgumentIsPath]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;

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

def sdk : Separate<["-"], "sdk">, Flags<[FrontendOption]>,
def sdk : Separate<["-"], "sdk">, Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Compile against <sdk>">, MetaVarName<"<sdk>">;

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

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

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

def F : JoinedOrSeparate<["-"], "F">, Flags<[FrontendOption]>,
def F : JoinedOrSeparate<["-"], "F">, Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Add directory to framework search path">;
def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption]>, Alias<F>;
def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption, ArgumentIsPath]>,
Alias<F>;

def Fsystem : Separate<["-"], "Fsystem">, Flags<[FrontendOption]>,
def Fsystem : Separate<["-"], "Fsystem">,
Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Add directory to system framework search path">;

def I : JoinedOrSeparate<["-"], "I">, Flags<[FrontendOption]>,
def I : JoinedOrSeparate<["-"], "I">, Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Add directory to the import search path">;
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption]>, Alias<I>;
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>,
Alias<I>;

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

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

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

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

def output_file_map : Separate<["-"], "output-file-map">,
Flags<[NoInteractiveOption]>,
Flags<[NoInteractiveOption, ArgumentIsPath]>,
HelpText<"A file which specifies the location of outputs">,
MetaVarName<"<path>">;
def output_file_map_EQ : Joined<["-"], "output-file-map=">,
Flags<[NoInteractiveOption, ArgumentIsPath]>,
Alias<output_file_map>;

def save_temps : Flag<["-"], "save-temps">,
Expand All @@ -194,7 +203,7 @@ def driver_time_compilation : Flag<["-"], "driver-time-compilation">,
Flags<[NoInteractiveOption,DoesNotAffectIncrementalBuild]>,
HelpText<"Prints the total time it took to execute all compilation tasks">;
def stats_output_dir: Separate<["-"], "stats-output-dir">,
Flags<[FrontendOption, HelpHidden]>,
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
HelpText<"Directory to write unified compilation-statistics files to">;
def trace_stats_events: Flag<["-"], "trace-stats-events">,
Flags<[FrontendOption, HelpHidden]>,
Expand All @@ -208,28 +217,30 @@ def emit_loaded_module_trace : Flag<["-"], "emit-loaded-module-trace">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Emit a JSON file containing information about what modules were loaded">;
def emit_loaded_module_trace_path : Separate<["-"], "emit-loaded-module-trace-path">,
Flags<[FrontendOption, NoInteractiveOption]>,
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
HelpText<"Emit the loaded module trace JSON to <path>">,
MetaVarName<"<path>">;
def emit_loaded_module_trace_path_EQ : Joined<["-"], "emit-loaded-module-trace-path=">,
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_loaded_module_trace_path>;
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
Alias<emit_loaded_module_trace_path>;

def emit_tbd : Flag<["-"], "emit-tbd">,
HelpText<"Emit a TBD file">,
Flags<[FrontendOption, NoInteractiveOption]>;
def emit_tbd_path : Separate<["-"], "emit-tbd-path">,
Flags<[FrontendOption, NoInteractiveOption]>,
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
HelpText<"Emit the TBD file to <path>">,
MetaVarName<"<path>">;
def emit_tbd_path_EQ : Joined<["-"], "emit-tbd-path=">,
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_tbd_path>;
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
Alias<emit_tbd_path>;

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

def module_cache_path : Separate<["-"], "module-cache-path">,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
HelpText<"Specifies the Clang module cache path">;

def module_name : Separate<["-"], "module-name">, Flags<[FrontendOption]>,
Expand All @@ -250,17 +261,21 @@ def emit_module : Flag<["-"], "emit-module">,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
HelpText<"Emit an importable module">;
def emit_module_path : Separate<["-"], "emit-module-path">,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
ArgumentIsPath]>,
HelpText<"Emit an importable module to <path>">,
MetaVarName<"<path>">;
def emit_module_path_EQ : Joined<["-"], "emit-module-path=">,
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_module_path>;
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
ArgumentIsPath]>,
Alias<emit_module_path>;

def emit_objc_header : Flag<["-"], "emit-objc-header">,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
HelpText<"Emit an Objective-C header file">;
def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
ArgumentIsPath]>,
MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;

def import_cf_types : Flag<["-"], "import-cf-types">,
Expand Down Expand Up @@ -337,7 +352,7 @@ def save_optimization_record : Flag<["-"], "save-optimization-record">,
Flags<[FrontendOption]>, HelpText<"Generate a YAML optimization record file">;
def save_optimization_record_path :
Separate<["-"], "save-optimization-record-path">,
Flags<[FrontendOption]>,
Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Specify the file name of any generated YAML optimization record">;

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

def L : JoinedOrSeparate<["-"], "L">, Group<linker_option_Group>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
HelpText<"Add directory to library link search path">;
def L_EQ : Joined<["-"], "L=">, Alias<L>;
def L_EQ : Joined<["-"], "L=">,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
Alias<L>;

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

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

def api_diff_data_file: Separate<["-"], "api-diff-data-file">,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
ArgumentIsPath]>,
HelpText<"API migration data is from <path>">,
MetaVarName<"<path>">;

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

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

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

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

def profile_coverage_mapping : Flag<["-"], "profile-coverage-mapping">,
Expand Down Expand Up @@ -705,16 +725,22 @@ def index_file : Flag<["-"], "index-file">,
HelpText<"Produce index data for a source file">, ModeOpt,
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
def index_file_path : Separate<["-"], "index-file-path">,
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
HelpText<"Produce index data for file <path>">,
MetaVarName<"<path>">;

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

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

def working_directory : Separate<["-"], "working-directory">,
HelpText<"Resolve file paths relative to the specified directory">,
MetaVarName<"<path>">;
def working_directory_EQ : Joined<["-"], "working-directory=">,
Alias<working_directory>;

include "FrontendOptions.td"
Loading