dhall-lang / dhall-haskell

Maintainable configuration files
https://dhall-lang.org/
BSD 3-Clause "New" or "Revised" License
908 stars 211 forks source link

building static binary with nix fails with dhall #2484

Closed zoranbosnjak closed 1 year ago

zoranbosnjak commented 1 year ago

A test project fails to build under nix when both:

The static build is fine without dhall dependency (that is, when dhall is removed from .cabal file). Also, a normal (non-static) build is OK, even with dhall dependency present.

Environment

$ nix-channel --update
unpacking channels...
$ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.version'
"23.05pre448426.6b9c27b4c9c"
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.5 LTS"
$ nix --version
nix (Nix) 2.13.2

Steps to reproduce

$ cd dhalltest
$ nix-build --arg static true
...
Building executable 'dhalltest' for dhalltest-0.1.0..
[1 of 1] Compiling Main             ( app/Main.hs, dist/build/dhalltest/dhalltest-tmp/Main.o )
Linking dist/build/dhalltest/dhalltest ...
/nix/store/dbgdbpda30rscjlps73glkgz3w8gqszp-binutils-2.39/bin/ld: cannot find -ltinfo: No such file or directory
collect2: error: ld returned 1 exit status
`cc' failed in phase `Linker'. (Exit code: 1)
error: builder for '/nix/store/pai01vf9y7w7iibxzjbba51qfqm59ql8-dhalltest-0.1.0.drv' failed with exit code 1

Test project structure

$ tree ../dhalltest/
../dhalltest/
├── app
│   └── Main.hs
├── default.nix
└── dhalltest.cabal
-- app/Main.hs
module Main where

main :: IO ()
main = putStrLn "Hello, Haskell!"
# default.nix
{ nixpkgs ? import <nixpkgs> {}
, strip ? true
, static ? false    # build static binary
}:

let
  pkgs = if static == true
    then nixpkgs.pkgsMusl.pkgsMusl
    else nixpkgs;
  haskellPackages = pkgs.haskellPackages;
  drv2 = haskellPackages.callCabal2nix "dhalltest" ./. { };
  drv = if static == true
    then drv2.overrideDerivation (oldAttrs: {
      configureFlags = [
        "--ghc-option=-optl=-static"
        "--disable-shared"
        "--extra-lib-dirs=${pkgs.gmp6.override { withStatic = true; }}/lib"
        "--extra-lib-dirs=${pkgs.zlib.static}/lib"
        "--extra-lib-dirs=${pkgs.libffi.overrideAttrs (old: { dontDisableStatic = true; })}/lib"
        ] ++ pkgs.lib.optionals (!strip) [
          "--disable-executable-stripping"
        ];
      })
    else drv2;
in drv
-- dhalltest.cabal
cabal-version:      2.4
name:               dhalltest
version:            0.1.0

executable dhalltest
    main-is:          Main.hs
    hs-source-dirs:   app
    default-language: Haskell2010
    build-depends:
        base
        , dhall
TristanCacqueray commented 1 year ago

It looks like you are missing extra libs in the configureFlags: https://github.com/dhall-lang/dhall-haskell/blob/849f3d1f8d0ad342f984ecbbc5b4a9bca9a9b37e/nix/shared.nix#L291-L295 e.g. a static ncurses is needed for tinfo.

zoranbosnjak commented 1 year ago

Thanks for the tip. The following additional ncurses line is required in the configureFlags:

         "--disable-shared"
+        "--extra-lib-dirs=${pkgs.ncurses.override { enableStatic = true; }}/lib"
         "--extra-lib-dirs=${pkgs.gmp6.override { withStatic = true; }}/lib"

The enableShared argument is not recognized and has to be omitted.