-
Notifications
You must be signed in to change notification settings - Fork 697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass ld-options
through to GHC
#5451
Pass ld-options
through to GHC
#5451
Conversation
Please let me know if there are docs I should update for this. |
Hmm, this isn't working yet. The flags are passed to the linker, but they appear too early in the Since with linker flags later I want them to appear at the end. Any hints? Is this because of the position inside GHC flags as given in
|
I tried permuting the flags directly in the GHC invocation cabal makes, but the results are the same. So it seems like |
I found a very hacky workaround: Pass This makes the order unimportant: See https://linux.die.net/man/1/ld
I don't want to keep this as the final solution though, as it can make linking slower (and you lose the ability to specify which symbols exactly should be picked by exploiting the order; but this ability you lose anyway if GHC gives you only one location to put your symbols). At least this workaround is independent from Cabal itself: It works with the current PR without modifications, only users would have to use it. |
Urgh, trouble. You cannot pass
But you also can't pass This problem is created by the fact that GHC uses Why is that? From
|
I have researched how the various linkers do it: GNU
|
6840cdf
to
eeb4aeb
Compare
Is this PR good? |
How can i test it without messing up my working ghc installation? |
You should be able to test it by just cloning from git, checking out the branch, and building it with cabal or stack. You don't need to install it globally. |
Is there anything that an interested passerby like myself could do to help get this merged? Statically linked Haskell executables are something I'm very much interested, so I'd like to help unblock anything if it's at all within my capability 😄 |
any update? |
Ping. #5446 has been merged, so it would be really nice if this could be merged in as well. |
eeb4aeb
to
1916762
Compare
1916762
to
26f5b34
Compare
I've rebased (there was a formatting-to-80-line-limit change apparently). This is ready to be merged from my side. Also answering my own question from before:
I found that this is a decision of GHC itself, not Cabal. Using , ["-l" ++ lib | lib <- ghcOptLinkLibs opts]
, ["-L" ++ dir | dir <- flags ghcOptLinkLibPath ]
, [ "-optl" ++ opt | opt <- ghcOptLinkOptions opts] instead of , [ "-optl" ++ opt | opt <- ghcOptLinkOptions opts]
, ["-l" ++ lib | lib <- ghcOptLinkLibs opts]
, ["-L" ++ dir | dir <- flags ghcOptLinkLibPath ] doesn't help with the fact that the
flags that GHC adds at the very end. If we want to change that, we probably have to do that in GHC itself. |
Also I would very very very much like if this could be cherry-picked on |
This fixes only GHC, what about GHCJS? Wouldn't similar problem we there too? |
This is completely @bgamari's call. This shouldn't break anything, but who knows... I'd like to see similar change for GHCJS, and tests. Without those, I wouldn't merge this. |
... i.e. IMHO 3.0 train has left the station. |
I’d GHCJS supposed to be a first-class-citizen for Cabal support? I was under the impression that GHC was the primary support target for Cabal. If this is the case it would more than make sense for this to be pulled into the 3.0 release train as this is a significant feature for anyone building “relocatable” Haskell executables. |
My goals with this are for statically linking Linux executables. I would prefer to leave ghcjs related changes to those familiar with that toolchain; I'm not even sure to what program |
Repeating a side investigation from a review question, so that it's visible here (quoting myself):
This addresses the last mystery I've encountered while implementing this. |
Ready to merge from my side. Please remember that this PR adds only 2 lines of code, and the 2 are identical. Correspondingly, this is a 1-line PR with pretty obvious effect that's been waiting for > 1 year. It would be great to get it landed. |
Merged, thanks! |
Pass `ld-options` through to GHC (cherry picked from commit 853414b)
Also cherry-picked into 3.0. |
Cabal-3.0.0.0 has been released on Hackage with this change. |
Now that this is done, who should we ask that's familiar with the cabal parts of ghcjs whether a similar change would make sense for ghcjs? |
Looks like Given some
and still produces
There is however linking step in GHCJS compilation process too
but I'm not sure if there's anything to configure, and whether it's just |
I've filed a GHC bug for that now: https://gitlab.haskell.org/ghc/ghc/issues/17071 |
I've made a tentative PR for that now: https://gitlab.haskell.org/ghc/ghc/merge_requests/1589 |
/cc @luite @JoshMeredith |
GHCJS has an internal linker and doesn't pass the options on to a separate program at the moment. In general it ignores unsupported options. It should be safe to pass |
Until now, giving `-optl` linker flags to `ghc` on the command line placed them in the wrong place in the `ld` command line: They were given before all the Haskell libararies, when they should appear after. Background: Most linkers like `ld.bfd` and `ld.gold`, but not the newer LLVM `lld`, work in a way where the order of `-l` flags given matters; earlier `-lmylib1` flags are supposed to create "holes" for linker symbols that are to be filled with later `lmylib2` flags that "fill the holes" for these symbols. As discovered in haskell/cabal#5451 (comment), the `-optl` flags appeared before e.g. the -lHStext-1.2.3.1 -lHSbinary-0.8.6.0 -lHScontainers-0.6.0.1 flags that GHC added at the very end. Haskell libraries typically depend on C libraries, so `-lHS*` flags will create holes for the C libraries to fill in, but that only works when those libraries' `-l` flags are given **after** the `-lHS*` flags; until now they were given before, which was wrong. This meant that Cabal's `--ld-options` flag and `ld-options` `.cabal` file field were pretty ineffective, unless you used the `--ld-option=--start-group` hack as (haskell/cabal#5451 (comment)) that convinces the classical linkers to not be dependent on the order of linker flags given. This commit fixes the problem by simply flipping the order, putting `-optl` flags at the end, after Haskell libraries. The code change is effectively only `args1 ++ args` -> `args ++ args1` but the commit also renames the variables for improved clarity. Simple way to test it: ghc --make Main.hs -fforce-recomp -v -optl-s on a `Main.hs` like: import qualified Data.Set as Set main = print $ Set.fromList "hello"
Until now, giving `-optl` linker flags to `ghc` on the command line placed them in the wrong place in the `ld` command line: They were given before all the Haskell libararies, when they should appear after. Background: Most linkers like `ld.bfd` and `ld.gold`, but not the newer LLVM `lld`, work in a way where the order of `-l` flags given matters; earlier `-lmylib1` flags are supposed to create "holes" for linker symbols that are to be filled with later `lmylib2` flags that "fill the holes" for these symbols. As discovered in haskell/cabal#5451 (comment), the `-optl` flags appeared before e.g. the -lHStext-1.2.3.1 -lHSbinary-0.8.6.0 -lHScontainers-0.6.0.1 flags that GHC added at the very end. Haskell libraries typically depend on C libraries, so `-lHS*` flags will create holes for the C libraries to fill in, but that only works when those libraries' `-l` flags are given **after** the `-lHS*` flags; until now they were given before, which was wrong. This meant that Cabal's `--ld-options` flag and `ld-options` `.cabal` file field were pretty ineffective, unless you used the `--ld-option=--start-group` hack as (haskell/cabal#5451 (comment)) that convinces the classical linkers to not be dependent on the order of linker flags given. This commit fixes the problem by simply flipping the order, putting `-optl` flags at the end, after Haskell libraries. The code change is effectively only `args1 ++ args` -> `args ++ args1` but the commit also renames the variables for improved clarity. Simple way to test it: ghc --make Main.hs -fforce-recomp -v -optl-s on a `Main.hs` like: import qualified Data.Set as Set main = print $ Set.fromList "hello"
Until now, giving `-optl` linker flags to `ghc` on the command line placed them in the wrong place in the `ld` command line: They were given before all the Haskell libararies, when they should appear after. Background: Most linkers like `ld.bfd` and `ld.gold`, but not the newer LLVM `lld`, work in a way where the order of `-l` flags given matters; earlier `-lmylib1` flags are supposed to create "holes" for linker symbols that are to be filled with later `lmylib2` flags that "fill the holes" for these symbols. As discovered in haskell/cabal#5451 (comment), the `-optl` flags appeared before e.g. the -lHStext-1.2.3.1 -lHSbinary-0.8.6.0 -lHScontainers-0.6.0.1 flags that GHC added at the very end. Haskell libraries typically depend on C libraries, so `-lHS*` flags will create holes for the C libraries to fill in, but that only works when those libraries' `-l` flags are given **after** the `-lHS*` flags; until now they were given before, which was wrong. This meant that Cabal's `--ld-options` flag and `ld-options` `.cabal` file field were pretty ineffective, unless you used the `--ld-option=--start-group` hack as (haskell/cabal#5451 (comment)) that convinces the classical linkers to not be dependent on the order of linker flags given. This commit fixes the problem by simply flipping the order, putting `-optl` flags at the end, after Haskell libraries. The code change is effectively only `args1 ++ args` -> `args ++ args1` but the commit also renames the variables for improved clarity. Simple way to test it: ghc --make Main.hs -fforce-recomp -v -optl-s on a `Main.hs` like: import qualified Data.Set as Set main = print $ Set.fromList "hello"
Until now, giving `-optl` linker flags to `ghc` on the command line placed them in the wrong place in the `ld` command line: They were given before all the Haskell libararies, when they should appear after. Background: Most linkers like `ld.bfd` and `ld.gold`, but not the newer LLVM `lld`, work in a way where the order of `-l` flags given matters; earlier `-lmylib1` flags are supposed to create "holes" for linker symbols that are to be filled with later `lmylib2` flags that "fill the holes" for these symbols. As discovered in haskell/cabal#5451 (comment), the `-optl` flags appeared before e.g. the -lHStext-1.2.3.1 -lHSbinary-0.8.6.0 -lHScontainers-0.6.0.1 flags that GHC added at the very end. Haskell libraries typically depend on C libraries, so `-lHS*` flags will create holes for the C libraries to fill in, but that only works when those libraries' `-l` flags are given **after** the `-lHS*` flags; until now they were given before, which was wrong. This meant that Cabal's `--ld-options` flag and `ld-options` `.cabal` file field were pretty ineffective, unless you used the `--ld-option=--start-group` hack as (haskell/cabal#5451 (comment)) that convinces the classical linkers to not be dependent on the order of linker flags given. This commit fixes the problem by simply flipping the order, putting `-optl` flags at the end, after Haskell libraries. The code change is effectively only `args1 ++ args` -> `args ++ args1` but the commit also renames the variables for improved clarity. Simple way to test it: ghc --make Main.hs -fforce-recomp -v -optl-s on a `Main.hs` like: import qualified Data.Set as Set main = print $ Set.fromList "hello"
My GHC PR was merged, so 8.10 should fix the remaining problems here. |
Tentative. Fixes #4925
Based on #5446; that one should be merged first and then this one rebased.
To review, only review the top commits (this change is much smaller than it looks here).
Please include the following checklist in your PR:
[ci skip]
is used to avoid triggering the build bots.Please also shortly describe how you tested your change. Bonus points for added tests!
cabal init
mini project and checking that it "fails the right way" (linker errors) when--ld-option=-static
is given.