[Haskell-cafe] Haskell plugin dynamic linking issue

Lana Black lanablack at amok.cc
Tue Apr 11 07:20:38 UTC 2017


On 10/04/17 22:46, Albert Y. C. Lai wrote:
> I am surprised that at this point you did not receive the warning I
> received:
> 
> 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.

Thank you for this suggestion. Now things start to get rather strange. I
have changed the cabal file accordingly [1]. When I run cabal configure,
I get the following error:

> cabal configure
Resolving dependencies...
Configuring cabal-bug-0.1...
cabal: Missing dependency on a foreign library:
* Missing C library: HSrts-ghc8.0.2
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.

However, that doesn't prevent cabal build from succeeding, and now I
have a shared library linked to RTS.

> cabal build
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 )

> ldd dist/build/libHScabal-bug-0.1-50NTk4EdDNe8utEsR21Nft-ghc8.0.2.so
	linux-vdso.so.1 (0x00007ffea75c9000)
	libHSrts-ghc8.0.2.so => /usr/lib64/ghc-8.0.2/rts/libHSrts-ghc8.0.2.so
(0x00007f8057193000)
	libHSbase-4.9.1.0-ghc8.0.2.so =>
/usr/lib64/ghc-8.0.2/base-4.9.1.0/libHSbase-4.9.1.0-ghc8.0.2.so
(0x00007f8056589000)
	libHSinteger-gmp-1.0.0.1-ghc8.0.2.so =>
/usr/lib64/ghc-8.0.2/integer-gmp-1.0.0.1/libHSinteger-gmp-1.0.0.1-ghc8.0.2.so
(0x00007f8056353000)
	libHSghc-prim-0.5.0.0-ghc8.0.2.so =>
/usr/lib64/ghc-8.0.2/ghc-prim-0.5.0.0/libHSghc-prim-0.5.0.0-ghc8.0.2.so
(0x00007f8055f68000)
	libgmp.so.10 => /usr/lib64/libgmp.so.10 (0x00007f8055cca000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f80559c7000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f805562e000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f8055425000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f8055221000)
	libffi.so.6 => /usr/lib64/libffi.so.6 (0x00007f8055018000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8054dfb000)
	/lib64/ld-linux-x86-64.so.2 (0x000056212e051000)

However, if I run cabal build without calling cabal configure first, the
latter fails and the build process is stopped at that point. This also
prevents me from building my project with stack.

>> 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).

Thanks for this explanation.

> 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?

Yes, I'm aware of this. The real code in question has calls to hs_init()
and hs_exit(). All I'm trying to do now is to solve the linking problem.

[1]: https://github.com/greydot/cabal-bug/blob/extra-lib/cabal-bug.cabal



More information about the Haskell-Cafe mailing list