This patch introduces the new -fdriver-only flag which instructs Clang to only execute the driver logic without running individual jobs. In a way, this is very similar to -###, with the following differences:
* it doesn't automatically print all jobs,
* it doesn't avoid side effects (e.g. it will generate compilation database when -MJ is specified).
This flag will be useful in testing D121997.
Reviewed By: dexonsmith, egorzhdan
Differential Revision: https://reviews.llvm.org/D127408
///
/// \param FailingCommand - For non-zero results, this will be set to the
/// Command which failed, if any.
+ /// \param LogOnly - When true, only tries to log the command, not actually
+ /// execute it.
/// \return The result code of the subprocess.
- int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
+ int ExecuteCommand(const Command &C, const Command *&FailingCommand,
+ bool LogOnly = false) const;
/// ExecuteJob - Execute a single job.
///
/// \param FailingCommands - For non-zero results, this will be a vector of
/// failing commands and their associated result code.
- void ExecuteJobs(
- const JobList &Jobs,
- SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const;
+ /// \param LogOnly - When true, only tries to log the command, not actually
+ /// execute it.
+ void
+ ExecuteJobs(const JobList &Jobs,
+ SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands,
+ bool LogOnly = false) const;
/// initCompilationForDiagnostics - Remove stale state and suppress output
/// so compilation can be reexecuted to generate additional diagnostic
" overwriting polymorphic C++ objects">,
NegFlag<SetFalse>>;
def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>;
+def fdriver_only : Flag<["-"], "fdriver-only">, Flags<[NoXarchOption, CoreOption]>,
+ Group<Action_Group>, HelpText<"Only run the driver.">;
def fsyntax_only : Flag<["-"], "fsyntax-only">,
Flags<[NoXarchOption,CoreOption,CC1Option,FC1Option]>, Group<Action_Group>;
def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group<f_Group>;
}
int Compilation::ExecuteCommand(const Command &C,
- const Command *&FailingCommand) const {
+ const Command *&FailingCommand,
+ bool LogOnly) const {
if ((getDriver().CCPrintOptions ||
getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
raw_ostream *OS = &llvm::errs();
C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
}
+ if (LogOnly)
+ return 0;
+
std::string Error;
bool ExecutionFailed;
int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
}
void Compilation::ExecuteJobs(const JobList &Jobs,
- FailingCommandList &FailingCommands) const {
+ FailingCommandList &FailingCommands,
+ bool LogOnly) const {
// According to UNIX standard, driver need to continue compiling all the
// inputs on the command line even one of them failed.
// In all but CLMode, execute all the jobs unless the necessary inputs for the
if (!InputsOk(Job, FailingCommands))
continue;
const Command *FailingCommand = nullptr;
- if (int Res = ExecuteCommand(Job, FailingCommand)) {
+ if (int Res = ExecuteCommand(Job, FailingCommand, LogOnly)) {
FailingCommands.push_back(std::make_pair(Res, FailingCommand));
// Bail as soon as one command fails in cl driver mode.
if (TheDriver.IsCLMode())
int Driver::ExecuteCompilation(
Compilation &C,
SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {
+ if (C.getArgs().hasArg(options::OPT_fdriver_only)) {
+ if (C.getArgs().hasArg(options::OPT_v))
+ C.getJobs().Print(llvm::errs(), "\n", true);
+
+ C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true);
+
+ // If there were errors building the compilation, quit now.
+ if (!FailingCommands.empty() || Diags.hasErrorOccurred())
+ return 1;
+
+ return 0;
+ }
+
// Just print if -### was present.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
C.getJobs().Print(llvm::errs(), "\n", true);
C.getArgs().hasArg(options::OPT_Qunused_arguments))
return;
+ // Claim -fdriver-only here.
+ (void)C.getArgs().hasArg(options::OPT_fdriver_only);
// Claim -### here.
(void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
if (!C)
return nullptr;
+ if (C->getArgs().hasArg(driver::options::OPT_fdriver_only))
+ return nullptr;
+
// Just print the cc1 options if -### was present.
if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {
C->getJobs().Print(llvm::errs(), "\n", true);
+// RUN: rm -f %t.log
// RUN: env CC_PRINT_OPTIONS=1 \
// RUN: CC_PRINT_OPTIONS_FILE=%t.log \
// RUN: %clang -S -o %t.s %s
// RUN: FileCheck %s < %t.log
-// CHECK: [Logging clang options]
-// CHECK: {{.*}} "-S"
+// RUN: rm -f %t.log
+// RUN: env CC_PRINT_OPTIONS=1 \
+// RUN: CC_PRINT_OPTIONS_FILE=%t.log \
+// RUN: %clang -fdriver-only -o %t.s %s
+// RUN: FileCheck %s < %t.log
+// CHECK: [Logging clang options]
+// CHECK: {{.*}} "-cc1"
--- /dev/null
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// Check that -fdriver-only doesn't actually run the generated -cc1 job.
+//
+// RUN: %clang -c %s -o %t/a.o -fdriver-only
+// RUN: not cat %t/a.o
+
+// Check that -fdriver-only respects errors.
+//
+// RUN: not %clang -c %s -fdriver-only -target i386-apple-darwin9 -m32 -Xarch_i386 -o
+
+// Check that -fdriver-only respects -v.
+//
+// RUN: %clang -c %s -fdriver-only -v 2>&1 | FileCheck %s --check-prefix=CHECK-V
+// CHECK-V: {{.*}} "-cc1"
+//
+// RUN: %clang -c %s -fdriver-only 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V --allow-empty
+// CHECK-NO-V-NOT: {{.*}} "-cc1"