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);
}