From 9c775f2f6dd9ce03f62573f40e2738487cbe0c2b Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Mon, 19 Aug 2024 08:17:37 -0400 Subject: [PATCH] Always pass `ghc-options` (#8717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Always pass `ghc-options` The [documentation for `ghc-shared-options`][1] states that they are combined with `ghc-options`: > Additional options for GHC when the package is built as shared > library. The options specified via this field are combined with the > ones specified via `ghc-options`, and are passed to GHC during both > the compile and link phases. However, _only_ `ghc-shared-options` and not `ghc-options` are passed in many cases. This is an issue because it requires setting `ghc-shared-options` even if the shared (dynamic) parts of the build don't actually need different options; this has the unpleasant side-effect of causing modules to be compiled twice, effectively doubling compile time! See here, where any non-empty `ghc-shared-options` causes Cabal to not set `-dynamic-too`: https://github.com/haskell/cabal/blob/acbc0f3a5cc9faf0913ff3e270196693816cec41/Cabal/src/Distribution/Simple/GHC.hs#L1466-L1469 This issue was discovered while integrating the `mold` linker with a Haskell project. [1]: https://cabal.readthedocs.io/en/latest/cabal-package.html#pkg-field-ghc-shared-options * Add documentation * Also enhance profArgs and profDynArgs --------- Co-authored-by: Hécate Moonlight Co-authored-by: Hécate --- Cabal/src/Distribution/Simple/GHC.hs | 6 +++--- Cabal/src/Distribution/Simple/GHCJS.hs | 8 ++++---- changelog.d/pr-8717 | 25 +++++++++++++++++++++++++ doc/cabal-package-description-file.rst | 5 +++++ 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 changelog.d/pr-8717 diff --git a/Cabal/src/Distribution/Simple/GHC.hs b/Cabal/src/Distribution/Simple/GHC.hs index 3ce66bb38bc..a8f15bc92da 100644 --- a/Cabal/src/Distribution/Simple/GHC.hs +++ b/Cabal/src/Distribution/Simple/GHC.hs @@ -734,7 +734,7 @@ libAbiHash verbosity _pkg_descr lbi lib clbi = do , ghcOptFPic = toFlag True , ghcOptHiSuffix = toFlag "dyn_hi" , ghcOptObjSuffix = toFlag "dyn_o" - , ghcOptExtra = hcSharedOptions GHC libBi + , ghcOptExtra = hcOptions GHC libBi ++ hcSharedOptions GHC libBi } profArgs = vanillaArgs @@ -746,7 +746,7 @@ libAbiHash verbosity _pkg_descr lbi lib clbi = do (withProfLibDetail lbi) , ghcOptHiSuffix = toFlag "p_hi" , ghcOptObjSuffix = toFlag "p_o" - , ghcOptExtra = hcProfOptions GHC libBi + , ghcOptExtra = hcOptions GHC libBi ++ hcProfOptions GHC libBi } profDynArgs = vanillaArgs @@ -760,7 +760,7 @@ libAbiHash verbosity _pkg_descr lbi lib clbi = do , ghcOptFPic = toFlag True , ghcOptHiSuffix = toFlag "p_dyn_hi" , ghcOptObjSuffix = toFlag "p_dyn_o" - , ghcOptExtra = hcProfSharedOptions GHC libBi + , ghcOptExtra = hcOptions GHC libBi ++ hcProfSharedOptions GHC libBi } ghcArgs = let (libWays, _, _) = buildWays lbi diff --git a/Cabal/src/Distribution/Simple/GHCJS.hs b/Cabal/src/Distribution/Simple/GHCJS.hs index 973230ee3c7..05fa3016738 100644 --- a/Cabal/src/Distribution/Simple/GHCJS.hs +++ b/Cabal/src/Distribution/Simple/GHCJS.hs @@ -583,7 +583,7 @@ buildOrReplLib mReplFlags verbosity numJobs _pkg_descr lbi lib clbi = do , ghcOptFPic = toFlag True , -- ghcOptHiSuffix = toFlag "dyn_hi", -- ghcOptObjSuffix = toFlag "dyn_o", - ghcOptExtra = hcSharedOptions GHC libBi + ghcOptExtra = hcOptions GHC libBi ++ hcSharedOptions GHC libBi , ghcOptHPCDir = hpcdir Hpc.Dyn } @@ -772,7 +772,7 @@ buildOrReplLib mReplFlags verbosity numJobs _pkg_descr lbi lib clbi = do , ghcOptDynLinkMode = toFlag GhcDynamicOnly , ghcOptInputFiles = toNubListR dynamicObjectFiles , ghcOptOutputFile = toFlag sharedLibFilePath - , ghcOptExtra = hcSharedOptions GHC libBi + , ghcOptExtra = hcOptions GHC libBi ++ hcSharedOptions GHC libBi , -- For dynamic libs, Mac OS/X needs to know the install location -- at build time. This only applies to GHC < 7.8 - see the -- discussion in #1660. @@ -1330,7 +1330,7 @@ gbuild verbosity numJobs pkg_descr lbi bm clbi = do ghcOptFPic = toFlag True , ghcOptHiSuffix = toFlag "dyn_hi" , ghcOptObjSuffix = toFlag "dyn_o" - , ghcOptExtra = hcSharedOptions GHC bnfo + , ghcOptExtra = hcOptions GHC bnfo ++ hcSharedOptions GHC bnfo , ghcOptHPCDir = hpcdir Hpc.Dyn } dynTooOpts = @@ -1781,7 +1781,7 @@ libAbiHash verbosity _pkg_descr lbi lib clbi = do , ghcOptFPic = toFlag True , ghcOptHiSuffix = toFlag "js_dyn_hi" , ghcOptObjSuffix = toFlag "js_dyn_o" - , ghcOptExtra = hcSharedOptions GHC libBi + , ghcOptExtra = hcOptions GHC libBi ++ hcSharedOptions GHC libBi } profArgs = vanillaArgs diff --git a/changelog.d/pr-8717 b/changelog.d/pr-8717 new file mode 100644 index 00000000000..b0ac7e09388 --- /dev/null +++ b/changelog.d/pr-8717 @@ -0,0 +1,25 @@ +synopsis: Always pass `ghc-options` to GHC +packages: Cabal +prs: #8717 +issues: + +description: { + +Previously, options set in the package field `ghc-options` would not be passed +to GHC during the link phase for shared objects (where multiple `.o` or +`.dyn_o` files are merged into a single object file). This made it impossible +to use `ghc-options` to use a different linker by setting (for example) +`ghc-options: -optl-fuse-ld=mold -optlm-fuse-ld=mold`; the options would be +dropped in the link phase, falling back to the default linker. + +It was possible to work around this by duplicating the `ghc-options` to +`ghc-shared-options`, which _are_ passed in the shared link phase, but that had +the (undocumented and unfortunate) side-effect of disabling the GHC +`-dynamic-too` flag, effectively doubling compilation times when +`ghc-shared-options` are set. + +Now, `ghc-options` are combined with `ghc-shared-options` (to accurately +reflect the documentation on this feature) and the fact that +`ghc-shared-options` disables `-dynamic-too` is documented. + +} diff --git a/doc/cabal-package-description-file.rst b/doc/cabal-package-description-file.rst index e5e170f3984..839b2dc37db 100644 --- a/doc/cabal-package-description-file.rst +++ b/doc/cabal-package-description-file.rst @@ -1780,6 +1780,11 @@ system-dependent values for these fields. ones specified via :pkg-field:`ghc-options`, and are passed to GHC during both the compile and link phases. + Note that if any :pkg-field:`ghc-shared-options` are set, the + ``-dynamic-too` option will never be passed to GHC, leading to all modules + being compiled twice (once to generate the ``.o`` files and another to + generate the ``.dyn_o`` files). + .. pkg-field:: ghcjs-options: token list Like :pkg-field:`ghc-options` but applies to GHCJS