[Haskell-cafe] Haskell plugin dynamic linking issue

Albert Y. C. Lai trebla at vex.net
Mon Apr 10 22:46:45 UTC 2017

On 2017-04-10 04:58 PM, Lana Black wrote:
> ~/devel/hs/cabal-bug> cabal build
> Package has never been configured. Configuring with default flags. If this
> fails, please run configure manually.
> Resolving dependencies...
> Configuring cabal-bug-0.1...

I am surprised that at this point you did not receive the warning I 

Warning: Instead of 'ghc-options: -lHSrts-ghc8.0.2' use 
'extra-libraries: HSrts-ghc8.0.2'

In my http://www.vex.net/~trebla/haskell/so.xhtml I use the 
extra-libraries route (and build-type: Configure to automate "8.0.2"). 
Also I do not use ghc-options, see below.

> Building cabal-bug-0.1...
> Preprocessing library cabal-bug-0.1...
> [1 of 1] Compiling Cabal.Bug        ( src/Cabal/Bug.hs,
> dist/build/Cabal/Bug.o )
> Linking a.out ...

This a.out is not an executable. It is a shared library. The name 
"a.out" is a historical generic bland default name for any linker output 
whenever the user fails to specify "-o realname". Linker output could be 
executable or library depending on other flags.

Now to see why this a.out exists at all, you really should use "cabal 
build -v" to see how cabal uses GHC. But the short story is:

cabal calls GHC at least 3 times:

1st time is to compile *.hs files to *.o files, e.g., Bug.hs to Bug.o. 
(If you have multiple *.hs files, it is still one call, and you also see 
a -j2 or -j4 or -j65536 according to your number of CPU cores to tell 
GHC to parallelize.)

2nd time is to produce the *.a library.

3rd time is to produce the *.so library.

Now, if you hardcode the blunt sledgehammer that is ghc-options: -fPIC 
-dynamic -shared, as opposed to letting cabal do it at the right times 
(namely, -shared during the 3rd time only), then the extraneous -shared 
during the 1st time, which is supposed to be *.o only, tricks GHC into 
calling the linker to produce an extraneous *.so (except there is no -o 
so the name comes out as a.out).

But do not think that you can declare victory now and take this a.out 
and get away with it.

For all practical purposes you will need to include some C code in the 
library. See again my article for why. But the short story is: Who's 
gonna call hs_init?

The 1st call to GHC does not mention the C code whatsoever. The a.out 
thus produced will be missing the C code. It is incomplete.

There are extra calls after the 1st and before the 2nd to compile *.c to 

Only by the 3rd call are all *.o files, from both Haskell and C, brought 
together into a complete *.so. (Well, the 2nd call too, but you are not 
going after the *.a.)

More information about the Haskell-Cafe mailing list