GSL dependency cblas in nix flake

I tried to investigate a bit, I don’t know why it works with gcc which includes a dynamic link to libgslcblas.so.0 (containing cblas_ctrmv) while zig does not,
even tough pkg-config --cflags --libs gsl does return:

-I/nix/store/yggzrbj04jg5mr34g2v83zmaw6sk2lwd-gsl-2.8-dev/include
-L/nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib
-lgsl -lgslcblas -lm

GCC

$ nix -L build .#test-gcc
[…]
@nix { "action": "setPhase", "phase": "buildPhase" }
++ mkdir -p /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin
+++ pkg-config --cflags --libs gsl
++ gcc main.c -o /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin/test-gcc -I/nix/store/yggzrbj04jg5mr34g2v83zmaw6sk2lwd-gsl-2.8-dev/include -L/nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib -lgsl -lgslcblas -lm
++ set +x
Running phase: installPhase
@nix { "action": "setPhase", "phase": "installPhase" }
no Makefile or custom installPhase, doing nothing
++++ grep RUNPATH
++++ readelf -d /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin/test-gcc
 0x000000000000001d (RUNPATH)            Library runpath: [/nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/lib:/nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib:/nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib:/nix/store/mhd0rk497xm0xnip7262xdw9bylvzh99-gcc-13.3.0-lib/lib]
++++ lddtree /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin/test-gcc
/nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin/test-gcc (interpreter => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/ld-linux-x86-64.so.2)
    libgsl.so.28 => /nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib/libgsl.so.28
    libgslcblas.so.0 => /nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib/libgslcblas.so.0
    libm.so.6 => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libm.so.6
    libc.so.6 => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libc.so.6
++++ set +x
Running phase: fixupPhase
@nix { "action": "setPhase", "phase": "fixupPhase" }
shrinking RPATHs of ELF executables and libraries in /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc
shrinking /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin/test-gcc
checking for references to /build/ in /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc...
patching script interpreter paths in /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc
stripping (with command strip and flags -S -p) in  /nix/store/jqg6f90qia0p1nxg0qh664j8018kvfby-test-gcc/bin
$ nix -L run .#test-gcc
Area betweeen [-1.96, 1.96]: 0.950004

Zig

$ nix -L build .#test-zig
[…]
@nix { "action": "setPhase", "phase": "buildPhase" }
++ export ZIG_GLOBAL_CACHE_DIR=/build/69fw0gijinr109dfcwg9zcz7099dil57-source
++ ZIG_GLOBAL_CACHE_DIR=/build/69fw0gijinr109dfcwg9zcz7099dil57-source
++ mkdir -p /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin
+++ pkg-config --cflags --libs gsl
++ zig build-exe main.c -femit-bin=/nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin/test-zig -I/nix/store/yggzrbj04jg5mr34g2v83zmaw6sk2lwd-gsl-2.8-dev/include -L/nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib -lgsl -lgslcblas -lm
++ set +x
Running phase: installPhase
@nix { "action": "setPhase", "phase": "installPhase" }
no Makefile or custom installPhase, doing nothing
++++ grep RUNPATH
++++ readelf -d /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin/test-zig
 0x000000000000001d (RUNPATH)            Library runpath: [/nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib:/nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/lib:/nix/store/lrz0729rrid6p4lsfpj0d1mlamzzrlhr-python3-3.12.8-env/lib]
++++ lddtree /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin/test-zig
/nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin/test-zig (interpreter => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/ld-linux-x86-64.so.2)
    libgsl.so.28 => /nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib/libgsl.so.28
        libm.so.6 => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libm.so.6
    libc.so.6 => /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libc.so.6
++++ set +x
Running phase: fixupPhase
@nix { "action": "setPhase", "phase": "fixupPhase" }
shrinking RPATHs of ELF executables and libraries in /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig
shrinking /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin/test-zig
checking for references to /build/ in /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig...
patching script interpreter paths in /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig
stripping (with command strip and flags -S -p) in  /nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin
$ nix -L run .#test-zig
/nix/store/6all27vywm3h7256bkfgbcbc3g1hlb4c-test-zig/bin/test-zig:
symbol lookup error: /nix/store/988nciljvk1p8y9byarjxd6ygf3fc7i1-gsl-2.8/lib/libgsl.so.28:
undefined symbol: cblas_ctrmv

flake.nix

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    flake-utils.url = "github:numtide/flake-utils";
    #zig-overlay.url = "github:mitchellh/zig-overlay";
    #zig2nix.url = "github:Cloudef/zig2nix";
    #zig2nix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = inputs:
    inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
      let
        pkgs = import inputs.nixpkgs { inherit system; };
        zig = pkgs.zig;
        #zig = inputs.zig-overlay.packages.${system}.master;
        # Wrap binary package zig on linux so /usr/bin/env can be found inside a sandbox
        zigBin =
          pkgs.writeScriptBin "zig" ''
            args=()
            for d in /*; do
              args+=("--dev-bind" "$d" "$d")
            done
            ${pkgs.bubblewrap}/bin/bwrap "''${args[@]}" \
              --bind ${pkgs.coreutils} /usr \
              -- ${pkgs.lib.getExe zig} "$@"
          '';
        postInstall = ''
          set -x
          readelf -d $out/bin/test-* | grep RUNPATH
          lddtree $out/bin/test-*
          set +x
        '';
      in
      {
        packages.test-zig = pkgs.stdenv.mkDerivation {
          name = "test-zig";
          src = ./.;
          buildInputs = [ zigBin pkgs.gsl pkgs.pkg-config pkgs.llvmPackages.bintools pkgs.pax-utils pkgs.binutils ];
          buildPhase = ''
            set -x
            export ZIG_GLOBAL_CACHE_DIR=$PWD
            mkdir -p $out/bin
            zig build-exe main.c -femit-bin=$out/bin/test-zig $(pkg-config --cflags --libs gsl)
            set +x
          '';
          inherit postInstall;
        };
        packages.test-gcc = pkgs.stdenv.mkDerivation {
          name = "test-gcc";
          src = ./.;
          buildInputs = [ pkgs.gsl pkgs.pkg-config pkgs.pax-utils pkgs.binutils ];
          buildPhase = ''
            set -x
            mkdir -p $out/bin
            gcc main.c -o $out/bin/test-gcc $(pkg-config --cflags --libs gsl)
            set +x
          '';
          inherit postInstall;
        };
        devShells.default = pkgs.mkShell {
          packages = [
            zig
            pkgs.gsl
            #pkgs.blas
            pkgs.pkg-config
          ];
        };
      });
}

main.c

#include <gsl/gsl_cdf.h>
#include <stdio.h>

int main(){
    double bottom_tail = gsl_cdf_gaussian_P(-1.96, 1);
    printf("Area betweeen [-1.96, 1.96]: %g\n", 1 - 2*bottom_tail);
}
1 Like