]> granicus.if.org Git - clang/commitdiff
PR 17421: Implemented -save-temps={obj|cwd} option
authorReid Kleckner <reid@kleckner.net>
Mon, 2 Feb 2015 22:41:48 +0000 (22:41 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 2 Feb 2015 22:41:48 +0000 (22:41 +0000)
-save-temps=cwd is equivalent to -save-temps
-save-temps=obj saves temporary file in the same directory as output

This helps to avoid clobbering of temp files in case of parallel
compilation with -save-temps of the files that have the same name
but located in different directories.

Patch by Artem Belevich

Reviewed By: rnk

Differential Revision: http://reviews.llvm.org/D7304

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227886 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/Driver.h
include/clang/Driver/Options.td
lib/Driver/Driver.cpp
lib/Driver/Tools.cpp
test/Driver/save-temps.c

index 67d67c3074d740098024007939cdabd9efa6e539..18186fd4d523ff383e8003a94cec4669b7a38519 100644 (file)
@@ -61,6 +61,12 @@ class Driver {
     CLMode
   } Mode;
 
+  enum SaveTempsMode {
+    SaveTempsNone,
+    SaveTempsCwd,
+    SaveTempsObj
+  } SaveTemps;
+
 public:
   // Diag - Forwarding function for diagnostics.
   DiagnosticBuilder Diag(unsigned DiagID) const {
@@ -232,6 +238,9 @@ public:
     InstalledDir = Value;
   }
 
+  bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
+  bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; }
+
   /// @}
   /// @name Primary Functionality
   /// @{
index 3d1b5bf68be6bfbb87bc2fb2bb84484a6fdc01ef..e1271072dd40c01416d740661f1372c9fe7f4ed1 100644 (file)
@@ -1454,7 +1454,10 @@ def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption]>,
 def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>;
 def rtlib_EQ : Joined<["-", "--"], "rtlib=">;
 def r : Flag<["-"], "r">;
+def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
+  HelpText<"Save intermediate compilation results.">;
 def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
+  Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
   HelpText<"Save intermediate compilation results">;
 def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt,
   HelpText<"Write assembly to file for input to assemble jobs">;
index 1664d0d49d46960482943f13c3d9c08b3a589dcf..0424c4b2653ec67af904b7b5349264c206e276a9 100644 (file)
@@ -44,19 +44,17 @@ using namespace clang::driver;
 using namespace clang;
 using namespace llvm::opt;
 
-Driver::Driver(StringRef ClangExecutable,
-               StringRef DefaultTargetTriple,
+Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
                DiagnosticsEngine &Diags)
-  : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
-    ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
-    UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
-    DriverTitle("clang LLVM compiler"),
-    CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
-    CCLogDiagnosticsFilename(nullptr),
-    CCCPrintBindings(false),
-    CCPrintHeaders(false), CCLogDiagnostics(false),
-    CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
-    CCCUsePCH(true), SuppressMissingInputWarning(false) {
+    : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
+      SaveTemps(SaveTempsNone), ClangExecutable(ClangExecutable),
+      SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
+      DefaultTargetTriple(DefaultTargetTriple),
+      DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
+      CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
+      CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+      CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
+      CCCUsePCH(true), SuppressMissingInputWarning(false) {
 
   Name = llvm::sys::path::stem(ClangExecutable);
   Dir  = llvm::sys::path::parent_path(ClangExecutable);
@@ -364,6 +362,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
   if (const Arg *A = Args->getLastArg(options::OPT_resource_dir))
     ResourceDir = A->getValue();
 
+  if (const Arg *A = Args->getLastArg(options::OPT_save_temps_EQ)) {
+    SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())
+                    .Case("cwd", SaveTempsCwd)
+                    .Case("obj", SaveTempsObj)
+                    .Default(SaveTempsCwd);
+  }
+
   // Perform the default argument translations.
   DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
 
@@ -504,7 +509,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
 
   // If any of the preprocessing commands failed, clean up and exit.
   if (!FailingCommands.empty()) {
-    if (!C.getArgs().hasArg(options::OPT_save_temps))
+    if (!isSaveTempsEnabled())
       C.CleanupFileList(C.getTempFiles(), true);
 
     Diag(clang::diag::note_drv_command_failed_diag_msg)
@@ -612,7 +617,7 @@ int Driver::ExecuteCompilation(Compilation &C,
     const Command *FailingCommand = it->second;
 
     // Remove result files if we're not saving temps.
-    if (!C.getArgs().hasArg(options::OPT_save_temps)) {
+    if (!isSaveTempsEnabled()) {
       const JobAction *JA = cast<JobAction>(&FailingCommand->getSource());
       C.CleanupFileMap(C.getResultFiles(), JA, true);
 
@@ -1471,8 +1476,8 @@ void Driver::BuildJobs(Compilation &C) const {
   }
 }
 
-static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
-                                    const JobAction *JA,
+static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
+                                    const ToolChain *TC, const JobAction *JA,
                                     const ActionList *&Inputs) {
   const Tool *ToolForJob = nullptr;
 
@@ -1481,7 +1486,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
   // compiler input.
 
   if (TC->useIntegratedAs() &&
-      !C.getArgs().hasArg(options::OPT_save_temps) &&
+      !SaveTemps &&
       !C.getArgs().hasArg(options::OPT_via_file_asm) &&
       !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
       !C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
@@ -1512,8 +1517,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
     const Tool *Compiler = TC->SelectTool(*CompileJA);
     if (!Compiler)
       return nullptr;
-    if (!Compiler->canEmitIR() ||
-        !C.getArgs().hasArg(options::OPT_save_temps)) {
+    if (!Compiler->canEmitIR() || !SaveTemps) {
       Inputs = &(*Inputs)[0]->getInputs();
       ToolForJob = Compiler;
     }
@@ -1529,7 +1533,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
   if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) &&
       !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
       !C.getArgs().hasArg(options::OPT_traditional_cpp) &&
-      !C.getArgs().hasArg(options::OPT_save_temps) &&
+      !SaveTemps &&
       !C.getArgs().hasArg(options::OPT_rewrite_objc) &&
       ToolForJob->hasIntegratedCPP())
     Inputs = &(*Inputs)[0]->getInputs();
@@ -1577,7 +1581,7 @@ void Driver::BuildJobsForAction(Compilation &C,
   const ActionList *Inputs = &A->getInputs();
 
   const JobAction *JA = cast<JobAction>(A);
-  const Tool *T = SelectToolForJob(C, TC, JA, Inputs);
+  const Tool *T = SelectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs);
   if (!T)
     return;
 
@@ -1708,7 +1712,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
   }
 
   // Output to a temporary file?
-  if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
+  if ((!AtTopLevel && !isSaveTempsEnabled() &&
         !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
       CCGenDiagnostics) {
     StringRef Name = llvm::sys::path::filename(BaseInput);
@@ -1780,11 +1784,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
     NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
   }
 
+  // Prepend object file path if -save-temps=obj
+  if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) &&
+      JA.getType() != types::TY_PCH) {
+    Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
+    SmallString<128> TempPath(FinalOutput->getValue());
+    llvm::sys::path::remove_filename(TempPath);
+    StringRef OutputFileName = llvm::sys::path::filename(NamedOutput);
+    llvm::sys::path::append(TempPath, OutputFileName);
+    NamedOutput = C.getArgs().MakeArgString(TempPath.c_str());
+  }
+
   // If we're saving temps and the temp file conflicts with the input file,
   // then avoid overwriting input file.
-  if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) &&
-      NamedOutput == BaseName) {
-
+  if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) {
     bool SameFile = false;
     SmallString<256> Result;
     llvm::sys::fs::current_path(Result);
index 35e3691ec2672abac499f8458600c869093a36f8..9c89c5214984a6a3570ac48ab95be13118ea1516 100644 (file)
@@ -4495,7 +4495,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // With -save-temps, we want to save the unoptimized bitcode output from the
   // CompileJobAction, so disable optimizations if they are not already
   // disabled.
-  if (Args.hasArg(options::OPT_save_temps) && !OptDisabled &&
+  if (C.getDriver().isSaveTempsEnabled() && !OptDisabled &&
       isa<CompileJobAction>(JA))
     CmdArgs.push_back("-disable-llvm-optzns");
 
index a157aeaaff4acf710a4b64020a9f23fc59921b42..438d748932b8f958314097ef3a3d6fa15b69f719 100644 (file)
@@ -5,7 +5,18 @@
 // CHECK: "-o" "save-temps.bc"
 // CHECK: "-o" "save-temps.s"
 // CHECK: "-o" "save-temps.o"
-// CHECK: "-o" "a.out" 
+// CHECK: "-o" "a.out"
+
+// Check -save-temps=cwd which should work the same as -save-temps above
+//
+// RUN: %clang -target x86_64-apple-darwin -save-temps=cwd -arch x86_64 %s -### 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CWD
+// CWD: "-o" "save-temps.i"
+// CWD: "-disable-llvm-optzns"
+// CWD: "-o" "save-temps.bc"
+// CWD: "-o" "save-temps.s"
+// CWD: "-o" "save-temps.o"
+// CWD: "-o" "a.out"
 
 // Check for a single clang cc1 invocation when NOT using -save-temps.
 // RUN: %clang -target x86_64-apple-darwin -arch x86_64 -S %s -### 2>&1 \
 // MULT-ARCH: "-o" "save-temps-i386.bc"
 // MULT-ARCH: "-o" "save-temps-i386.s"
 // MULT-ARCH: "-o" "save-temps-i386.o"
-// MULT-ARCH: "-o" "a.out-i386" 
+// MULT-ARCH: "-o" "a.out-i386"
 // MULT-ARCH: "-o" "save-temps-x86_64.i"
 // MULT-ARCH: "-o" "save-temps-x86_64.bc"
 // MULT-ARCH: "-o" "save-temps-x86_64.s"
 // MULT-ARCH: "-o" "save-temps-x86_64.o"
-// MULT-ARCH: "-o" "a.out-x86_64" 
+// MULT-ARCH: "-o" "a.out-x86_64"
 // MULT-ARCH: lipo
 // MULT-ARCH: "-create" "-output" "a.out" "a.out-i386" "a.out-x86_64"
+
+// RUN: %clang -target x86_64-apple-darwin -save-temps=cwd -arch i386 -arch x86_64 %s -### 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=MULT-ARCH-CWD
+// MULT-ARCH-CWD: "-o" "save-temps-i386.i"
+// MULT-ARCH-CWD: "-o" "save-temps-i386.bc"
+// MULT-ARCH-CWD: "-o" "save-temps-i386.s"
+// MULT-ARCH-CWD: "-o" "save-temps-i386.o"
+// MULT-ARCH-CWD: "-o" "a.out-i386"
+// MULT-ARCH-CWD: "-o" "save-temps-x86_64.i"
+// MULT-ARCH-CWD: "-o" "save-temps-x86_64.bc"
+// MULT-ARCH-CWD: "-o" "save-temps-x86_64.s"
+// MULT-ARCH-CWD: "-o" "save-temps-x86_64.o"
+// MULT-ARCH-CWD: "-o" "a.out-x86_64"
+// MULT-ARCH-CWD: lipo
+// MULT-ARCH-CWD: "-create" "-output" "a.out" "a.out-i386" "a.out-x86_64"
+
+// Check that temp files are saved in the same directory as the output file
+// regardless of whether -o is specified.
+//
+// RUN: %clang -target x86_64-apple-darwin -save-temps=obj -o obj/dir/a.out -arch x86_64 %s -### 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK-OBJ
+// CHECK-OBJ: "-o" "obj/dir{{/|\\\\}}save-temps.i"
+// CHECK-OBJ: "-disable-llvm-optzns"
+// CHECK-OBJ: "-o" "obj/dir{{/|\\\\}}save-temps.bc"
+// CHECK-OBJ: "-o" "obj/dir{{/|\\\\}}save-temps.s"
+// CHECK-OBJ: "-o" "obj/dir{{/|\\\\}}save-temps.o"
+// CHECK-OBJ: "-o" "obj/dir{{/|\\\\}}a.out"
+//
+// RUN: %clang -target x86_64-apple-darwin -save-temps=obj -arch x86_64 %s -### 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK-OBJ-NOO
+// CHECK-OBJ-NOO: "-o" "save-temps.i"
+// CHECK-OBJ-NOO: "-disable-llvm-optzns"
+// CHECK-OBJ-NOO: "-o" "save-temps.bc"
+// CHECK-OBJ-NOO: "-o" "save-temps.s"
+// CHECK-OBJ-NOO: "-o" "save-temps.o"
+// CHECK-OBJ-NOO: "-o" "a.out"