Make getLinkerFileListName more similar to getDependencyFileName. Add an
assertion. Tweak some variable names as per review comments.
http://reviews.llvm.org/D4104
Files:
include/clang/Basic/DiagnosticDriverKinds.td
include/clang/Driver/Options.td
lib/Driver/Tools.cpp
lib/Driver/Tools.h
test/Driver/Inputs/filelist/a.o
test/Driver/Inputs/filelist/a.obj
test/Driver/Inputs/filelist/b.o
test/Driver/Inputs/filelist/c.a
test/Driver/filelist.c
Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -39,6 +39,7 @@
"cannot specify '%0%1' when compiling multiple source files">;
def err_no_external_assembler : Error<
"there is no external assembler that can be used on this platform">;
+def err_drv_unable_to_open_file : Error< "unable to open file: %0">;
def err_drv_unable_to_remove_file : Error<
"unable to remove file: %0">;
def err_drv_command_failure : Error<
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1384,6 +1384,8 @@
def : Flag<["-"], "no-integrated-as">, Alias<fno_integrated_as>,
Flags<[CC1Option, DriverOption]>;
+def fuse_linker_response_files : Joined<["-"], "fuse-linker-response-files">;
+
def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>,
HelpText<"Resolve file paths relative to the specified directory">;
def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>,
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -39,6 +39,7 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <sys/stat.h>
+#include <fstream>
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -168,11 +169,17 @@
}
}
-static void AddLinkerInputs(const ToolChain &TC,
+static void AddLinkerInputs(Compilation &C, const ToolChain &TC,
const InputInfoList &Inputs, const ArgList &Args,
ArgStringList &CmdArgs) {
+ const bool UseLinkerResponseFiles =
+ Args.hasArg(options::OPT_fuse_linker_response_files);
const Driver &D = TC.getDriver();
+ const char *CurrentFileListName;
+ std::ofstream CurrentFileList;
+ unsigned FileListSequence = 0;
+
// Add extra linker input arguments which are not treated as inputs
// (constructed via -Xarch_).
Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
@@ -190,10 +197,35 @@
// Add filenames immediately.
if (II.isFilename()) {
- CmdArgs.push_back(II.getFilename());
+ if (UseLinkerResponseFiles && II.getType() == types::TY_Object) {
+ if (!CurrentFileList.is_open()) {
+ CurrentFileListName =
+ Clang::getLinkerFileListName(Args, Inputs, FileListSequence++);
+
+ // Skip the leading '@'
+ assert(CurrentFileListName[0] == '@' && "expected '@' prefixed name");
+ CurrentFileList.open(&CurrentFileListName[1],
+ std::ios_base::trunc | std::ios_base::out);
+ if (!CurrentFileList.is_open())
+ D.Diag(diag::err_drv_unable_to_open_file) << CurrentFileListName;
+ C.addTempFile(CurrentFileListName);
+ }
+ CurrentFileList << II.getFilename() << std::endl;
+ } else {
+ if (CurrentFileList.is_open()) {
+ CurrentFileList.close();
+ CmdArgs.push_back(CurrentFileListName);
+ }
+ CmdArgs.push_back(II.getFilename());
+ }
continue;
}
+ if (CurrentFileList.is_open()) {
+ CurrentFileList.close();
+ CmdArgs.push_back(CurrentFileListName);
+ }
+
// Otherwise, this is a linker input argument.
const Arg &A = II.getInputArg();
@@ -206,6 +238,13 @@
A.renderAsInput(Args, CmdArgs);
}
+ // NOTE this is needed here to handle the case where an object file is the
+ // last argument; otherwise, we don't properly close the file list.
+ if (CurrentFileList.is_open()) {
+ CurrentFileList.close();
+ CmdArgs.push_back(CurrentFileListName);
+ }
+
// LIBRARY_PATH - included following the user specified library paths.
// and only supported on native toolchains.
if (!TC.isCrossCompiling())
@@ -4886,7 +4925,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_t);
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs);
//----------------------------------------------------------------------------
// Libraries
@@ -5153,6 +5192,26 @@
return Args.MakeArgString(Res + ".d");
}
+const char *Clang::getLinkerFileListName(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs,
+ unsigned SequenceNumber) {
+ std::string Buffer;
+ llvm::raw_string_ostream Name(Buffer);
+
+ // Add the prefix so as to ensure that it is made part of the argument string
+ Name << "@";
+
+ if (Arg *Output = Args.getLastArg(options::OPT_o)) {
+ StringRef Value = Output->getValue();
+ Name << Value.substr(0, Value.rfind('.'));
+ } else {
+ Name << getBaseInputStem(Args, Inputs);
+ }
+
+ Name << SequenceNumber << ".rsp";
+ return Args.MakeArgString(Name.str());
+}
+
void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -5503,7 +5562,7 @@
break;
}
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
if (isObjCRuntimeLinked(Args) &&
!Args.hasArg(options::OPT_nostdlib) &&
@@ -5545,8 +5604,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_F);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5713,7 +5771,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_e);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -5735,8 +5793,7 @@
addProfileRT(getToolChain(), Args, CmdArgs);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5819,7 +5876,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6001,7 +6058,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6127,7 +6184,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6376,7 +6433,7 @@
if (D.IsUsingLTO(Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6638,7 +6695,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
unsigned Major, Minor, Micro;
getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
@@ -7100,7 +7157,7 @@
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs);
addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
// The profile runtime also needs access to system libraries.
@@ -7229,7 +7286,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
addProfileRT(getToolChain(), Args, CmdArgs);
@@ -7357,7 +7414,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -7693,7 +7750,7 @@
if (EH.ShouldUseExceptionTables)
CmdArgs.push_back("-fexceptions");
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -40,6 +40,9 @@
const InputInfoList &Inputs);
static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
const InputInfoList &Inputs);
+ static const char *getLinkerFileListName(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs,
+ unsigned SequenceNumber);
private:
void AddPreprocessingOptions(Compilation &C, const JobAction &JA,
Index: test/Driver/filelist.c
===================================================================
--- /dev/null
+++ test/Driver/filelist.c
@@ -0,0 +1,54 @@
+// Test handling of -fuse-linker-response-files
+
+// RUN: %clang -### %S/Inputs/filelist/a.o -o test 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-FILELIST
+
+// CHECK-NO-FILELIST-NOT: "@test0.rsp"
+// CHECK-NO-FILELIST: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+
+// RUN: %clang -### -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.o -o test 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-FILELIST
+// RUN: FileCheck -check-prefix CHECK-FILELIST-0 %s < test0.rsp
+
+// CHECK-FILELIST-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+// CHECK-FILELIST: "@test0.rsp"
+
+// CHECK-FILELIST-0: {{.*}}/test/Driver/Inputs/filelist/a.o
+
+// RUN: %clang -### -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.o -library %S/Inputs/filelist/b.o -o test 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-FILELIST-SPLIT
+// RUN: FileCheck -check-prefix CHECK-FILELIST-SPLIT-0 %s < test0.rsp
+// RUN: FileCheck -check-prefix CHECK-FILELIST-SPLIT-1 %s < test1.rsp
+
+// CHECK-FILELIST-SPLIT-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+// CHECK-FILELIST-SPLIT: @test0.rsp
+// CHECK-FILELIST-SPLIT: -library
+// CHECK-FILELIST-SPLIT-NOT: "{{.*}}/test/Driver/Inputs/filelist/b.o"
+// CHECK-FILELIST-SPLIT: @test1.rsp
+
+// CHECK-FILELIST-SPLIT-0: a.o
+
+// CHECK-FILELIST-SPLIT-1: b.o
+
+// RUN: %clang '-###' -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.o %S/Inputs/filelist/c.a %S/Inputs/filelist/b.o -o test 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-FILELIST-ARCHIVES
+// RUN: FileCheck -check-prefix CHECK-FILELIST-ARCHIVES-0 %s < test0.rsp
+
+// CHECK-FILELIST-ARCHIVES-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+// CHECK-FILELIST-ARCHIVES-NOT: "{{.*}}/test/Driver/Inputs/filelist/c.a"
+// CHECK-FILELIST-ARCHIVES-NOT: "{{.*}}/test/Driver/Inputs/filelist/b.o"
+// CHECK-FILELIST-ARCHIVES: @test0.rsp
+
+// CHECK-FILELIST-ARCHIVES-0: {{.*}}/test/Driver/Inputs/filelist/a.o
+// CHECK-FILELIST-ARCHIVES-0: {{.*}}/test/Driver/Inputs/filelist/c.a
+// CHECK-FILELIST-ARCHIVES-0: {{.*}}/test/Driver/Inputs/filelist/b.o
+
+// RUN: %clang -### -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.obj -o test 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-ALT-SUFFIX
+// RUN: FileCheck -check-prefix CHECK-ALT-SUFFIX-0 %s < test0.rsp
+
+// CHECK-ALT-SUFFIX-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.obj"
+// CHECK-ALT-SUFFIX: "@test0.rsp"
+
+// CHECK-ALT-SUFFIX-0: {{.*}}/test/Driver/Inputs/filelist/a.obj
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits