logos-delivery/nix/default.nix
osmaczko 5034086fef
Chore/make nix build phase configurable (#3826)
* nix: parameterize build flags with named args

Expose `enablePostgres`, `enableNimDebugDlOpen`, and `chroniclesLogLevel`
as arguments on `nix/default.nix`. Defaults preserve today's hardcoded
behavior, so `nix build .#liblogosdelivery` with no overrides is a
no-op change.

Consume the package via `callPackage` in `flake.nix` so consumers can
use `.override { ... }` without extra wrapping.

* nix: link libstdc++ on Linux so consumers don't need patchelf

Append `stdenv.cc.cc.lib` to `buildInputs` on Linux and add `-lstdc++`
to the Nim `--passL` flags. Nix stdenv's fixupPhase will auto-inject
`${stdenv.cc.cc.lib}/lib` into the output's RUNPATH, so downstream
consumers can drop their patchelf step.

macOS resolves the C++ stdlib via dyld/libc++ and is unaffected.

* nix: bundle librln into the output for a self-contained package

Copy the librln shared library (`librln.so` / `librln.dylib`) from the
zerokit input into `$out/lib` and rewrite the internal reference in
`liblogosdelivery`:

- Darwin: set librln's install name to `@rpath/librln.dylib`, change the
  consumer's reference to match, and add `@loader_path` as an rpath.
- Linux: add `$ORIGIN` to the rpath so `librln.so` resolves from the
  sibling directory, preserving the gcc-lib entry injected by the stdenv
  fixupPhase for libstdc++.

The installed `liblogosdelivery` no longer carries a `/nix/store/...`
absolute path to zerokit, so downstream consumers can ship the bundle
as-is.
2026-04-27 12:51:39 +02:00

137 lines
4.6 KiB
Nix

{ pkgs
, src
, zerokitRln
, enablePostgres ? true
, enableNimDebugDlOpen ? true
, chroniclesLogLevel ? null
}:
let
deps = import ./deps.nix { inherit pkgs; };
nimDefineArgs = pkgs.lib.concatStringsSep " \\\n " (
[ "--define:disable_libbacktrace" ]
++ pkgs.lib.optional enablePostgres "--define:postgres"
++ pkgs.lib.optional enableNimDebugDlOpen "--define:nimDebugDlOpen"
++ pkgs.lib.optional (chroniclesLogLevel != null)
"--define:chronicles_log_level=${toString chroniclesLogLevel}"
);
# nat_traversal is excluded from the static pathArgs; it is handled
# separately in buildPhase (its bundled C libs must be compiled first).
otherDeps = builtins.removeAttrs deps [ "nat_traversal" ];
# Some packages (e.g. regex, unicodedb) put their .nim files under src/
# while others use the repo root. Pass both so the compiler finds either layout.
pathArgs =
builtins.concatStringsSep " "
(builtins.concatMap (p: [ "--path:${p}" "--path:${p}/src" ])
(builtins.attrValues otherDeps));
libExt =
if pkgs.stdenv.hostPlatform.isWindows then "dll"
else if pkgs.stdenv.hostPlatform.isDarwin then "dylib"
else "so";
in
pkgs.stdenv.mkDerivation {
pname = "liblogosdelivery";
version = "dev";
inherit src;
nativeBuildInputs = with pkgs; [
nim-2_2
git
gnumake
which
] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.darwin.cctools ];
buildInputs = [ zerokitRln ]
++ pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.stdenv.cc.cc.lib ];
buildPhase = ''
export HOME=$TMPDIR
export XDG_CACHE_HOME=$TMPDIR/.cache
export NIMBLE_DIR=$TMPDIR/.nimble
export NIMCACHE=$TMPDIR/nimcache
mkdir -p build $NIMCACHE
# nat_traversal bundles C sub-libraries that must be compiled before linking.
# Copy the fetchgit store path to a writable tmpdir, build, then pass to nim.
NAT_TRAV=$TMPDIR/nat_traversal
cp -r ${deps.nat_traversal} $NAT_TRAV
chmod -R +w $NAT_TRAV
make -C $NAT_TRAV/vendor/miniupnp/miniupnpc \
CFLAGS="-Os -fPIC" build/libminiupnpc.a
make -C $NAT_TRAV/vendor/libnatpmp-upstream \
CFLAGS="-Wall -Os -fPIC -DENABLE_STRNATPMPERR -DNATPMP_MAX_RETRIES=4" libnatpmp.a
echo "== Building liblogosdelivery (dynamic) =="
nim c \
--noNimblePath \
${pathArgs} \
--path:$NAT_TRAV \
--path:$NAT_TRAV/src \
--passL:"-L${zerokitRln}/lib -lrln${pkgs.lib.optionalString pkgs.stdenv.isLinux " -lstdc++"}" \
${nimDefineArgs} \
--out:build/liblogosdelivery.${libExt} \
--app:lib \
--threads:on \
--opt:size \
--noMain \
--mm:refc \
--header \
--nimMainPrefix:liblogosdelivery \
--nimcache:$NIMCACHE \
liblogosdelivery/liblogosdelivery.nim
echo "== Building liblogosdelivery (static) =="
nim c \
--noNimblePath \
${pathArgs} \
--path:$NAT_TRAV \
--path:$NAT_TRAV/src \
--passL:"-L${zerokitRln}/lib -lrln${pkgs.lib.optionalString pkgs.stdenv.isLinux " -lstdc++"}" \
${nimDefineArgs} \
--out:build/liblogosdelivery.a \
--app:staticlib \
--threads:on \
--opt:size \
--noMain \
--mm:refc \
--nimMainPrefix:liblogosdelivery \
--nimcache:$NIMCACHE \
liblogosdelivery/liblogosdelivery.nim
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib $out/include
cp build/liblogosdelivery.${libExt} $out/lib/ 2>/dev/null || true
cp build/liblogosdelivery.a $out/lib/ 2>/dev/null || true
cp liblogosdelivery/liblogosdelivery.h $out/include/ 2>/dev/null || true
runHook postInstall
'';
# Bundle librln alongside liblogosdelivery so the output is self-contained.
# Use --add-rpath (not --set-rpath) so fixupPhase's stdenv RUNPATH injection
# for libstdc++ is preserved.
postInstall =
pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
cp ${zerokitRln}/lib/librln.dylib $out/lib/
chmod +w $out/lib/librln.dylib $out/lib/liblogosdelivery.dylib
install_name_tool -id @rpath/liblogosdelivery.dylib $out/lib/liblogosdelivery.dylib
install_name_tool -id @rpath/librln.dylib $out/lib/librln.dylib
old=$(otool -L $out/lib/liblogosdelivery.dylib | awk 'NR>1{print $1}' | grep librln)
install_name_tool -change "$old" @rpath/librln.dylib $out/lib/liblogosdelivery.dylib
install_name_tool -add_rpath @loader_path $out/lib/liblogosdelivery.dylib
''
+ pkgs.lib.optionalString pkgs.stdenv.isLinux ''
cp ${zerokitRln}/lib/librln.so $out/lib/
patchelf --add-rpath '$ORIGIN' $out/lib/liblogosdelivery.so
'';
}