From c7a198bc03467e55f2a933be3ac8c4fece3bd094 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 16 Mar 2020 17:55:00 +0000 Subject: [PATCH] Driver: honour `-no-toolchain-stdlib-rpath` on Unices Handle `-no-toolchain-stdlib-rpath` on Linux/android as well as Darwin. This enables the flags on other Unix platforms as it can be useful to control the embedded rpath for the library. --- lib/Driver/ToolChains.h | 9 ++------- lib/Driver/UnixToolChains.cpp | 32 +++++++++++++++++++++++++------- test/Driver/linker.swift | 13 ++++++++++++- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index bd3302acebae3..a01eef8139589 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -114,11 +114,8 @@ class LLVM_LIBRARY_VISIBILITY GenericUnix : public ToolChain { /// platforms. virtual std::string getTargetForLinker() const; - /// Whether to specify a linker -rpath to the Swift runtime library path. - /// -rpath is not supported on all platforms, and subclasses may override - /// this method to return false on platforms that don't support it. The - /// default is to return true (and so specify an -rpath). - virtual bool shouldProvideRPathToLinker() const; + bool addRuntimeRPath(const llvm::Triple &T, + const llvm::opt::ArgList &Args) const; InvocationInfo constructInvocation(const DynamicLinkJobAction &job, const JobContext &context) const override; @@ -137,8 +134,6 @@ class LLVM_LIBRARY_VISIBILITY Android : public GenericUnix { protected: std::string getTargetForLinker() const override; - bool shouldProvideRPathToLinker() const override; - public: Android(const Driver &D, const llvm::Triple &Triple) : GenericUnix(D, Triple) {} diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 882358a938185..4383d298e00b5 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -110,8 +110,30 @@ std::string toolchains::GenericUnix::getTargetForLinker() const { return getTriple().str(); } -bool toolchains::GenericUnix::shouldProvideRPathToLinker() const { - return true; +bool toolchains::GenericUnix::addRuntimeRPath(const llvm::Triple &T, + const llvm::opt::ArgList &Args) const { + // If we are building a static executable, do not add a rpath for the runtime + // as it is a static binary and the loader will not be invoked. + if (Args.hasFlag(options::OPT_static_executable, + options::OPT_no_static_executable, false)) + return false; + + // If we are building with a static standard library, do not add a rpath for + // the runtime because the runtime will be part of the binary and the rpath is + // no longer necessary. + if (Args.hasFlag(options::OPT_static_stdlib, options::OPT_no_static_stdlib, + false)) + return false; + + // FIXME: We probably shouldn't be adding an rpath here unless we know ahead + // of time the standard library won't be copied. + + // Honour the user's request to add a rpath to the binary. This defaults to + // `true` on non-android and `false` on android since the library must be + // copied into the bundle. + return Args.hasFlag(options::OPT_toolchain_stdlib_rpath, + options::OPT_no_toolchain_stdlib_rpath, + !T.isAndroid()); } ToolChain::InvocationInfo @@ -209,9 +231,7 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, getRuntimeLibraryPaths(RuntimeLibPaths, context.Args, context.OI.SDKPath, /*Shared=*/!(staticExecutable || staticStdlib)); - if (!(staticExecutable || staticStdlib) && shouldProvideRPathToLinker()) { - // FIXME: We probably shouldn't be adding an rpath here unless we know - // ahead of time the standard library won't be copied. + if (addRuntimeRPath(getTriple(), context.Args)) { for (auto path : RuntimeLibPaths) { Arguments.push_back("-Xlinker"); Arguments.push_back("-rpath"); @@ -381,8 +401,6 @@ std::string toolchains::Android::getTargetForLinker() const { } } -bool toolchains::Android::shouldProvideRPathToLinker() const { return false; } - std::string toolchains::Cygwin::getDefaultLinker() const { // Cygwin uses the default BFD linker, even on ARM. return ""; diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index 41da067876b96..a6cd03565ee91 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -27,7 +27,7 @@ // RUN: %swiftc_driver -driver-print-jobs -target thumbv7-unknown-linux-gnueabihf -Ffoo -Fsystem car -F cdr -framework bar -Lbaz -lboo -Xlinker -undefined %s 2>&1 > %t.linux.txt // RUN: %FileCheck -check-prefix LINUX-thumbv7 %s < %t.linux.txt -// RUN: %swiftc_driver -driver-print-jobs -target armv7-none-linux-androideabi -Ffoo -Fsystem car -F cdr -framework bar -Lbaz -lboo -Xlinker -undefined %s 2>&1 > %t.android.txt +// RUN: %swiftc_driver_plain -driver-print-jobs -target armv7-none-linux-androideabi -Ffoo -Fsystem car -F cdr -framework bar -Lbaz -lboo -Xlinker -undefined %s 2>&1 > %t.android.txt // RUN: %FileCheck -check-prefix ANDROID-armv7 %s < %t.android.txt // RUN: %FileCheck -check-prefix ANDROID-armv7-NEGATIVE %s < %t.android.txt @@ -63,6 +63,12 @@ // RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -g %s | %FileCheck -check-prefix DEBUG %s +// RUN: %swiftc_driver_plain -driver-print-jobs -target x86_64-unknown-linux-gnu -toolchain-stdlib-rpath %s 2>&1 | %FileCheck -check-prefix LINUX-STDLIB-RPATH %s +// RUN: %swiftc_driver_plain -driver-print-jobs -target x86_64-unknown-linux-gnu -no-toolchain-stdlib-rpath %s 2>&1 | %FileCheck -check-prefix LINUX-NO-STDLIB-RPATH %s + +// RUN: %swiftc_driver_plain -driver-print-jobs -target armv7-unknown-linux-androideabi -toolchain-stdlib-rpath %s 2>&1 | %FileCheck -check-prefix ANDROID-STDLIB-RPATH %s +// RUN: %swiftc_driver_plain -driver-print-jobs -target armv7-unknown-linux-androideabi -no-toolchain-stdlib-rpath %s 2>&1 | %FileCheck -check-prefix ANDROID-NO-STDLIB-RPATH %s + // RUN: %empty-directory(%t) // RUN: touch %t/a.o // RUN: touch %t/a.swiftmodule @@ -428,6 +434,11 @@ // RELATIVE_ARCLITE: {{/|\\\\}}DISTINCTIVE-PATH{{/|\\\\}}usr{{/|\\\\}}lib{{/|\\\\}}arc{{/|\\\\}}libarclite_macosx.a // RELATIVE_ARCLITE: -o {{[^ ]+}} +// LINUX-STDLIB-RPATH: -Xlinker -rpath -Xlinker [[STDLIB_PATH:[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)linux]] +// LINUX-NO-STDLIB-RPATH-NOT: -Xlinker -rpath -Xlinker [[STDLIB_PATH:[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)linux]] + +// ANDROID-STDLIB-RPATH: -Xlinker -rpath -Xlinker [[STDLIB_PATH:[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)android]] +// ANDROID-NO-STDLIB-RPATH-NOT: -Xlinker -rpath -Xlinker [[STDLIB_PATH:[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)android]] // Clean up the test executable because hard links are expensive. // RUN: rm -rf %t/DISTINCTIVE-PATH/usr/bin/swiftc