diff options
author | Matthew Pickering <matthewtpickering@gmail.com> | 2021-06-17 16:52:58 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-06-20 07:13:41 -0400 |
commit | 6281a333303a4dbe75a97a87c17c0fbace5268f5 (patch) | |
tree | 72f0fc5405fe5bfefdc5cd8183d10389f5b53079 | |
parent | 6c783817ef089e85642c3383937117cff9d15f67 (diff) | |
download | haskell-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.hs | 63 | ||||
-rw-r--r-- | compiler/GHC/Linker/Dynamic.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Linker/Loader.hs | 4 | ||||
-rw-r--r-- | compiler/GHC/Linker/MacOS.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Linker/Static.hs | 2 | ||||
-rw-r--r-- | docs/users_guide/expected-undocumented-flags.txt | 1 | ||||
-rw-r--r-- | docs/users_guide/phases.rst | 14 |
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. |