mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When generating a compiler invocation in driver::createCompilerInvocation() we end up using filelists if the number of inputs is > 128 (to work around command line arg limits). We never actually write them out though, and so fail when parsing the frontend arguments that reference them. As this function is called frequently by SourceKit and command line limits aren't a concern here, this patch makes the 128 threshold value configurable via a new -driver-filelist-threshold option. This is set to its maximum value in driver::createCompilerInvocation() to ensure filelists aren't used. This new option makes the existing -driver-use-filelists (that forces filelists to be used) redundant as it's now equivalent to -driver-filelist-threshold=0. Resolves rdar://problem/38231888
91 lines
3.3 KiB
C++
91 lines
3.3 KiB
C++
//===--- FrontendUtil.cpp - Driver Utilities for Frontend -----------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/Driver/FrontendUtil.h"
|
|
|
|
#include "swift/AST/DiagnosticsDriver.h"
|
|
#include "swift/Driver/Action.h"
|
|
#include "swift/Driver/Compilation.h"
|
|
#include "swift/Driver/Driver.h"
|
|
#include "swift/Driver/Job.h"
|
|
#include "swift/Driver/ToolChain.h"
|
|
#include "swift/Frontend/Frontend.h"
|
|
|
|
using namespace swift;
|
|
using namespace swift::driver;
|
|
|
|
std::unique_ptr<CompilerInvocation>
|
|
swift::driver::createCompilerInvocation(ArrayRef<const char *> Argv,
|
|
DiagnosticEngine &Diags) {
|
|
SmallVector<const char *, 16> Args;
|
|
Args.push_back("<swiftc>"); // FIXME: Remove dummy argument.
|
|
Args.insert(Args.end(), Argv.begin(), Argv.end());
|
|
|
|
// When creating a CompilerInvocation, ensure that the driver creates a single
|
|
// frontend command.
|
|
Args.push_back("-force-single-frontend-invocation");
|
|
|
|
// Avoid using filelists
|
|
std::string neverThreshold =
|
|
std::to_string(Compilation::NEVER_USE_FILELIST);
|
|
Args.push_back("-driver-filelist-threshold");
|
|
Args.push_back(neverThreshold.c_str());
|
|
|
|
// Force the driver into batch mode by specifying "swiftc" as the name.
|
|
Driver TheDriver("swiftc", "swiftc", Args, Diags);
|
|
|
|
// Don't check for the existence of input files, since the user of the
|
|
// CompilerInvocation may wish to remap inputs to source buffers.
|
|
TheDriver.setCheckInputFilesExist(false);
|
|
|
|
std::unique_ptr<llvm::opt::InputArgList> ArgList =
|
|
TheDriver.parseArgStrings(ArrayRef<const char *>(Args).slice(1));
|
|
if (Diags.hadAnyError())
|
|
return nullptr;
|
|
|
|
std::unique_ptr<ToolChain> TC = TheDriver.buildToolChain(*ArgList);
|
|
if (Diags.hadAnyError())
|
|
return nullptr;
|
|
|
|
std::unique_ptr<Compilation> C =
|
|
TheDriver.buildCompilation(*TC, std::move(ArgList));
|
|
if (!C || C->getJobs().empty())
|
|
return nullptr; // Don't emit an error; one should already have been emitted
|
|
|
|
SmallPtrSet<const Job *, 4> CompileCommands;
|
|
for (const Job *Cmd : C->getJobs())
|
|
if (isa<CompileJobAction>(Cmd->getSource()))
|
|
CompileCommands.insert(Cmd);
|
|
|
|
if (CompileCommands.size() != 1) {
|
|
// TODO: include Jobs in the diagnostic.
|
|
Diags.diagnose(SourceLoc(), diag::error_expected_one_frontend_job);
|
|
return nullptr;
|
|
}
|
|
|
|
const Job *Cmd = *CompileCommands.begin();
|
|
if (StringRef("-frontend") != Cmd->getArguments().front()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_expected_frontend_command);
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CompilerInvocation> Invocation(new CompilerInvocation());
|
|
const llvm::opt::ArgStringList &BaseFrontendArgs = Cmd->getArguments();
|
|
ArrayRef<const char *> FrontendArgs =
|
|
llvm::makeArrayRef(BaseFrontendArgs.data() + 1,
|
|
BaseFrontendArgs.data() + BaseFrontendArgs.size());
|
|
if (Invocation->parseArgs(FrontendArgs, Diags))
|
|
return nullptr; // Don't emit an error; one should already have been emitted
|
|
|
|
return Invocation;
|
|
}
|