Skip to content
  • Niklas Hambüchen's avatar
    linker: Move -optl flags to end of linker invocation. · 60c26403
    Niklas Hambüchen authored and Marge Bot's avatar Marge Bot committed
    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
    https://github.com/haskell/cabal/pull/5451#issuecomment-518001240,
    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
    (https://github.com/haskell/cabal/pull/5451#issuecomment-406761676) 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"
    60c26403