Search code examples
haskellcabalnix

Finding foreign library with cabal using nix-shell


I have a similar problem to: Cabal can't find foreign library when building on NixOS

Basically I'm using cabal2nix to generate from a package.yaml containing:

extra-libraries:
  - libmnl

This produces a cabal.nix file:

{ mkDerivation, base, bytestring, cereal, containers, hpack
, iproute, lens, libmnl, netlink, primitive
, resourcet, safe-exceptions, stdenv, transformers
}:
mkDerivation {
  pname = "relay";
  version = "0.1.0.0";
  src = ./.;
  libraryHaskellDepends = [
    base bytestring cereal containers iproute lens netlink
    primitive resourcet safe-exceptions transformers
  ];
  librarySystemDepends = [ libmnl ];
  libraryToolDepends = [ hpack ];
  testHaskellDepends = [
    base bytestring cereal containers iproute lens netlink
    primitive resourcet safe-exceptions transformers
  ];
  testSystemDepends = [ libmnl ];
  preConfigure = "hpack";
  homepage = "https://github.com/MatrixAI/Relay#readme";
  license = stdenv.lib.licenses.asl20;
}

If I enter into this via nix-shell, and run cabal configure. It complains that it cannot find libmnl:

Resolving dependencies...
Configuring relay-0.1.0.0...
cabal: Missing dependency on a foreign library:
* Missing (or bad) C library: libmnl
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.

Also running gcc -c test.c -lmnl on this file inside nix-shell works:

#include <libmnl/libmnl.h>

int main() { return 0; }

So why is cabal failing to find libmnl but gcc can easily find it in the nix-shell.

When running with -v3 it appears to try to link to -llibmnl. But the proper linking should be -lmnl. This seems very problematic, is there a way to tell cabal to be linking with the flag -lmnl, not -llibmnl?

I've found that if I edit the Cabal file and change extra-libraries to point to mnl instead of libmnl, it then works by changing how Cabal tries to link. However the cabal2nix then when taking package.yaml generates libmnl which is the correct package attribute from Nix. It appears that extra-libraries should be mnl whereas the cabal.nix should be libmnl.


Solution

  • Basically the the extra-libraries need to be using mnl not libmnl. Then when using cabal2nix, it needs to map libmnl package to the mnl attribute. This was solved with upstream cabal2nix mapping mnl to libmnl commit: https://github.com/NixOS/cabal2nix/issues/413#event-2257811946