diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index 7be6dffbe37cf..60aa1fd99836e 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -249,6 +249,14 @@ class ToolChain { const Driver &getDriver() const { return D; } const llvm::Triple &getTriple() const { return Triple; } + /// Special handling for passing down '-l' arguments. + /// + /// Not all downstream tools (lldb, ld etc.) consistently accept + /// a space between the '-l' flag and its argument, so we remove + /// the extra space if it was present in \c Args. + static void addLinkedLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &FrontendArgs); + /// Construct a Job for the action \p JA, taking the given information into /// account. /// diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 3e83fc623a7e7..0e498ccddf932 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -701,7 +701,7 @@ def libc : Separate<["-"], "libc">, HelpText<"libc runtime library to use">; def linker_option_Group : OptionGroup<"">; -def l : Joined<["-"], "l">, Group, +def l : JoinedOrSeparate<["-"], "l">, Group, Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, HelpText<"Specifies a library which should be linked against">; def framework : Separate<["-"], "framework">, Group, diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index e4047e2839ed4..af322a56f496b 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -796,7 +796,9 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back("-no_objc_category_merging"); // These custom arguments should be right before the object file at the end. - context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); + context.Args.AddAllArgsExcept(Arguments, {options::OPT_linker_option_Group}, + {options::OPT_l}); + ToolChain::addLinkedLibArgs(context.Args, Arguments); context.Args.AddAllArgValues(Arguments, options::OPT_Xlinker); // This should be the last option, for convenience in checking output. diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 522a9727c454a..525af62dd2b56 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -287,6 +287,15 @@ mergeBatchInputs(ArrayRef jobs, return false; } +void ToolChain::addLinkedLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &FrontendArgs) { + Args.getLastArg(options::OPT_l); + for (auto Arg : Args.getAllArgValues(options::OPT_l)) { + const std::string lArg("-l" + Arg); + FrontendArgs.push_back(Args.MakeArgString(Twine(lArg))); + } +} + /// Construct a \c BatchJob by merging the constituent \p jobs' CommandOutput, /// input \c Job and \c Action members. Call through to \c constructInvocation /// on \p BatchJob, to build the \c InvocationInfo. diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index f11fed94301a7..ae5306538f915 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -142,6 +142,7 @@ static void addLTOArgs(const OutputInfo &OI, ArgStringList &arguments) { } } + void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, const CommandOutput &output, const ArgList &inputArgs, @@ -842,7 +843,8 @@ ToolChain::constructInvocation(const InterpretJobAction &job, Arguments.push_back("-module-name"); Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName)); - context.Args.AddAllArgs(Arguments, options::OPT_l, options::OPT_framework); + context.Args.AddAllArgs(Arguments, options::OPT_framework); + ToolChain::addLinkedLibArgs(context.Args, Arguments); // The immediate arguments must be last. context.Args.AddLastArg(Arguments, options::OPT__DASH_DASH); @@ -1190,8 +1192,8 @@ ToolChain::constructInvocation(const REPLJobAction &job, addRuntimeLibraryFlags(context.OI, FrontendArgs); context.Args.AddLastArg(FrontendArgs, options::OPT_import_objc_header); - context.Args.AddAllArgs(FrontendArgs, options::OPT_l, options::OPT_framework, - options::OPT_L); + context.Args.AddAllArgs(FrontendArgs, options::OPT_framework, options::OPT_L); + ToolChain::addLinkedLibArgs(context.Args, FrontendArgs); if (!useLLDB) { FrontendArgs.insert(FrontendArgs.begin(), {"-frontend", "-repl"}); diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 30905f6b72253..1dc32acfd8357 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -358,7 +358,9 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, } // These custom arguments should be right before the object file at the end. - context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); + context.Args.AddAllArgsExcept(Arguments, {options::OPT_linker_option_Group}, + {options::OPT_l}); + ToolChain::addLinkedLibArgs(context.Args, Arguments); context.Args.AddAllArgs(Arguments, options::OPT_Xlinker); context.Args.AddAllArgValues(Arguments, options::OPT_Xclang_linker); diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index b3567bf969b11..5001fa33fd2a5 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -179,7 +179,9 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, } context.Args.AddAllArgs(Arguments, options::OPT_Xlinker); - context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); + context.Args.AddAllArgsExcept(Arguments, {options::OPT_linker_option_Group}, + {options::OPT_l}); + ToolChain::addLinkedLibArgs(context.Args, Arguments); context.Args.AddAllArgValues(Arguments, options::OPT_Xclang_linker); // Run clang in verbose mode if "-v" is set diff --git a/test/Driver/linker-library-with-space.swift b/test/Driver/linker-library-with-space.swift new file mode 100644 index 0000000000000..b4497301147d6 --- /dev/null +++ b/test/Driver/linker-library-with-space.swift @@ -0,0 +1,18 @@ +// RUN: %swiftc_driver -sdk "" -driver-print-jobs -target x86_64-unknown-linux-gnu -Ffoo -Fsystem car -F cdr -framework bar -Lbaz -lboo -Xlinker -undefined %s 2>&1 > %t.linux.txt +// RUN: %FileCheck -check-prefix LINUX-lib-flag-space %s < %t.linux.txt + +// LINUX-lib-flag-space: swift +// LINUX-lib-flag-space: -o [[OBJECTFILE:.*]] + +// LINUX-lib-flag-space: clang{{(\.exe)?"? }} +// LINUX-lib-flag-space-DAG: -pie +// LINUX-lib-flag-space-DAG: [[OBJECTFILE]] +// LINUX-lib-flag-space-DAG: -lswiftCore +// LINUX-lib-flag-space-DAG: -L [[STDLIB_PATH:[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)]] +// LINUX-lib-flag-space-DAG: -Xlinker -rpath -Xlinker [[STDLIB_PATH]] +// LINUX-lib-flag-space-DAG: -F foo -iframework car -F cdr +// LINUX-lib-flag-space-DAG: -framework bar +// LINUX-lib-flag-space-DAG: -L baz +// LINUX-lib-flag-space-DAG: -lboo +// LINUX-lib-flag-space-DAG: -Xlinker -undefined +// LINUX-lib-flag-space: -o main diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index 2282192c66250..4f36bf7eada78 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -1,6 +1,8 @@ // Must be able to run xcrun-return-self.sh // REQUIRES: shell // REQUIRES: rdar65281056 +// FIXME: When this is turned on, please move the test from linker-library-with-space.swift +// to this file and remove that file. // RUN: %swiftc_driver -sdk "" -driver-print-jobs -target x86_64-apple-macosx10.9 %s 2>&1 > %t.simple.txt // RUN: %FileCheck %s < %t.simple.txt // RUN: %FileCheck -check-prefix SIMPLE %s < %t.simple.txt diff --git a/test/Driver/options-repl.swift b/test/Driver/options-repl.swift index 118ebd7b834f9..52646ae073fab 100644 --- a/test/Driver/options-repl.swift +++ b/test/Driver/options-repl.swift @@ -16,7 +16,7 @@ // RUN: %swift_driver -sdk "" -lldb-repl -### | %FileCheck -check-prefix=LLDB %s -// RUN: %swift_driver -sdk "" -lldb-repl -D A -DB -D C -DD -L /path/to/libraries -L /path/to/more/libraries -F /path/to/frameworks -lsomelib -framework SomeFramework -sdk / -I "this folder" -module-name Test -target %target-triple -### | %FileCheck -check-prefix=LLDB-OPTS %s +// RUN: %swift_driver -sdk "" -lldb-repl -D A -DB -D C -DD -L /path/to/libraries -L /path/to/more/libraries -F /path/to/frameworks -lsomelib -l otherlib -framework SomeFramework -sdk / -I "this folder" -module-name Test -target %target-triple -### | %FileCheck -check-prefix=LLDB-OPTS %s // LLDB: lldb{{(\.exe)?"?}} {{"?}}--repl= // LLDB-NOT: -module-name @@ -30,6 +30,7 @@ // LLDB-OPTS-DAG: -L /path/to/more/libraries // LLDB-OPTS-DAG: -F /path/to/frameworks // LLDB-OPTS-DAG: -lsomelib +// LLDB-OPTS-DAG: -lotherlib // LLDB-OPTS-DAG: -framework SomeFramework // LLDB-OPTS-DAG: -I \"this folder\" // LLDB-OPTS: "