[clang][driver] Introduce new -fdriver-only flag

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
This commit is contained in:
Jan Svoboda 2022-06-09 16:58:09 +02:00
parent 84b9ae6624
commit c12577c61d
7 changed files with 65 additions and 9 deletions

View File

@ -295,16 +295,22 @@ public:
///
/// \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

View File

@ -2751,6 +2751,8 @@ defm strict_vtable_pointers : BoolFOption<"strict-vtable-pointers",
" 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>;

View File

@ -162,7 +162,8 @@ bool Compilation::CleanupFileMap(const ArgStringMap &Files,
}
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();
@ -191,6 +192,9 @@ int Compilation::ExecuteCommand(const Command &C,
C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
}
if (LogOnly)
return 0;
std::string Error;
bool ExecutionFailed;
int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
@ -237,7 +241,8 @@ static bool InputsOk(const Command &C,
}
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
@ -246,7 +251,7 @@ void Compilation::ExecuteJobs(const JobList &Jobs,
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())

View File

@ -1689,6 +1689,19 @@ void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
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);
@ -4761,6 +4774,8 @@ void Driver::BuildJobs(Compilation &C) const {
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);

View File

@ -54,6 +54,9 @@ clang::createInvocation(ArrayRef<const char *> ArgList,
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);

View File

@ -1,8 +1,14 @@
// 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"

View File

@ -0,0 +1,19 @@
// 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"