summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2021-06-17 16:52:58 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-06-20 07:13:41 -0400
commit6281a333303a4dbe75a97a87c17c0fbace5268f5 (patch)
tree72f0fc5405fe5bfefdc5cd8183d10389f5b53079
parent6c783817ef089e85642c3383937117cff9d15f67 (diff)
downloadhaskell-6281a333303a4dbe75a97a87c17c0fbace5268f5.tar.gz
Linker/darwin: Properly honour -fno-use-rpaths
The specification is now simple * On linux, use `-Xlinker -rpath -Xlinker` to set the rpath of the executable * On darwin, never use `-Xlinker -rpath -Xlinker`, always inject the rpath afterwards, see `runInjectRPaths`. * If `-fno-use-rpaths` is passed then *never* inject anything into the rpath. Fixes #20004
-rw-r--r--compiler/GHC/Driver/Session.hs63
-rw-r--r--compiler/GHC/Linker/Dynamic.hs2
-rw-r--r--compiler/GHC/Linker/Loader.hs4
-rw-r--r--compiler/GHC/Linker/MacOS.hs2
-rw-r--r--compiler/GHC/Linker/Static.hs2
-rw-r--r--docs/users_guide/expected-undocumented-flags.txt1
-rw-r--r--docs/users_guide/phases.rst14
7 files changed, 56 insertions, 32 deletions
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 8b760a1b08..d51fa4d8f2 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -206,6 +206,7 @@ module GHC.Driver.Session (
-- * Linker/compiler information
LinkerInfo(..),
CompilerInfo(..),
+ useXLinkerRPath,
-- * Include specifications
IncludeSpecs(..), addGlobalInclude, addQuoteInclude, flattenIncludes,
@@ -3681,7 +3682,8 @@ defaultFlags settings
Opt_ProfCountEntries,
Opt_SharedImplib,
Opt_SimplPreInlining,
- Opt_VersionMacros
+ Opt_VersionMacros,
+ Opt_RPath
]
++ [f | (ns,f) <- optLevelFlags, 0 `elem` ns]
@@ -3689,8 +3691,6 @@ defaultFlags settings
++ default_PIC platform
- ++ default_RPath platform
-
++ validHoleFitDefaults
where platform = sTargetPlatform settings
@@ -3744,29 +3744,6 @@ default_PIC platform =
-- information.
_ -> []
-
--- We usually want to use RPath, except on macOS (OSDarwin). On recent macOS
--- versions the number of load commands we can embed in a dynamic library is
--- restricted. Hence since b592bd98ff2 we rely on -dead_strip_dylib to only
--- link the needed dylibs instead of linking the full dependency closure.
---
--- If we split the library linking into injecting -rpath and -l @rpath/...
--- components, we will reduce the number of libraries we link, however we will
--- still inject one -rpath entry for each library, independent of their use.
--- That is, we even inject -rpath values for libraries that we dead_strip in
--- the end. As such we can run afoul of the load command size limit simply
--- by polluting the load commands with RPATH entries.
---
--- Thus, we disable Opt_RPath by default on OSDarwin. The savvy user can always
--- enable it with -use-rpath if they so wish.
---
--- See Note [Dynamic linking on macOS]
-
-default_RPath :: Platform -> [GeneralFlag]
-default_RPath platform | platformOS platform == OSDarwin = []
-default_RPath _ = [Opt_RPath]
-
-
-- General flags that are switched on/off when other general flags are switched
-- on
impliedGFlags :: [(GeneralFlag, TurnOnFlag, GeneralFlag)]
@@ -4786,6 +4763,40 @@ data CompilerInfo
| UnknownCC
deriving Eq
+
+-- | Should we use `-XLinker -rpath` when linking or not?
+-- See Note [-fno-use-rpaths]
+useXLinkerRPath :: DynFlags -> OS -> Bool
+useXLinkerRPath _ OSDarwin = False -- See Note [Dynamic linking on macOS]
+useXLinkerRPath dflags _ = gopt Opt_RPath dflags
+
+{-
+Note [-fno-use-rpaths]
+~~~~~~~~~~~~~~~~~~~~~~
+
+First read, Note [Dynamic linking on macOS] to understand why on darwin we never
+use `-XLinker -rpath`.
+
+The specification of `Opt_RPath` is as follows:
+
+The default case `-fuse-rpaths`:
+* On darwin, never use `-Xlinker -rpath -Xlinker`, always inject the rpath
+ afterwards, see `runInjectRPaths`. There is no way to use `-Xlinker` on darwin
+ as things stand but it wasn't documented in the user guide before this patch how
+ `-fuse-rpaths` should behave and the fact it was always disabled on darwin.
+* Otherwise, use `-Xlinker -rpath -Xlinker` to set the rpath of the executable,
+ this is the normal way you should set the rpath.
+
+The case of `-fno-use-rpaths`
+* Never inject anything into the rpath.
+
+When this was first implemented, `Opt_RPath` was disabled on darwin, but
+the rpath was still always augmented by `runInjectRPaths`, and there was no way to
+stop this. This was problematic because you couldn't build an executable in CI
+with a clean rpath.
+
+-}
+
-- -----------------------------------------------------------------------------
-- RTS hooks
diff --git a/compiler/GHC/Linker/Dynamic.hs b/compiler/GHC/Linker/Dynamic.hs
index 5c96eb55aa..48c3c6fcbd 100644
--- a/compiler/GHC/Linker/Dynamic.hs
+++ b/compiler/GHC/Linker/Dynamic.hs
@@ -57,7 +57,7 @@ linkDynLib logger tmpfs dflags0 unit_env o_files dep_packages
, -- Only if we want dynamic libraries
WayDyn `Set.member` ways dflags
-- Only use RPath if we explicitly asked for it
- , gopt Opt_RPath dflags
+ , useXLinkerRPath dflags os
= ["-L" ++ l, "-Xlinker", "-rpath", "-Xlinker", l]
-- See Note [-Xlinker -rpath vs -Wl,-rpath]
| otherwise = ["-L" ++ l]
diff --git a/compiler/GHC/Linker/Loader.hs b/compiler/GHC/Linker/Loader.hs
index 97cfac3a7e..749c8ea725 100644
--- a/compiler/GHC/Linker/Loader.hs
+++ b/compiler/GHC/Linker/Loader.hs
@@ -964,7 +964,7 @@ dynLoadObjs interp hsc_env pls@LoaderState{..} objs = do
concatMap (\l -> [ Option ("-l" ++ l) ])
(nub $ snd <$> temp_sos)
++ concatMap (\lp -> Option ("-L" ++ lp)
- : if gopt Opt_RPath dflags
+ : if useXLinkerRPath dflags (platformOS platform)
then [ Option "-Xlinker"
, Option "-rpath"
, Option "-Xlinker"
@@ -973,7 +973,7 @@ dynLoadObjs interp hsc_env pls@LoaderState{..} objs = do
(nub $ fst <$> temp_sos)
++ concatMap
(\lp -> Option ("-L" ++ lp)
- : if gopt Opt_RPath dflags
+ : if useXLinkerRPath dflags (platformOS platform)
then [ Option "-Xlinker"
, Option "-rpath"
, Option "-Xlinker"
diff --git a/compiler/GHC/Linker/MacOS.hs b/compiler/GHC/Linker/MacOS.hs
index 4851ae96b9..765ea7a7b3 100644
--- a/compiler/GHC/Linker/MacOS.hs
+++ b/compiler/GHC/Linker/MacOS.hs
@@ -44,6 +44,8 @@ import System.FilePath ((</>), (<.>))
--
-- See Note [Dynamic linking on macOS]
runInjectRPaths :: Logger -> DynFlags -> [FilePath] -> FilePath -> IO ()
+-- Make sure to honour -fno-use-rpaths if set on darwin as well see #20004
+runInjectRPaths _ dflags _ _ | not (gopt Opt_RPath dflags) = return ()
runInjectRPaths logger dflags lib_paths dylib = do
info <- lines <$> askOtool logger dflags Nothing [Option "-L", Option dylib]
-- filter the output for only the libraries. And then drop the @rpath prefix.
diff --git a/compiler/GHC/Linker/Static.hs b/compiler/GHC/Linker/Static.hs
index b0b8f1c541..a94fa153f6 100644
--- a/compiler/GHC/Linker/Static.hs
+++ b/compiler/GHC/Linker/Static.hs
@@ -95,7 +95,7 @@ linkBinary' staticLink logger tmpfs dflags unit_env o_files dep_units = do
(l `makeRelativeTo` full_output_fn)
else l
-- See Note [-Xlinker -rpath vs -Wl,-rpath]
- rpath = if gopt Opt_RPath dflags
+ rpath = if useXLinkerRPath dflags (platformOS platform)
then ["-Xlinker", "-rpath", "-Xlinker", libpath]
else []
-- Solaris 11's linker does not support -rpath-link option. It silently
diff --git a/docs/users_guide/expected-undocumented-flags.txt b/docs/users_guide/expected-undocumented-flags.txt
index f7e55fa573..9861386d0c 100644
--- a/docs/users_guide/expected-undocumented-flags.txt
+++ b/docs/users_guide/expected-undocumented-flags.txt
@@ -82,7 +82,6 @@
-fspecialize-aggressively
-fth
-ftype-function-depth
--fuse-rpaths
-fversion-macros
-fvia-c
-haddock-opts
diff --git a/docs/users_guide/phases.rst b/docs/users_guide/phases.rst
index 73d9777f99..6833ce36d7 100644
--- a/docs/users_guide/phases.rst
+++ b/docs/users_guide/phases.rst
@@ -824,6 +824,18 @@ for example).
Where to find user-supplied libraries… Prepend the directory ⟨dir⟩
to the library directories path.
+.. ghc-flag:: -fuse-rpaths
+ :shortdesc: Set the rpath based on -L flags
+ :type: dynamic
+ :category: linking
+
+ This flag is enabled by default and will set the rpath of the linked
+ object to the library directories of dependent packages.
+
+ When building binaries to distribute it can be useful to pass your own
+ linker options to control the rpath and disable the automatic injection of
+ rpath entries by disabling this flag.
+
.. ghc-flag:: -framework-path ⟨dir⟩
:shortdesc: On Darwin/OS X/iOS only, add ⟨dir⟩ to the list of directories
searched for frameworks. This option corresponds to the ``-F``
@@ -911,7 +923,7 @@ for example).
When linking shared libraries (:ghc-flag:`-shared`) GHC does not
automatically link the RTS. This is to allow choosing the RTS flavour
(:ghc-flag:`-threaded`, :ghc-flag:`-eventlog`, etc) when linking an
- executable.
+ executable.
However when the shared library is the intended product it is useful to be
able to reverse this default. See :ref:`shared-libraries-c-api` for an
usage example.