Skip to content

Commit

Permalink
Always pass ghc-options (#8717)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Hécate <[email protected]>
(cherry picked from commit 9c775f2)

# Conflicts:
#	Cabal/src/Distribution/Simple/GHC.hs
#	doc/cabal-package-description-file.rst
  • Loading branch information
9999years authored and mergify[bot] committed Sep 14, 2024
1 parent 86f7f2c commit f87b166
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 6 deletions.
29 changes: 27 additions & 2 deletions Cabal/src/Distribution/Simple/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,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
Expand All @@ -701,13 +701,38 @@ 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
}
<<<<<<< HEAD

Check failure on line 706 in Cabal/src/Distribution/Simple/GHC.hs

View workflow job for this annotation

GitHub Actions / hlint

Error: Parse error: on input `<<<<<<<' ▫︎ Found: " , ghcOptExtra = hcOptions GHC libBi ++ hcProfOptions GHC libBi\n }\n> <<<<<<< HEAD\n ghcArgs\n | withVanillaLib lbi = vanillaArgs\n"

Check failure on line 706 in Cabal/src/Distribution/Simple/GHC.hs

View workflow job for this annotation

GitHub Actions / hlint

Error: Parse error: on input `<<<<<<<' ▫︎ Found: " , ghcOptExtra = hcOptions GHC libBi ++ hcProfOptions GHC libBi\n }\n> <<<<<<< HEAD\n ghcArgs\n | withVanillaLib lbi = vanillaArgs\n"
ghcArgs
| withVanillaLib lbi = vanillaArgs
| withSharedLib lbi = sharedArgs
| withProfLib lbi = profArgs
| otherwise = error "libAbiHash: Can't find an enabled library way"
=======
profDynArgs =
vanillaArgs
`mappend` mempty
{ ghcOptProfilingMode = toFlag True
, ghcOptProfilingAuto =
Internal.profDetailLevelFlag
True
(withProfLibDetail lbi)
, ghcOptDynLinkMode = toFlag GhcDynamicOnly
, ghcOptFPic = toFlag True
, ghcOptHiSuffix = toFlag "p_dyn_hi"
, ghcOptObjSuffix = toFlag "p_dyn_o"
, ghcOptExtra = hcOptions GHC libBi ++ hcProfSharedOptions GHC libBi
}
ghcArgs =
let (libWays, _, _) = buildWays lbi
in case libWays (componentIsIndefinite clbi) of
(ProfDynWay : _) -> profDynArgs
(ProfWay : _) -> profArgs
(StaticWay : _) -> vanillaArgs
(DynWay : _) -> sharedArgs
_ -> error "libAbiHash: Can't find an enabled library way"
>>>>>>> 9c775f2f6 (Always pass `ghc-options` (#8717))

(ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)

Expand Down
8 changes: 4 additions & 4 deletions Cabal/src/Distribution/Simple/GHCJS.hs
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,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
}

Expand Down Expand Up @@ -758,7 +758,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.
Expand Down Expand Up @@ -1309,7 +1309,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 =
Expand Down Expand Up @@ -1743,7 +1743,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
Expand Down
25 changes: 25 additions & 0 deletions changelog.d/pr-8717
Original file line number Diff line number Diff line change
@@ -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.

}
15 changes: 15 additions & 0 deletions doc/cabal-package-description-file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,21 @@ 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.

<<<<<<< HEAD
=======
.. pkg-field:: ghc-prof-shared-options: token list

Additional options for GHC when the package is built as shared profiling
library. The options specified via this field are combined with the
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).

>>>>>>> 9c775f2f6 (Always pass `ghc-options` (#8717))
.. pkg-field:: ghcjs-options: token list

Like :pkg-field:`ghc-options` but applies to GHCJS
Expand Down

0 comments on commit f87b166

Please sign in to comment.