Building shared library with GHC 9.4.5

I have a personal project which on Linux involves building a shared library to be linked into a C++ program. The relevant portion of the Cabal file is as follows:

library
  if os(windows)
    ghc-options:         -stubdir stub -o brassica-interop.a -static -optl-static -staticlib -Wall
  else
    ghc-options:         -stubdir stub -o libbrassica-interop.so -dynamic -shared -fPIC -fPIE -flink-rts -Wall
  hs-source-dirs:      src
  exposed-modules:     BrassicaInterop
  build-depends:       base >= 4.7 && < 5
                     , brassica
                     , bytestring
                     , utf8-string >= 1.0 && < 1.1
  default-language:    Haskell2010

On GHC 9.2.5, this works without a problem. However, on upgrading to GHC 9.4.5, it gives the following error:

$ cabal build brassica-interop
Resolving dependencies...
Build profile: -w ghc-9.4.5 -O1
In order, the following will be built (use -v for more details):
 - brassica-interop-0.0.3 (lib) (first run)
Preprocessing library for brassica-interop-0.0.3..
Building library for brassica-interop-0.0.3..

when making flags consistent: warning:
    -dynamic-too is ignored when using -dynamic
[2 of 2] Linking libbrassica-interop.so [Flags changed]
/usr/bin/ld.gold: error: cannot open /<omitted>/brassica/dist-newstyle/build/x86_64-linux/ghc-9.4.5/brassica-interop-0.0.3/build/BrassicaInterop.dyn_o: No such file or directory
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)
Error: cabal: Failed to build brassica-interop-0.0.3.

I have no idea what’s happening here, or how to fix it. Does anyone have any ideas?

(Rereading the GHC User’s Guide, I saw it mention the --enable-shared Cabal option… alas, cabal build brassica-interop --enable-shared gives exactly the same result. However, cabal build brassica-interop --with-compiler=ghc-9.2.5 works, as mentioned above.)

1 Like

On further investigation, I get this error with GHC 9.4.1, but not 9.2.8… which is odd, since the 9.4.1 release notes make no mention of any changes to dynamic or shared library support. Furthermore, it looks like both GHC versions have the -dynamic-too flag, but the warning quoted above (about ignoring it in the presence of -dynamic) only gets emitted when I use GHC 9.4.1.

This last point made me suspect a Cabal issue. I tried running with cabal -v and comparing the respective GHC invocations themselves, but it looks like GHC always gets supplied the same arguments (modulo version number/hash changes). At this point I’m pretty much completely stumped… how could a different GHC version possibly break this, when the relevant functionality appears not to have changed in that new version?