Search code examples
haskellffihaskell-stack

Haskell FFI: Missing (or bad) C library


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

Solution

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