mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Driver] Allow passing all source files in a filelist.
Generate frontend commands with -filelist in them. This isn't actually implemented yet, but we can start testing at this point. Part 1 of https://bugs.swift.org/browse/SR-280.
This commit is contained in:
@@ -78,6 +78,12 @@ private:
|
||||
/// A list of input files and their associated types.
|
||||
InputFileList InputFilesWithTypes;
|
||||
|
||||
/// When non-null, a temporary file containing all input .swift files.
|
||||
/// Used for large compilations to avoid overflowing argv.
|
||||
///
|
||||
/// This is a pointer to a string whose data is held in #TempFilePaths.
|
||||
std::string AllSourceFilesPath;
|
||||
|
||||
/// Temporary files that should be cleaned up after the compilation finishes.
|
||||
///
|
||||
/// These apply whether the compilation succeeds or fails.
|
||||
@@ -194,6 +200,15 @@ public:
|
||||
LastBuildTime = time;
|
||||
}
|
||||
|
||||
/// Requests the path to a file containing all input source files. This can
|
||||
/// be shared across jobs.
|
||||
///
|
||||
/// If this is never called, the Compilation does not bother generating such
|
||||
/// a file.
|
||||
///
|
||||
/// \sa types::isPartOfSwiftCompilation
|
||||
const std::string &getAllSourcesPath() const;
|
||||
|
||||
/// Asks the Compilation to perform the Jobs which it knows about.
|
||||
/// \returns result code for the Compilation's Jobs; 0 indicates success and
|
||||
/// -2 indicates that one of the Compilation's Jobs crashed during execution
|
||||
|
||||
@@ -50,13 +50,32 @@ protected:
|
||||
constexpr static const char * const SWIFT_EXECUTABLE_NAME = "swift";
|
||||
|
||||
/// Packs together the supplementary information about the job being created.
|
||||
struct JobContext {
|
||||
class JobContext {
|
||||
private:
|
||||
const Compilation &C;
|
||||
|
||||
public:
|
||||
ArrayRef<const Job *> Inputs;
|
||||
const CommandOutput &Output;
|
||||
ArrayRef<const Action *> InputActions;
|
||||
const llvm::opt::ArgList &Args;
|
||||
ArrayRef<InputPair> TopLevelInputFiles;
|
||||
const CommandOutput &Output;
|
||||
const OutputInfo &OI;
|
||||
|
||||
/// The arguments to the driver. Can also be used to create new strings with
|
||||
/// the same lifetime.
|
||||
///
|
||||
/// This just caches C.getArgs().
|
||||
const llvm::opt::ArgList &Args;
|
||||
|
||||
public:
|
||||
JobContext(const Compilation &C, ArrayRef<const Job *> Inputs,
|
||||
ArrayRef<const Action *> InputActions,
|
||||
const CommandOutput &Output, const OutputInfo &OI);
|
||||
|
||||
/// Forwards to Compilation::getInputFiles.
|
||||
ArrayRef<InputPair> getTopLevelInputFiles() const;
|
||||
|
||||
/// Forwards to Compilation::getAllSourcesPath.
|
||||
const std::string &getAllSourcesPath() const;
|
||||
};
|
||||
|
||||
/// Packs together information chosen by toolchains to create jobs.
|
||||
@@ -126,11 +145,10 @@ public:
|
||||
/// This method dispatches to the various \c constructInvocation methods,
|
||||
/// which may be overridden by platform-specific subclasses.
|
||||
std::unique_ptr<Job> constructJob(const JobAction &JA,
|
||||
const Compilation &C,
|
||||
SmallVectorImpl<const Job *> &&inputs,
|
||||
std::unique_ptr<CommandOutput> output,
|
||||
const ActionList &inputActions,
|
||||
const llvm::opt::ArgList &args,
|
||||
ArrayRef<InputPair> topLevelInputFiles,
|
||||
std::unique_ptr<CommandOutput> output,
|
||||
const OutputInfo &OI) const;
|
||||
|
||||
/// Return the default language type to use for the given extension.
|
||||
|
||||
@@ -88,6 +88,8 @@ def driver_use_frontend_path : Separate<["-"], "driver-use-frontend-path">,
|
||||
def driver_show_incremental : Flag<["-"], "driver-show-incremental">,
|
||||
InternalDebugOpt,
|
||||
HelpText<"With -v, dump information about why files are being rebuilt">;
|
||||
def driver_use_filelists : Flag<["-"], "driver-use-filelists">,
|
||||
InternalDebugOpt, HelpText<"Pass input files as filelists whenever possible">;
|
||||
|
||||
def driver_always_rebuild_dependents :
|
||||
Flag<["-"], "driver-always-rebuild-dependents">, InternalDebugOpt,
|
||||
|
||||
@@ -618,3 +618,23 @@ int Compilation::performJobs() {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string &Compilation::getAllSourcesPath() const {
|
||||
auto *mutableThis = const_cast<Compilation *>(this);
|
||||
|
||||
if (AllSourceFilesPath.empty()) {
|
||||
SmallString<128> Buffer;
|
||||
std::error_code EC =
|
||||
llvm::sys::fs::createTemporaryFile("sources", "", Buffer);
|
||||
if (EC) {
|
||||
Diags.diagnose(SourceLoc(),
|
||||
diag::error_unable_to_make_temporary_file,
|
||||
EC.message());
|
||||
// FIXME: This should not take down the entire process.
|
||||
llvm::report_fatal_error("unable to create list of input sources");
|
||||
}
|
||||
mutableThis->addTemporaryFile(Buffer.str());
|
||||
mutableThis->AllSourceFilesPath = TempFilePaths.back();
|
||||
}
|
||||
return AllSourceFilesPath;
|
||||
}
|
||||
|
||||
@@ -1855,10 +1855,9 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
|
||||
}
|
||||
|
||||
// 4. Construct a Job which produces the right CommandOutput.
|
||||
std::unique_ptr<Job> ownedJob = TC.constructJob(*JA, std::move(InputJobs),
|
||||
std::move(Output),
|
||||
InputActions, C.getArgs(),
|
||||
C.getInputFiles(), OI);
|
||||
std::unique_ptr<Job> ownedJob = TC.constructJob(*JA, C, std::move(InputJobs),
|
||||
InputActions,
|
||||
std::move(Output), OI);
|
||||
Job *J = C.addJob(std::move(ownedJob));
|
||||
|
||||
// If we track dependencies for this job, we may be able to avoid running it.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Driver/ToolChain.h"
|
||||
|
||||
#include "swift/Driver/Compilation.h"
|
||||
#include "swift/Driver/Driver.h"
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
@@ -33,16 +33,29 @@ using namespace llvm::opt;
|
||||
|
||||
const char * const ToolChain::SWIFT_EXECUTABLE_NAME;
|
||||
|
||||
ToolChain::JobContext::JobContext(const Compilation &C,
|
||||
ArrayRef<const Job *> Inputs,
|
||||
ArrayRef<const Action *> InputActions,
|
||||
const CommandOutput &Output,
|
||||
const OutputInfo &OI)
|
||||
: C(C), Inputs(Inputs), InputActions(InputActions), Output(Output),
|
||||
OI(OI), Args(C.getArgs()) {}
|
||||
|
||||
ArrayRef<InputPair> ToolChain::JobContext::getTopLevelInputFiles() const {
|
||||
return C.getInputFiles();
|
||||
}
|
||||
const std::string &ToolChain::JobContext::getAllSourcesPath() const {
|
||||
return C.getAllSourcesPath();
|
||||
}
|
||||
|
||||
std::unique_ptr<Job>
|
||||
ToolChain::constructJob(const JobAction &JA,
|
||||
const Compilation &C,
|
||||
SmallVectorImpl<const Job *> &&inputs,
|
||||
std::unique_ptr<CommandOutput> output,
|
||||
const ActionList &inputActions,
|
||||
const llvm::opt::ArgList &args,
|
||||
ArrayRef<InputPair> topLevelInputFiles,
|
||||
std::unique_ptr<CommandOutput> output,
|
||||
const OutputInfo &OI) const {
|
||||
JobContext context{inputs, *output, inputActions, args, topLevelInputFiles,
|
||||
OI};
|
||||
JobContext context{C, inputs, inputActions, *output, OI};
|
||||
|
||||
auto invocationInfo = [&]() -> InvocationInfo {
|
||||
switch (JA.getKind()) {
|
||||
@@ -71,12 +84,12 @@ ToolChain::constructJob(const JobAction &JA,
|
||||
std::string relativePath =
|
||||
findProgramRelativeToSwift(invocationInfo.ExecutableName);
|
||||
if (!relativePath.empty()) {
|
||||
executablePath = args.MakeArgString(relativePath);
|
||||
executablePath = C.getArgs().MakeArgString(relativePath);
|
||||
} else {
|
||||
auto systemPath =
|
||||
llvm::sys::findProgramByName(invocationInfo.ExecutableName);
|
||||
if (systemPath) {
|
||||
executablePath = args.MakeArgString(systemPath.get());
|
||||
executablePath = C.getArgs().MakeArgString(systemPath.get());
|
||||
} else {
|
||||
// For debugging purposes.
|
||||
executablePath = invocationInfo.ExecutableName;
|
||||
|
||||
@@ -39,6 +39,8 @@ using namespace llvm::opt;
|
||||
|
||||
/// The name of the Swift migrator binary.
|
||||
static const char * const SWIFT_UPDATE_NAME = "swift-update";
|
||||
/// The limit for passing a list of files on the command line.
|
||||
static const size_t TOO_MANY_FILES = 128;
|
||||
|
||||
static void addInputsOfType(ArgStringList &Arguments,
|
||||
ArrayRef<const Action *> Inputs,
|
||||
@@ -242,9 +244,16 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
|
||||
auto *IA = cast<InputAction>(context.InputActions[0]);
|
||||
const Arg &PrimaryInputArg = IA->getInputArg();
|
||||
bool FoundPrimaryInput = false;
|
||||
|
||||
for (auto inputPair : context.TopLevelInputFiles) {
|
||||
if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.getTopLevelInputFiles().size() > TOO_MANY_FILES) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(context.getAllSourcesPath().c_str());
|
||||
Arguments.push_back("-primary-file");
|
||||
PrimaryInputArg.render(context.Args, Arguments);
|
||||
} else {
|
||||
bool FoundPrimaryInput = false;
|
||||
for (auto inputPair : context.getTopLevelInputFiles()) {
|
||||
if (!types::isPartOfSwiftCompilation(inputPair.first))
|
||||
continue;
|
||||
|
||||
@@ -256,12 +265,19 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
}
|
||||
Arguments.push_back(inputPair.second->getValue());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OutputInfo::Mode::SingleCompile: {
|
||||
if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.InputActions.size() > TOO_MANY_FILES) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(context.getAllSourcesPath().c_str());
|
||||
} else {
|
||||
for (const Action *A : context.InputActions) {
|
||||
cast<InputAction>(A)->getInputArg().render(context.Args, Arguments);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
// RUN: cp %s %t
|
||||
// RUN: not %swiftc_driver -driver-print-jobs -c -target x86_64-apple-macosx10.9 %s %t/driver-compile.swift 2>&1 | FileCheck -check-prefix DUPLICATE-NAME %s
|
||||
|
||||
// RUN: %swiftc_driver -driver-print-jobs -c -target x86_64-apple-macosx10.9 %s %S/../Inputs/empty.swift -module-name main -driver-use-filelists 2>&1 | FileCheck -check-prefix=FILELIST %s
|
||||
|
||||
// RUN: rm -rf %t && mkdir -p %t/DISTINCTIVE-PATH/usr/bin/
|
||||
// RUN: ln %swift_driver_plain %t/DISTINCTIVE-PATH/usr/bin/swiftc
|
||||
// RUN: ln -s "swiftc" %t/DISTINCTIVE-PATH/usr/bin/swift-update
|
||||
@@ -102,6 +104,13 @@
|
||||
// DUPLICATE-NAME: error: filename "driver-compile.swift" used twice: '{{.*}}test/Driver/driver-compile.swift' and '{{.*}}driver-compile.swift'
|
||||
// DUPLICATE-NAME: note: filenames are used to distinguish private declarations with the same name
|
||||
|
||||
// FILELIST: bin/swift
|
||||
// FILELIST: -filelist [[SOURCES:["]?[^ ]+sources[^ ]*["]?]]
|
||||
// FILELIST: -primary-file {{.*/(driver-compile.swift|empty.swift)}}
|
||||
// FILELIST-NEXT: bin/swift
|
||||
// FILELIST: -filelist [[SOURCES]]
|
||||
// FILELIST: -primary-file {{.*/(driver-compile.swift|empty.swift)}}
|
||||
|
||||
// UPDATE-CODE: DISTINCTIVE-PATH/usr/bin/swift-update
|
||||
// UPDATE-CODE: -c{{ }}
|
||||
// UPDATE-CODE: -o {{.+}}.remap
|
||||
|
||||
Reference in New Issue
Block a user