I am trying to bind to a C library in Haskell, using the FFI, but am getting "Missing (or bad) C library".
I am using Haskell Tool Stack 2.7.3 on Ubuntu Linux. I have made a minimal reproducible example as follows.
Here is the error message when I run stack build
:
Building all executables for `c' once. After a successful build of all of them, only specified executables will be rebuilt.
c> configure (lib + exe)
Configuring c-0.0.0...
Cabal-simple_mPHDZzAJ_3.2.1.0_ghc-8.10.7: Missing dependency on a foreign
library:
* Missing (or bad) C library: small
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.If the
library file does exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.
-- While building package c-0.0.0 (scroll up to its section to see the error) using:
/home/t/.stack/setup-exe-cache/x86_64-linux-tinfo6/Cabal-simple_mPHDZzAJ_3.2.1.0_ghc-8.10.7 --builddir=.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.2.1.0 configure --user --package-db=clear --package-db=global --package-db=/home/t/.stack/snapshots/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/pkgdb --package-db=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/pkgdb --libdir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/lib --bindir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/bin --datadir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/share --libexecdir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/libexec --sysconfdir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/etc --docdir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/doc/c-0.0.0 --htmldir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/doc/c-0.0.0 --haddockdir=/home/t/c/.stack-work/install/x86_64-linux-tinfo6/789c3ce353623de67e3141c688e7a5c70e1e6d9a517056f87d6850c406d11f12/8.10.7/doc/c-0.0.0 --dependency=base=base-4.14.3.0 --extra-include-dirs=/home/t/c/src --extra-lib-dirs=/home/t/c/src --exact-configuration --ghc-option=-fhide-source-paths
Process exited with code: ExitFailure 1
My package.yaml
file:
name: c
dependencies:
- base >= 4.7 && < 5
library:
source-dirs: src
extra-libraries: small
executables:
c-exe:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- c
The src/Lib.hs
file with the bindings in it:
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CApiFFI #-}
module Lib
( x
) where
import qualified Foreign.C.Types as F
foreign import capi "small.h x" x :: IO F.CInt
The src/small.c
file:
#include "small.h"
int x() {
return 0;
}
The src/small.h
file:
int x();
I compiled the C
code first with:
gcc -c -o src/small.o src/small.c
My stack.yaml
file:
resolver:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/20.yaml
extra-include-dirs:
- src
extra-lib-dirs:
- src
For convenience I have put this minimal example on Github:
git clone https://github.com/8n8/haskell-c-ffi-minimal
cd haskell-c-ffi-minimal
stack build
In the package.yaml
file, in the library
section, change it to
library:
source-dirs: src
c-sources:
- src/small.c
and the stack.yaml
file can be reduced to
resolver:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/20.yaml
and there is no need to do a separate step to compile the C
code.