Cabal foreign libraries
In this age of the
stack domination, not everyone remembers the role of
Cabal and cabal-install`. And still cabal and cabal-install do progress and introduce new features, that may benefit entire ecosystem. And it’s quite unfortunate that some of the changes remain unnoticed.
The big list of changes in Cabal-2.0 can be found here. In this post I’d like to look into one single change: Foreign libraries support.
TLDR: you can find all documentation in the cabal user-guide, which is a very good resource to read anyway.
Let’s look into the problem solved by this feature. Sometimes we need to use Haskell in projects written in other language. This can be done either by making an Haskell executable and using some RPC to communicate between different components or by making a shared object. For a long time cabal did not support shared objects definition. Common solution for that problem was to create an
executable section in cabal file, add
-shared and then play games with
-fPIC support. That solution was doable but painfull and required knowledge of low level details.
And finally in cabal-2.0 a support for that usecase was introduced. Now we have a new stanza,
foreign-library which means that
Cabal will build a standalone library to be used with foreign languages.
foreign-library block we can define
type of the library:
native-staticfor static library (
native-sharedfor the dynamic library (
native-shared are supported.
If you are using windows you should remember to add
options: standlone stanza. With this option
libHSrts will not be required. You should not set this option otherwise.
A simple example:
foreign-library mylib type: native-shared lib-version-info: 6:3:2 build-depends: base >=4.9 && <4.10 hs-source-dirs: src other-modules Lib default-language: Haskell2010
If you have foreign exported modules, then you should also provide:
library build-depends: base >= 4.9 && <4.10 hs-source-dirs: src other-modules: Lib install-includes: Lib_stub.h default-language: Haskell2010
Lib_stub.h so header file will be installed in the system. See #5299. This workaround helps with the problem but still you will not be able to call
cabal sdist because it will try to copy autogenerated file that does not exist in filesystem.
cabal install you’ll get:
~/.cabal/ ~//cabal/libmylib.so -> libmylib.so.4.2.3 ~/.cabal/libmylib.so.4 -> libmylib.so.4.2.3 ~/.cabal/libmylib.so.4.2.3 ~/.cabal/lib/x86_64-linux-ghc-8.0.2/foreign-0.1.0.0-22cwmsmBVpIHoSDwDYFUR6/include/Lib_stub.h
Update: problem with
sdist can be worked around by using a buildinfo trick
foreign.buildinfofile with the following contents:
add section to cabal:
install-includesstanza - now sdist works.
comments powered by Disqus