Fil-C on Nix

Filnix wiki

mbrock/filnix

ports.nix

Fil-C package ports - list-based structure

Each port: (for pkgs.package [transforms...])
Explicit names: { bash = for pkgs.bash [...]; }

λpkgs, prev, final
let
12inherit import./ports inherit pkgs lib pkgs;
for arg use pin src broken markAsNotNecessarilyInsecure skipTests skipCheck parallelize serialize tool link patch skipPatch removeCFlag addCFlag removeCMakeFlag addCMakeFlag addMakeFlag removeMakeFlag addMesonFlag removeMesonFlag configure removeConfigureFlag wip astRewrite github gnu gnuTarGz

Nixpkgs' Bash patches use -p0; the pinned importer emits -p1 paths. Apply our unwind buffer fix separately without changing their strip level.

47bashUnwindPatch=
λold
48postPatch=
old.postPatch or ""
uses use

For programs that dlopen() optional libraries by soname and declare them in .note.dlopen ELF notes (systemd, kbd). Natively the notes make autoPatchelfHook add the libraries to RUNPATH. Under Fil-C neither half works: section() on globals is dropped, so there are no notes, and Fil-C's dlopen() does not search the caller's RUNPATH (docs/filc-findings.md). So rewrite every soname literal in the source that a build input provides to its absolute path, and put the notes back (they then carry the same paths), since make-initrd-ng reads them to copy a binary's dlopen()ed libraries into the initrd.

62dlopenByPath=
λold
63postPatch=
old.postPatch or ""
+
for soname in $(grep -rhoE '"lib[A-Za-z0-9_+-]+\.so\.[0-9.]+"' src | tr -d '"' | sort -u); do
for dir in ${toStringmapp: "${p.lib or p.out or p}/lib" old.buildInputs}; do
if [ -e "$dir/$soname" ]; then
grep -rlF "\"$soname\"" src | xargs sed -i "s|\"$soname\"|\"$dir/$soname\"|g"
echo "dlopen: $soname -> $dir/$soname"
break
fi
done
done
76postFixup=
old.postFixup or ""
+
for output in $(getAllOutputNames); do
${pkgs.buildPackages.python3.interpreter} ${./ports/restore-dlopen-notes.py} \
${pkgs.buildPackages.binutils-unwrapped}/bin/objcopy "''${!output}"
done
uses use

Mozilla's root store from NSS 3.131.1, which removes the emSign roots behind the October 2026 eMudhra key compromise (emSign ECC Root CA - G3, emSign Root CA - C1 and emSign ECC Root CA - C3). Used for cacert; the NSS port's libnssckbi is p11-kit's trust module, which reads the host's trust store at runtime instead of compiled-in roots.

89nssCertdata=
pkgs.fetchurl
90urls=
"https://hg-edge.mozilla.org/projects/nss/raw-file/NSS_3_131_1_RTM/lib/ckfw/builtins/certdata.txt" "https://raw.githubusercontent.com/nss-dev/nss/refs/tags/NSS_3_131_1_RTM/lib/ckfw/builtins/certdata.txt"
94hash=
"sha256-PsK00kDcEsdH6vRQBh24SvdXxIO72jAvninOtdcL5RA="

The build platform's guile, to compile Scheme modules to .go files (the bytecode is the same). As an input it would propagate its native libunistring and libgc onto the Fil-C link path, so only its programs are exposed.

101guileForBuild=
pkgs.runCommand"guile-for-build" { }
mkdir -p $out/bin
ln -s ${pkgs.buildPackages.guile_3_0}/bin/* $out/bin/

The Fil-C guile, for builds that must load Fil-C extensions or run tests with it at build time. It runs on the build machine.

108filcGuileForBuild=
pkgs.runCommand"filc-guile-for-build" { }
mkdir -p $out/bin
ln -s ${final.guile_3_0}/bin/* $out/bin/

Guile libraries whose tests load Fil-C code (their own extension or a C library through the FFI) must run them with the Fil-C guile; Nixpkgs' cross build would use the build platform's.

116guileTestsOnFilc=
λold
117preCheck=
old.preCheck or ""
+
export PATH=${final.guile_3_0}/bin:$PATH
for f in pre-inst-env pre-inst-guile; do
if [ -f $f ]; then
substituteInPlace $f --replace-quiet \
${pkgs.buildPackages.guile_3_0}/bin/guile ${final.guile_3_0}/bin/guile
fi
done
126checkFlags=
old.checkFlags or [ ] ++ "GUILE=${final.guile_3_0}/bin/guile"
uses use
131fftwPort=
λold
138nativeBuildInputs=
builtins.filterdep: ¬pkgs.lib.hasInfix"gfortran" dep.name or "" old.nativeBuildInputs

Nixpkgs adds LLVM's OpenMP when the compiler is Clang.

142buildInputs=
builtins.filterdep: ¬pkgs.lib.hasInfix"openmp" dep.name or "" old.buildInputs or [ ]
145configureFlags=
builtins.filterf: ¬builtins.elemf "--enable-openmp" "--enable-avx512" old.configureFlags
++
"--disable-fortran"
"--disable-openmp"

Fil-C does not yet lower AVX-512 gather intrinsics.

"--disable-avx512"
159doCheck=
true
uses use
in
import./ports/pipewire-consumers.nix inherit pkgs prev final;
import./ports/media.nix inherit pkgs;
import./ports/tpm2.nix inherit pkgs final;

Core Libraries

let
172boostPort=
λboost
174boost for boost
patch./ports/patch/boost-filc.patch

1.86's B2 still accepts context-impl from the Context Jamfile.

pkgs.lib.optionalpkgs.lib.versionAtLeastboost.version "1.87" patch./patches/boost-context-feature.patch
patch./patches/boost-gdb-scripts.patch
patch./patches/boost-function-vtable-tag.patch
patch./patches/boost-test-execution-monitor.patch

io_context's executor keeps its context pointer and flag bits in a uintptr_t; the first use_service through a strand trapped.

patch./patches/boost-asio-io-context-executor-pointer.patch
use
λold

error_code keeps its source_location pointer in a uintptr_t with a flag bit, which drops the capability, and what() then trapped (Boost.URL's parse errors in Nix). Keep no location instead.

191postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace boost/system/detail/error_code.hpp --replace-fail \
'( loc? reinterpret_cast<boost::uintptr_t>( loc ): 2 )' '2'
arg

Match upstream pizlix: Context and Coroutine2 use ucontext. The older Coroutine v1 library requires fcontext and is omitted.

202toolset=
"clang"
203extraB2Args=
"context-impl=ucontext" "--without-coroutine"
use
209doCheck=
true
210checkPhase=
runHook preCheck
$CXX -std=c++17 -I. ${./tests/boost-context.cpp} \
-Lstage/lib -Wl,-rpath,"$PWD/stage/lib" -lboost_context -lboost_json -pthread -o boost-check
LD_LIBRARY_PATH="$PWD/stage/lib" ./boost-check
$CXX -std=c++17 -I. ${./tests/boost-continuation.cpp} \
-Lstage/lib -Wl,-rpath,"$PWD/stage/lib" -lboost_context -pthread -o continuation-check
LD_LIBRARY_PATH="$PWD/stage/lib" ./continuation-check
$CXX -std=c++17 -I. ${./tests/boost-asio.cpp} -pthread -o asio-check
./asio-check
$CXX -std=c++17 -I. ${./tests/boost-error-code.cpp} -o error-code-check
./error-code-check
# Boost.Test, both as the compiled library and header-only. The
# module deliberately fails some cases, so compare its summary.
$CXX -std=c++17 -I. -DBOOST_TEST_DYN_LINK ${./tests/boost-test.cpp} \
-Lstage/lib -Wl,-rpath,"$PWD/stage/lib" -lboost_unit_test_framework -o boost-test-check
sed 's|<boost/test/unit_test.hpp>|<boost/test/included/unit_test.hpp>|' \
${./tests/boost-test.cpp} > boost-test-included.cpp
$CXX -std=c++17 -I. boost-test-included.cpp -o boost-test-included-check
for check in ./boost-test-check ./boost-test-included-check; do
status=0
LD_LIBRARY_PATH="$PWD/stage/lib" $check --report_level=short \
--color_output=no > boost-test.log 2>&1 || status=$?
cat boost-test.log
test "$status" = 201
sed -n '/^Test module/,$p' boost-test.log | sed '/^$/d' \
done
runHook postCheck
in
245boost186=
boostPortpkgs.boost186
246boost187=
boostPortpkgs.boost187
let
252icuPort=
λicu patches
254icu for icu
mappatch patches
toolpkgs.autoreconfHook
toolpkgs.pkg-config
use

Nixpkgs unpacks into icu/source; the upstream tree has icu4c/source.

261patchFlags=
"-p3"

ICU disables its upstream suite for cross builds; its "test" target is just a directory. Exercise the real target libraries explicitly.

264doCheck=
true
265checkPhase=
runHook preCheck
$CXX ${./tests/icu.cpp} -Icommon -Ii18n -Llib \
-Wl,-rpath,"$PWD/lib" -licui18n -licuuc -licudata -o icu-check
./icu-check
LD_LIBRARY_PATH="$PWD/lib" ./bin/uconv -V
runHook postCheck
in

abseil-cpp is an alias of this LTS branch, so both names get the port.

298abseil-cpp_202601=
298abseil-cpp_202601

Upstream Fil-C's port: Status, Cord, Mutex and BitGenRef keep pointers in integer words, which drops their capabilities.

patch./ports/patch/abseil-cpp-20260107.1.patch

[[clang::annotate]] in the public headers crashed FilPizlonator in every consumer (protobuf, re2).

patch./patches/abseil-cpp-no-refactor-annotate.patch
let
310protobufPort=
λsourcePatch

Tagged pointers in integer words, byte-wise swaps and inline assembly in the C++ runtime (see the patch headers).

The Fil-C driver rewrites version scripts itself and cannot parse extern "C++" { ... } blocks, so linking libprotobuf aborted. The maps only hide non-protobuf symbols; skip them.

addCMakeFlag"-Dprotobuf_HAVE_LD_VERSION_SCRIPT=OFF"
λold

Fil-C keeps a musttail call only when every pointer argument is the caller's own argument. The table-driven parser advances ptr, so field-to-field tail calls would add a frame per field; PROTOBUF_TAILCALL false makes each field return to the parse loop. Runs after Nixpkgs rewrites this #if for older versions.

324postPatch=
old.postPatch or ""
+
sed -i 's/^\(#if \w*(clang::musttail)\)/\1 \&\& !defined(__FILC__)/' \
src/google/protobuf/port_def.inc
grep -q '(clang::musttail) && !defined(__FILC__)' \
src/google/protobuf/port_def.inc
332randomOrderingTest=
λold

Map salts its integer hash with the table address and rotates the key by its low 6 bits; Fil-C's allocator returns tables with the same low bits, so small maps iterate in a fixed order. Only this statistical check of order randomization fails (4609 others pass in 34.1); iteration order is unspecified either way.

339preCheck=
old.preCheck or ""
+
export GTEST_FILTER=-MapImplTest.RandomOrdering
uses use
in
364mpfr
addCFlag"-DNO_ASM"
use
λold
367postPatch=
old.postPatch or ""
+
# Fil-C aborts and allocation-size traps terminate with SIGTRAP.
substituteInPlace tests/tests.c --replace-fail SIGABRT SIGTRAP
374ada

CMake's env emulator must not replace ctest's target path lookup.

patch./patches/ada-cross-emulator-test.patch
379SDL_compat

Keep the symbol loader out of line: SDL12_compat.c compiles in 30 s, not 873 s (see the patch).

patch./patches/sdl12-symbol-loader.patch

sdl12-compat dlopens SDL2 by bare soname and relies on its RUNPATH, which Fil-C's loader ignores for dlopen (see docs/filc-findings.md). Name the libraries Nix selected, as the sdl2-compat port does for SDL3. (The testver check also needs sdl2-compat's -Bsymbolic-functions.)

use
λold
388postPatch=
old.postPatch or ""
+
substituteInPlace src/SDL12_compat.c \
--replace-fail '"libSDL2-2.0.so.0"' '"${pkgs.lib.getLibfinal.sdl2-compat}/lib/libSDL2-2.0.so.0"' \
--replace-fail '"libX11.so.6"' '"${pkgs.lib.getLibfinal.libx11}/lib/libX11.so.6"'
396smpeg

GTK 2 only serves the gtv demo player; SDL_mixer needs just the library, so keep GTK 2 out of its closure.

useold: buildInputs = builtins.filterdep: ¬pkgs.lib.hasPrefix"gtk+" dep.name or "" old.buildInputs;
configure"--disable-gtk-player"

Nixpkgs links everything with -lX11, which GTK used to provide.

linkfinal.libx11
409oniguruma

Hash keys and values carry pointers; ordinary longs lose capabilities.

patch./patches/oniguruma-pointer-data.patch

Nixpkgs builds minizip from zlib's source with a patch that installs ints.h. minizip needs no Fil-C changes and uses only zlib's public API, so use Nixpkgs' source for both packages.

421minizip
use
423inherit pkgs.zlib
src version
424sourceRoot=
"zlib-${pkgs.zlib.version}/contrib/minizip"
428zlib-ng
pin"2.2.4" "sha256-pzNDwwk+XNxQ2Td5l8OBW4eP0RC/ZRHCx3WfKvuQ9aM="
433openssl=
434openssl-sarcasm=
434openssl-sarcasm for ./ports/openssl-sarcasm.nix
437libev

Replace inline asm mfence with __atomic_thread_fence (Fil-C can't handle inline asm)

use
λattrs
440postPatch=
attrs.postPatch or ""
+
substituteInPlace ev.c \
--replace-fail '#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")' \
'#define ECB_MEMORY_FENCE __atomic_thread_fence(__ATOMIC_SEQ_CST)' \
--replace-fail '#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")' \
'#define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence(__ATOMIC_ACQUIRE)' \
--replace-fail '#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory")' \
'#define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence(__ATOMIC_RELEASE)'

(for pkgs.attr [

(pin "2.5.2" "sha256-Ob9nRS+kHQlIwhl2AQU/SLPXigKTiXNDMqYwmmgMbIc=")
(patch ./ports/patch/attr-2.5.2.patch)

])

461expat
pin"2.7.1" "sha256-NUVSVEuPmQEuUGL31XDsd/FLQSo/9cfY0NrmLA0hfDA="
patch./ports/patch/expat-2.7.1.patch
466nspr

NSPR's x86_64 atomics are hand-written assembly (os_Linux_x86_64.s), which Fil-C cannot assemble or check. Use the __sync builtins, as NSPR already does on loongarch and or1k, and build no .s file.

patch./patches/nspr-filc-atomics.patch
addMakeFlag"PR_MD_ASFILES="

PR_Accept(fd, NULL, ...) passed a length pointer with a null address, which Linux ignores but Fil-C's accept rejects; pass no length.

patch./patches/nspr-null-peer-address.patch

PLArena keeps its addresses as integers and PL_ARENA_ALLOCATE cast them back to pointers, which have no capability under Fil-C; NSS's first arena allocation trapped. Derive them from the arena header.

patch./patches/nspr-arena-pointer-provenance.patch

Nixpkgs runs no tests; NSPR's own suite covers the atomics, threads and loopback I/O (about 100 programs, a few minutes).

use
482doCheck=
true
483checkPhase=
runHook preCheck
make -C pr/tests
(cd pr/tests && ./runtests.sh "$PWD/../../dist")
runHook postCheck
493cacert=
493cacert
use
495version=
"3.131.1"
501nss

The same integer-to-pointer cast as NSPR's arenas, in NSS's arena-zeroing code.

patch./patches/nss-arena-pointer-provenance.patch

freebl's cpuid asm (cache line size for RSA) sets flags without a "cc" clobber, which Fil-C rejects when it runs.

patch./patches/nss-cpuid-cc-clobber.patch

Saved digest state put the context at offset 12, so SHA-256's function pointers lost their capabilities on the way through PK11_CloneContext and every TLS 1.3 handshake trapped. Pad the header.

patch./patches/nss-softoken-state-alignment.patch

The TLS RSA key exchange swaps the real and fake premaster keys with a constant-time XOR mask on the pointers, leaving bare integers.

patch./patches/nss-ssl-cswap-symkey.patch
use
λold

NSS keys its x86-64 assembly and intrinsics (AES-NI, PCLMUL, SHA-NI, AVX2 HACL*, the amd64 bignum and arcfour assembly) on target_arch=="x64". Build for a target NSS does not know, which selects the portable C code, and keep 64-bit words and __int128.

520buildPhase=
builtins.replaceStrings"--target x64" "--target filc -Dhave_int128_support=1" old.buildPhase

pk11_gtest and freebl_gtest initialize large std::vector test-vector tables in one static constructor, which takes Fil-C's pipeline over 20 minutes per file (SROA on the instrumented function). Skip them.

528postPatch=
old.postPatch
+
sed -i -e '/gtests\/pk11_gtest\//d' -e '/gtests\/freebl_gtest\//d' nss.gyp
# selfserv listens on the preferred loopback address for
# "localhost" (::1 where IPv6 is up), but ssl.sh forced tstclnt to
# IPv4 and could never connect; let tstclnt pick the same address.
sed -i 's/tstclnt -4 /tstclnt /' tests/ssl/ssl.sh
# dbtests requires the bigdb key dump to finish in under 5 seconds
# of wall time; under Fil-C on a loaded builder it flakes. Keep the
# check but allow a minute.
sed -i 's/test ''${TIMEARRAY\[0\]} -lt 5/test ''${TIMEARRAY[0]} -lt 60/' \
tests/dbtests/dbtests.sh
grep -q 'TIMEARRAY\[0\]} -lt 60' tests/dbtests/dbtests.sh

Run a subset of NSS's QA suites against the build tree, before installPhase rearranges the output: ciphers, certutil and the cert database, SDR, CRMF, S/MIME, EC, and TLS coverage and client auth. tools.sh (pk12util's cipher matrix, ~800 checks) passed locally but takes over half an hour under Fil-C.

546doCheck=
true
547checkPhase=
runHook preCheck
(
cd tests
export HOST=localhost DOMSUF=localdomain USE_IP=TRUE IP_ADDRESS=localhost
export DIST=$(dirname $out) OBJDIR=$(basename $out)
export OS_ARCH=Linux DLL_PREFIX=lib DLL_SUFFIX=so BUILT_OPT=1 USE_64=1
export TESTDIR=$TMPDIR/nss-tests NSS_CYCLES=standard
export NSS_TESTS="cipher lowhash cert dbtests sdr crmf smime ec ssl"
export NSS_SSL_TESTS=normal_normal NSS_SSL_RUN="cov auth"
./all.sh > $TMPDIR/nss-tests.log 2>&1 || true
)
sed -n '/^Tests summary/,$p' $TMPDIR/nss-tests.log
if ! grep -q '^Failed: *0$' $TMPDIR/nss-tests.log; then
grep -E 'FAILED|Failed' $TMPDIR/nss-tests.log | head -100
exit 1
fi
runHook postCheck
569libffi
patch./ports/patch/libffi-3.8.0.patch

Closure handlers may write to their by-value arguments, which the runtime passes in the read-only zargs() buffer (cffi's test_callback_large_struct).

patch./patches/libffi-closure-writable-args.patch
toolpkgs.autoreconfHook
configure"--disable-static"
configure"--disable-exec-static-tramp"
581libpng=
581libpng
pin"1.6.43" "sha256-alygZSOSotfJ2yrltAIQhDwLvAgcvUEIJasAzFnxSmw="
patch./ports/patch/libpng-1.6.43.patch
usepostPatch = "";
skipCheck"slow and occasionally flaky"
590libjpeg_turbo=
591libjpeg_turbo
patch./ports/patch/libjpeg-turbo-3.0.1.patch

The x86-64 SIMD extensions are NASM assembly; build the Arm Neon intrinsics instead, translated to SSE by the SIMDe headers.

patch./patches/libjpeg-turbo-simde-neon.patch
addCMakeFlag"-DSIMDE_NEON=1"
addCMakeFlag"-DREQUIRE_SIMD=1"
addCFlag"-isystem ${pkgs.buildPackages.simde}/include"
addCMakeFlag"-DCMAKE_SKIP_INSTALL_RPATH=ON"
argnasm = pkgs.hello;
605libxml2
patch./ports/patch/libxml2-2.14.4.patch
argpythonSupport = false;
skipCheck"python tests fail"

db and db5 are aliases of db53; override it so all three get the port.

623db53=
623db53

Private environments stored heap pointers in integer offsets and mutex IDs; give them the offset-based shared-region layout.

patch./patches/db-private-regions.patch

db_load without -h opens a private environment.

use
629doInstallCheck=
true
630installCheckPhase=
printf 'key\nvalue\n' | "$bin/bin/db_load" -T -t btree t.db
"$bin/bin/db_dump" -p t.db | grep -qx ' value'
638nettle
removeConfigureFlag"--enable-fat"
configure"--disable-assembler"
643pcre2
645libarchive
pin"3.7.4" "sha256-z3/IW59mPAbcK3A2t+5U0CcSFn4EsHvcxMJ1U6vy1v8="
patch./ports/patch/libarchive-3.7.4.patch
skipCheck"some tests fail"
skipPatch"mac"
652libedit
pin"20240808-3.1" "sha256-XwVzNJ13xKSJZxkc3WY03Xql9jmMalf+A3zAJpbWCZ8="
patch./ports/patch/libedit-20240808-3.1.patch
657libidn2 for pkgs.callPackage"${pkgs.path}/pkgs/development/libraries/libidn2" { }

Special case - libiconv comes from glibc in cross-compilation

663libiconv=
664pname=
"libiconv"
665attrs=
old: { }
666overrideArgs=
{ }
670pth

configure's makecontext probe passes a void (*)(void *) to makecontext, which Clang rejects, so pth fell back to setjmp/longjmp with a hand-patched jmp_buf stack pointer (sjljlx), which does not exist for this libc. Fil-C implements makecontext/swapcontext, so use pth's standard SUSv2 ucontext backend.

configure"--with-mctx-mth=mcsc"
configure"--with-mctx-dsp=sc"
configure"--with-mctx-stk=mc"
use
680doCheck=
true

maketest ignores test_std's exit status.

682checkPhase=
runHook preCheck
make test_std
./test_std
runHook postCheck

Core Utilities

693coreutils
skipCheck"too slow in Fil-C"
698bash=
698bash
arginteractive = true;

unwind_protect saves jmp_bufs in a misaligned buffer, losing their capabilities: bash -c 'set -e; false' crashed.

bashUnwindPatch
skipCheck"interactive mode issues"
706bashNonInteractive=
706bash
arginteractive = false;

unwind_protect saves jmp_bufs in a misaligned buffer, losing their capabilities: bash -c 'set -e; false' crashed.

bashUnwindPatch
skipCheck"test issues"
715busybox
arg
717enableStatic=
false
718enableMinimal=
false

These assembly implementations lack SaRCAsm capability signatures. Use BusyBox's portable C SHA implementations.

721extraConfig=
"CONFIG_SHA1_HWACCEL n\nCONFIG_SHA256_HWACCEL n"

The Makefile calls plain cc (filcc has no target prefix), and the build platform's compiler, there for HOSTCC, comes first on PATH: the result was a native busybox. Name the Fil-C compiler explicitly.

use
λold
727makeFlags=
old.makeFlags or [ ]
++
"CC=${final.stdenv.cc}/bin/cc"

Partial links (-r) of built-in.o: the Fil-C driver adds its own main even there, which then clashes in the final link.

"LD=${final.stdenv.cc.bintools}/bin/ld"

Fil-C's libc has no vfork; busybox vforks only to exec or exit.

addCFlag"-Dvfork=fork"

Under clang, busybox writes its const global pointers through an asm statement that launders the pointer, which Fil-C refuses. Make those globals plain variables (busybox's documented switch) and take the ordinary assignment path.

addCFlag"-DBB_GLOBAL_CONST="
use
λold
742postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace include/libbb.h libbb/const_hack.c --replace-fail \
'#if defined(__clang_major__) && __clang_major__ >= 9' \
'#if defined(__clang_major__) && __clang_major__ >= 9 && !defined(__FILC__)'
# printf %s passes the string to printf as a long long when the sizes
# match, which drops its capability; take the char * path instead.
substituteInPlace coreutils/printf.c --replace-fail \
'if (sizeof(argument) == sizeof(llv)) {' 'if (0) {'

nixpkgs' separate debug info adds -Wa,--compress-debug-sections, which Fil-C's assembler rejects, and busybox skips the preConfigure hook removeCFlag relies on.

useseparateDebugInfo = false;
761diffutils
patch./ports/patch/diffutils-3.12.patch
toolpkgs.perl
usepostPatch = "patchShebangs man/help2man";
skipTests"too slow"
768dash
pin"0.5.12" "sha256-akdKxG6LCzKRbExg32lMggWNMpfYs4W3RQgDDKSo8oo="
patch./ports/patch/dash-0.5.12.patch
773file
skipCheck"some magic tests fail"
777gawk
skipCheck"locale tests fail"
781a2ps
use
λold

gnulib's old obstack.h aligns pointers relative to (char *) 0, which drops their capabilities; align relative to the chunk.

785postPatch=
old.postPatch or ""
+
substituteInPlace lib/obstack.h --replace-fail \
'__BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0,' \
'__BPTR_ALIGN ((B),'
substituteInPlace tests/backup.tst tests/styles.tst \
--replace-quiet /bin/rm rm
792doCheck=
true
793preCheck=
"patchShebangs contrib tests"

Pointers that Guile keeps as scm_t_bits words, weak tables on FUGC, continuations without C stack copying: see docs/guile.md.

800guile_3_0=
800guile_3_0
patch./ports/patch/guile-3.0.11.patch

Nixpkgs' cross-build fix is already in 3.0.11.

skipPatch"c117f8edc471d3362043d88959d73c6a37e7e1e9"

Guile's JIT emits machine code.

configure"--disable-jit"
use
λold
807depsBuildBuild=
pkgs.stdenv.cc
808nativeBuildInputs=
old.nativeBuildInputs ++ guileForBuild

A smoke test of the installed interpreter. The test suite is run by hand (docs/guile.md); like Nixpkgs, the build skips it.

811doInstallCheck=
true
812installCheckPhase=
runHook preInstallCheck
$out/bin/guile -c '
(use-modules (ice-9 match) (srfi srfi-1) (ice-9 format))
(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
(unless (= (fib 20) 6765) (exit 1))
(unless (equal? (match (list 1 2 3) ((a . b) b)) (list 2 3)) (exit 1))
(gc)
(unless (= (fold + 0 (iota 100000)) 4999950000) (exit 1))
(unless (string=? (format #f "~a-~s" 1 "x") "1-\"x\"") (exit 1))
(unless (= 3 (call/cc (lambda (k) (+ 1 (k 3))))) (exit 1))
(display "guile ok\n")'
runHook postInstallCheck

Nixpkgs lists guile only as a host input, so configure finds no guile to compile the modules with. The build platform's guile cannot load Fibers' Fil-C extension, which configure checks for, so use the Fil-C guile itself: it runs on the build machine.

833gnu-shepherd=
833gnu-shepherd
useold: nativeBuildInputs = old.nativeBuildInputs ++ filcGuileForBuild;

Pure Guile. As with gnu-shepherd, configure needs a guile, and its tests run with the Fil-C one.

841lilypond=
841lilypond

The default TeX is built from the host package set, since it is a derived value that splicing does not reach; it only runs at build time.

arg

WIP: the Fil-C ghostscript-with-X fails configure (its -lz check links the build platform's zlib), so the lilypond wrapper puts the build platform's gs on PATH for PDF output.

849ghostscript=
pkgs.buildPackages.ghostscript
850tex=
pkgs.buildPackages.texliveSmall.withPackagesps: with ps; epsf fontinst fontware lh metafont
use
λold

Nixpkgs lists guile only as a build tool. LilyPond links libguile, and the build runs the Fil-C lilypond (it runs on the build machine) to compile its Scheme files.

864nativeBuildInputs=
builtins.filterd: ¬pkgs.lib.hasPrefix"guile" d.name or "" old.nativeBuildInputs ++ guileForBuild
869buildInputs=
old.buildInputs ++ final.guile_3_0

configure sets CROSS=yes, which drops the rules that run the programs (help2man, lilypond itself) but not the targets that need them. Fil-C programs run on the build machine.

873makeFlags=
old.makeFlags or [ ] ++ "CROSS=no"

handle_broken_dependencies () replaces the system's all-elements Grob_array, so the old one can be collected and deleted while this function still reads it through a reference (a use-after-free that Fil-C stops in 19 regression tests). Keep its SCM alive until the end.

879postPatch=
old.postPatch or ""
+
substituteInPlace lily/system.cc \
--replace-fail \
'std::vector<Grob *> &all_elts = all_elements ()->array_reference ();' \
'SCM all_elts_scm = get_object (this, "all-elements");
std::vector<Grob *> &all_elts = all_elements ()->array_reference ();' \
--replace-fail \
'debug_output (_f ("Element count %zu", count + all_elts.size ()) + "\n");' \
'debug_output (_f ("Element count %zu", count + all_elts.size ()) + "\n");
scm_remember_upto_here_1 (all_elts_scm);'
893guile-zlib=
894guile-gcrypt=
894guile-gcrypt

Otherwise configure finds the build platform's libgcrypt-config and records that libgcrypt for the FFI.

configure"--with-libgcrypt-prefix=${final.libgcrypt.dev}"
configure"--with-libgcrypt-libdir=${pkgs.lib.getLibfinal.libgcrypt}/lib"
guileTestsOnFilc
901guile-lzlib=
901guile-lzlib

configure finds liblz by running ldd on a test program, which does not work for a Fil-C program.

configure"guile_cv_liblz_libdir=${final.lzlib.out}/lib/liblz.so"
guileTestsOnFilc
907guile-zstd=
908guile-lzma=
909guile-sqlite3=
909guile-sqlite3
guileTestsOnFilc
910guile-git=
910guile-git
guileTestsOnFilc

Connecting to a socket that never accepts times out with a GITERR_OS error instead of GITERR_NET with the Fil-C libgit2.

use
λold
915preCheck=
old.preCheck or ""
+
substituteInPlace tests/clone.scm --replace-fail \
'(test-equal "clone beyond timeout"' \
'(test-skip 1) (test-equal "clone beyond timeout"'
922guile-avahi=
922guile-avahi

Clang reports an unused static function that GCC does not.

addCFlag"-Wno-error=unused-function"
guileTestsOnFilc
928guix=
928guix

configure takes libgcrypt from the build platform's libgcrypt-config otherwise; the path also ends up in guix/config.scm for the FFI.

configure"--with-libgcrypt-prefix=${final.libgcrypt.dev}"
configure"--with-libgcrypt-libdir=${pkgs.lib.getLibfinal.libgcrypt}/lib"
use
λold

graphviz (for documentation figures) fails to build natively at this Nixpkgs pin (its X variant installs no vimdot), so use the variant without X. slirp4netns (for container networking) needs libseccomp, and the Fil-C runtime does not support the seccomp system call.

940nativeBuildInputs=
builtins.filterd: ¬builtins.elemd.pname or "" "graphviz" "slirp4netns" old.nativeBuildInputs ++ pkgs.buildPackages.graphviz-nox
949propagatedBuildInputs=
builtins.filterd: d.pname or "" ≢ "slirp4netns" old.propagatedBuildInputs

The build-time tools (guile, makeinfo for the translated manuals) need a UTF-8 locale; the native build gets it from glibcLocales' hook, which does not apply here.

955LOCALE_ARCHIVE=
"${pkgs.buildPackages.glibcLocales}/lib/locale/locale-archive"
956LC_ALL=
"C.UTF-8"

The wrapper records $GUILE_LOAD_PATH, which also holds the build platform's Guile libraries (used to compile the modules); their FFI bindings point at native libraries, which a Fil-C process cannot load. Keep only the host's.

961preInstall=
old.preInstall or ""
+
hostOnly() { printf %s "$1" | tr : '\n' | grep -- -gnufilc0- | paste -sd: -; }
export GUILE_LOAD_PATH=$(hostOnly "$GUILE_LOAD_PATH")
export GUILE_LOAD_COMPILED_PATH=$(hostOnly "$GUILE_LOAD_COMPILED_PATH")
969mcron=
969mcron
useold: nativeBuildInputs = old.nativeBuildInputs ++ filcGuileForBuild;
975mailutils=
975mailutils

Configure finds GNU gss unusable for Fil-C.

removeConfigureFlag"--with-gssapi"
use
λold

guile-config runs an unprefixed pkg-config; give it the host's, so that it reports the Fil-C guile.

981nativeBuildInputs=
old.nativeBuildInputs ++ guileForBuild pkgs.writeShellScriptBin"pkg-config" ''exec "$PKG_CONFIG" "$@"''

The Guile binding tests load the Fil-C libmu_scm, so they need the Fil-C guile (it runs on the build machine).

987preCheck=
old.preCheck or ""
+
export PATH=${final.guile_3_0}/bin:$PATH

Out-of-bounds reads that Fil-C stops: imap4d's LIST reads ref[-1] for an empty reference; in test helpers, a memmove from the wrong offset, a loop that tests the output pointer instead of the input, and argv[i][len - 1] on an empty argument.

994postPatch=
old.postPatch or ""
+
substituteInPlace imap4d/list.c \
--replace-fail "if (ref[refinfo.reflen-1] != pfx->delim" \
"if (refinfo.reflen > 0 && ref[refinfo.reflen-1] != pfx->delim"
# Its word-wrapping stream kept writing after a failed flush
# (EPIPE when mail --version is piped into sed, which quits
# after the first line), past the end of its line buffer.
substituteInPlace libmailutils/stream/wordwrap.c --replace-fail \
" _wordwrap_flush_line (str, iptr[n]);" \
" { int rc = _wordwrap_flush_line (str, iptr[n]); if (rc) return rc; }"
substituteInPlace testsuite/cwdrepl.c \
--replace-fail 'size_t rest = n - start;' 'size_t rest = n - off;'
substituteInPlace libmailutils/tests/encode2047.c \
--replace-fail 'for (p = buf; *p;)' 'for (p = buf; *buf;)'
substituteInPlace libmailutils/tests/tesh.c \
--replace-fail "if (argv[i][len - 1] == ';')" \
"if (len > 0 && argv[i][len - 1] == ';')"
1021gnumake
patch./ports/patch/make-4.4.1.patch
argguileSupport = false;
1031gnutar
patch./ports/patch/tar-1.35.patch
skipPatch"acl-2.4.0-name-conflicts.patch" also part of the port
argaclSupport = false;

Build Tools

qemu-img is only on the PATH of cloud-localds and the other image tools in $out, and the Fil-C QEMU does not build yet. growpart, in the guest output that NixOS's boot.growPartition uses, does not need it.

1051cloud-utils
argqemu-utils = pkgs.emptyDirectory;
1055cmake

No Fil-C source patch; Nixpkgs 26.05's patches only apply to 4.x.

skipCheck"some tests fail"
addCMakeFlag"-DCMAKE_VERBOSE_MAKEFILE=ON"
addCMakeFlag"-DCMAKE_CXX_COMPILER=${pkgs.lib.getBinprev.stdenv.cc}/bin/c++"
addCMakeFlag"-DCMAKE_C_COMPILER=${pkgs.lib.getBinprev.stdenv.cc}/bin/cc"
addCMakeFlag"-DCMAKE_EXE_LINKER_FLAGS=-lm"

Only the C API is used. Avoid the unsupported target Fortran compiler and OpenMP runtime. The other precisions are overrides of this one.

1068v4l-utils

The BPF decoders are compiled by a clang for the BPF target.

argwithBPF = false;
1074ffmpeg-headless=
1074ffmpeg-headless

Upstream Fil-C's FFmpeg 8.0.1 port applies unchanged to 8.1.

patch./ports/patch/ffmpeg-8.0.1.patch
use
λold

8.1 keeps the log callback in an atomic_uintptr_t, which drops the function pointer's capability; every av_log call trapped.

1080postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace libavutil/log.c \
--replace-fail \
'static atomic_uintptr_t av_log_callback = (uintptr_t)av_log_default_callback;' \
'static void (*_Atomic av_log_callback)(void*, int, const char*, va_list) = av_log_default_callback;' \
--replace-fail \
'atomic_store_explicit(&av_log_callback, (uintptr_t)callback,' \
'atomic_store_explicit(&av_log_callback, callback,'
# flashsv2 rebased block pointers from one buffer into another
# with a pointer difference, keeping the first buffer's bounds.
substituteInPlace libavcodec/flashsv2enc.c --replace-fail \
's->key_blocks[i].enc += (s->keybuffer - s->encbuffer);' \
's->key_blocks[i].enc = s->keybuffer + (s->key_blocks[i].enc - s->encbuffer);'

Hand-written x86 assembly and inline assembly; upstream builds the same way.

configure"--disable-asm"

CUDA kernels would be compiled by a clang for the NVPTX target.

arg
1103withCudaLLVM=
false
1104withNvcodec=
false

x265 builds its 10/12-bit variants with GCC, and vid.stab uses OpenMP; neither toolchain targets Fil-C.

1107withX265=
false
1108withVidStab=
false
1114libgbm=
1114libgbm

Mesa's BLAKE3 has hand-written x86-64 assembly; use its C versions, as Mesa itself does for x32.

use
λold
1118postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace src/util/blake3/meson.build \
--replace-fail "elif cc.sizeof('void *') == 4" "elif true"
1129imlib2

Hand-written AMD64 blending assembly.

configure"--enable-amd64=no"
1134libvpx

Build without the x86 assembly and intrinsics dispatch.

removeConfigureFlag"--target=x86_64-linux-gcc"
configure"--target=generic-gnu"
argruntimeCpuDetectSupport = false;
1141libgit2
patch./patches/libgit2-configmap-cache-clear.patch

xdiff adds src/util as a SYSTEM include directory, which then comes after the wrapper's -isystem for Fil-C glibc, whose obsolete <regexp.h> stub shadows libgit2's own "regexp.h".

use
λold
1147postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace deps/xdiff/CMakeLists.txt \
--replace-fail "target_include_directories(xdiff SYSTEM PRIVATE" \
"target_include_directories(xdiff PRIVATE"

Video codecs: build the portable C code paths, without hand-written assembly or intrinsics dispatch.

1160x264
configure"--disable-asm"
1161svt-av1
removeCMakeFlag"-DSVT_AV1_LTO=ON"
addCMakeFlag"-DCOMPILE_C_ONLY=ON"
1165libavif

Honor allocation-failure returns for sizes that cannot be C objects.

patch./patches/libavif-allocation-size.patch
1169libaom
addCMakeFlag"-DAOM_TARGET_CPU=generic"

Keep the owning malloc pointer's capability in the aligned header.

patch./patches/libaom-allocation-pointer.patch
useold: passthru = old.passthru or { } // tests = old.passthru.tests or { } // allocation-encoder = import./tests/libaom.nix pkgs = final;;;;
1182onetbb

tbbmalloc carves objects out of raw mmap chunks, so its pointers carry no capability; TBB falls back to malloc without it.

addCMakeFlag"-DTBBMALLOC_BUILD=OFF"
  • queuing_rw_mutex tags its queue pointers in std::atomic<uintptr_t>; keep them in std::atomic<char*> and set the tag by pointer arithmetic.
  • Clang claims __GNUC__ 4, so TBB picked a "lock; notb" fence and stmxcsr/fstcw for the FPU state, inline asm with memory operands that Fil-C refuses; use std::atomic_thread_fence and <fenv.h>.
patch./patches/onetbb-fil-c.patch
use
λold
1193postPatch=
old.postPatch or ""
+
"\n"
+
# The tests use doctest, whose signal handling needs sigaltstack.
sed -i '/#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN/a #define DOCTEST_CONFIG_NO_POSIX_SIGNALS' \
test/common/test.h
grep -q DOCTEST_CONFIG_NO_POSIX_SIGNALS test/common/test.h
1202disabledTests=
old.disabledTests or [ ]
++

They expect allocations of nearly 2^64 bytes to throw bad_alloc; Fil-C stops the program instead.

"test_allocators"
"conformance_allocators"

Its own cpuid inline asm does not declare the clobbered ecx.

"test_mutex"

Not usable yet: the task scheduler and collaborative_call_once still keep pointers in integers and trap in most tests, and test_eh_algorithms spins. Marked unsupported so that dependents (libblake3's useTBB, ...) leave it out.

1214meta=
old.meta // badPlatforms = old.meta.badPlatforms or [ ] ++ prev.stdenv.hostPlatform.system;
1222libblake3
addCMakeFlag"-DBLAKE3_SIMD_TYPE=none"
1224wavpack
configure"--disable-asm"

Its MMX/SSE routines are yasm assembly, which Fil-C cannot link.

1227xvidcore
configure"--disable-assembly"
1229libopus
patch./ports/patch/opus-1.5.2.patch

Without the x86 intrinsics and their run-time CPU dispatch.

addMesonFlag"-Dintrinsics=disabled"
addMesonFlag"-Drtcd=disabled"
1238libopenmpt
patch./patches/libopenmpt-x87-control-word.patch

Found by Fil-C: a use-after-free when libc++'s codecvt returns partial, as it does for non-ASCII text in the C locale.

patch./patches/libopenmpt-codecvt-partial.patch

libpulseaudio is pulseaudio.override { libOnly = true; }, so this covers the library, the daemon and its modules.

1247pulseaudio

pa_atomic_ptr_t kept pointers in a uintptr_t, dropping their capabilities (pa_once's mutex came back null).

patch./patches/pulseaudio-atomic-ptr.patch
use
λold

PA_WARN_REFERENCE emits .gnu.warning sections as module asm, which FilPizlonator does not accept; drop the link-time warnings.

1254postPatch=
old.postPatch or ""
+
substituteInPlace src/pulsecore/macro.h --replace-fail \
'#if defined(__GNUC__) && defined(__ELF__)' '#if 0'
# Report no MMX/SSE, so the inline-asm mixing and volume routines
# stay unused.
substituteInPlace src/pulsecore/cpu-x86.c --replace-fail \
'/* get standard level */' 'return;'
# Fil-C's abort() raises SIGTRAP, and SIGBUS handlers are refused.
sed -i 's/\(test_replace_fail_[0-9]\), SIGABRT/\1, SIGTRAP/' \
src/tests/core-util-test.c
sed -i "/\[ 'sigbus-test', 'sigbus-test.c',/,+1d" src/tests/meson.build

The mix and remap benchmarks outlast their 120 s check timeout.

1267env=
old.env or { } // CK_TIMEOUT_MULTIPLIER = "5";

The C implementations instead of the perlasm AES, SHA, bignum and RC4 routines.

1275libressl
addCMakeFlag"-DENABLE_ASM=OFF"
use
λold

explicit_bzero's test inspects a signal handler's sigaltstack.

1279postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace tests/CMakeLists.txt --replace-fail \
'add_test(explicit_bzero explicit_bzero)' ""
1289physfs
use
λold

The LZMA SDK's PIC cpuid saves %rbx in %rdi around cpuid, so the asm clobbers %ebx without saying so, which FilPizlonator rejects. Name %ebx as the output instead.

1294postPatch=
old.postPatch or ""
+
substituteInPlace src/physfs_lzmasdk.h --replace-fail \
'#if defined(MY_CPU_AMD64) && defined(__PIC__)' \
'#if defined(MY_CPU_AMD64) && defined(__PIC__) && !defined(__FILC__)'
1302btrfs-progs
use
λold

Only the table-driven CRC32C: the PCLMUL one is hand-written assembly, and the SSE4.2 one emits crc32 as .byte inline asm.

1306postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace Makefile --replace-fail \
'CRYPTO_OBJECTS += crypto/crc32c-pcl-intel-asm_64.o' ""
substituteInPlace crypto/crc32c.c --replace-fail \
'#ifdef __x86_64__' '#if defined(__x86_64__) && !defined(__FILC__)'

The suites that need neither root nor a block device: the hash test vectors and speed test, and the string-table and array units.

1317doCheck=
true
1318checkTarget=
"test-hash test-string-table test-array"
1322isa-l
use
λold

Build as for an unknown CPU: the portable C "base" functions, without the yasm/nasm kernels and their multibinary dispatch.

1326postPatch=
old.postPatch or ""
+
substituteInPlace configure.ac --replace-fail \
'[x86_64], [CPU="x86_64"],' '[x86_64], [CPU=""],' \
--replace-fail '-D_FORTIFY_SOURCE=2 \' '\'

igzip's base hash-table reset calls wmemset, and Fil-C's glibc has no __wmemset_chk.

1333hardeningDisable=
old.hardeningDisable or [ ] ++ "fortify"

The unit tests for every function set.

1335doCheck=
true

pname is crypto++.

1341cryptopp=
1341cryptopp
use
λold

Plain C++ instead of the inline asm and SIMD intrinsics; e.g. SecureWipeBuffer's repstos has the pointer as an asm output. Set in config_asm.h so programs using the headers agree.

1346postPatch=
old.postPatch or ""
+
substituteInPlace config_asm.h --replace-fail \
'// #define CRYPTOPP_DISABLE_ASM 1' \
'#if defined(__FILC__)
# define CRYPTOPP_DISABLE_ASM 1
#endif'
# Integer's x86-64 word arithmetic is inline asm regardless;
# multiply through unsigned __int128 as on other 64-bit targets.
substituteInPlace integer.cpp --replace-fail \
'((defined(__aarch64__) || defined(__x86_64__)) && defined(CRYPTOPP_WORD128_AVAILABLE))' \
'((defined(__aarch64__) || (defined(__x86_64__) && !defined(__FILC__))) && defined(CRYPTOPP_WORD128_AVAILABLE))'
1362rubberband
use
λold

RTENTRY__ annotates the real-time entry points with __attribute__((annotate)), which crashes FilPizlonator.

1366postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace src/common/sysutils.h --replace-fail \
'# define RTENTRY__ __attribute__((annotate("realtime")))' \
'# define RTENTRY__'

Nixpkgs disables the Boost.Test suite for want of Boost.

1375buildInputs=
old.buildInputs or [ ] ++ final.boost
1376doCheck=
true
removeMesonFlag"-Dtests=disabled"
addMesonFlag"-Dtests=enabled"
1382libcamera

LTTng-UST tracepoints; the tracer's own tests exercise signal and namespace machinery Fil-C does not provide.

arg
1386withTracing=
false

jinja2, PyYAML and ply run on the build Python (3.13); the Fil-C set is for the ported 3.12, so meson could not import jinja2.

1389python3Packages=
pkgs.python3Packages

The experimental Python bindings would need the Fil-C Python.

addMesonFlag"-Dpycamera=disabled"
patch./patches/libcamera-no-dynamic.patch
1396polkit

polkit's hand-written get_type functions keep the GType in a volatile gsize, but GType is a pointer in Fil-C's GLib; use a GType with g_once_init_{enter,leave}_pointer (GLib 2.80).

patch./patches/polkit-pointer-gtype.patch

The runaway-script test needs asynchronous pthread_cancel, which Fil-C does not deliver (SIGCANCEL is reserved by the runtime); it hung forever. Under Fil-C a runaway rules script is not killed.

patch./patches/polkit-filc-no-runaway-test.patch

gtk-doc generates an unported GType scanner; GIR generation stays on.

removeMesonFlag"-Dgtk_doc=true"
addMesonFlag"-Dgtk_doc=false"
1410libgudev

The tests preload umockdev, whose Vala-generated code assumes integer GTypes, and LD_PRELOAD interposition does not apply to Fil-C symbols.

use
λold
1414doCheck=
false

GType is a pointer in Fil-C's GLib.

1416postPatch=
old.postPatch or ""
+
substituteInPlace gudev/gudevenumtypes.c.template \
--replace-fail 'static gsize static_g_define_type_id' \
'static GType static_g_define_type_id' \
--replace-fail 'g_once_init_enter (' 'g_once_init_enter_pointer (' \
--replace-fail 'g_once_init_leave (' 'g_once_init_leave_pointer ('
# Clang has no -export-dynamic driver flag (GCC passes it to ld).
substituteInPlace gudev/meson.build \
--replace-fail "'-export-dynamic'," "'-Wl,--export-dynamic',"
1429libical

The libical-glib install check runs PyGObject on the build platform, which the Fil-C Python port's package overrides (pyports.nix) also reach and break.

use
1434doInstallCheck=
false
1435nativeInstallCheckInputs=
[ ]
1439libshout

configure only finds -lssl, but libshout also calls libcrypto directly.

addCFlag"-Wl,-lcrypto"
1444ell
patch./patches/ell-no-debug-section.patch

test-ecdh wraps l_getrandom with ld --wrap, whose __real_ symbol Fil-C does not rename.

skipCheck"ld --wrap"
1451bluez

BlueZ builds against the copy of ELL's headers in its tarball.

patch./patches/ell-no-debug-section.patch
patch./patches/bluez-no-debug-section.patch

The MIDI profile stores pointers into ALSA's packed snd_seq_ev_ext, at a misaligned offset where Fil-C cannot keep a capability.

removeConfigureFlag"--enable-midi"
configure"--disable-midi"
use
λold

The installed test scripts run on Fil-C Python with its dbus-python and PyGObject. The build Python's wrapPython would give them the build interpreter and search its own, empty, site-packages layout.

1463nativeBuildInputs=
map
λp
pkgs.lib.hasPrefix"wrap-python-hook" p.name or ""
→
final.python3Packages.wrapPython
else
old.nativeBuildInputs
1473liburcu

Use compiler atomics instead of the x86 inline assembly ones.

configure"--enable-compiler-atomic-builtins"

The x86 header still used inline-assembly barriers ("lock; addl"), which Fil-C rejects when they run, and the memb flavor probed membarrier(2), which Fil-C refuses by stopping the program. Use the generic builtin barriers and the existing no-membarrier fallback. With that, the unit tests (674) pass and run again. rculfhash (BIND's dns tests) also needed the generic fls instead of bsr assembly, its node flags set and cleared with zorptr/zandptr rather than integer math, which dropped the next pointers' capabilities, and REMOVED_FLAG set by pointer CAS, since an integer atomic or was not seen by atomic pointer loads.

patch./patches/liburcu-filc.patch
use
λold
1488postCheck=
old.postCheck or ""
+
$CC -Iinclude ${./tests/liburcu-lfht.c} -Lsrc/.libs \
-Wl,-rpath,"$PWD/src/.libs" -lurcu -lurcu-cds -pthread \
-o lfht-test
./lfht-test
1497lttng-ust

With liburcu's compiler-builtin atomics, uatomic_or on the tagged node->next pointer does not compile; set the flag with a CAS loop.

patch./patches/lttng-ust-rculfhash-removed-flag.patch

Fil-C has no dl_iterate_phdr, which the base-address statedump uses to list loaded objects; skip that statedump.

patch./patches/lttng-ust-no-dl-iterate-phdr.patch

liblttng-ust-common's constructor probed membarrier(2), which Fil-C refuses by stopping the program; use the existing smp_mb fallback.

patch./patches/lttng-ust-no-membarrier.patch

Fil-C has no __start_/__stop_ section symbols, and the weak references in <lttng/tracepoint.h> crashed every instrumented program at startup; register each tracepoint from a constructor.

patch./patches/lttng-ust-tracepoint-ctor-registration.patch

libnuma's numa_preferred() trips a bounds check in Fil-C's get_mempolicy wrapper (docs/filc-findings.md), which the ring buffer calls for every channel.

configure"--disable-numa"
1517mbedtls
patch./patches/mbedtls-test-cli-crt-ec-der-len.patch

AES-NI, PadLock and bignum inline assembly pass pointers to asm.

use
λold
1521postPatch=
old.postPatch or ""
+
"\n"
+
for option in MBEDTLS_AESNI_C MBEDTLS_PADLOCK_C MBEDTLS_HAVE_ASM; do
${pkgs.python3}/bin/python3 scripts/config.py unset $option
done
1532libpq

libpq refuses to link anything named like exit. Fil-C 0.687 lowers small allocas to filc_allocate_without_exiting, which never exits.

use
λold
1536postPatch=
old.postPatch or ""
+
substituteInPlace src/interfaces/libpq/Makefile \
--replace-fail '-e __tsan_func_exit' '-e __tsan_func_exit -e _without_exiting'

Nixpkgs uses -flto with Clang to drop unused pg_config paths (and the dev-output references they carry). Fil-C has no LTO linker plugin, so garbage-collect sections at link time instead, as with GCC.

useold: env = old.env // CFLAGS = "-fdata-sections -ffunction-sections -Wl,--gc-sections";;

Fil-C keeps each function's name and source file for its stack traces outside the debug sections. Inlined OpenSSL header functions thus name openssl-dev headers, which outputChecks forbids in $out.

toolpkgs.removeReferencesTo
use
λold
1554postInstall=
old.postInstall
+
"\n"
+
remove-references-to ${pkgs.lib.concatMapStringsSep" " d: "-t ${pkgs.lib.getDevd}" builtins.filterd: d ? dev old.buildInputs} $out/lib/*.so*
1567libmpdclient

Nixpkgs lists the check library and pkg-config as native check inputs; meson looks the library up for the host at configure time.

use
λold
1571nativeBuildInputs=
old.nativeBuildInputs ++ pkgs.pkg-config
1572nativeCheckInputs=
[ ]
1573checkInputs=
final.check
1577liblc3

Meson's default b_lto would hand bitcode to the linker.

addMesonFlag"-Db_lto=false"
1582mpdecimal

The x64 configuration multiplies with mulq inline assembly that Fil-C rejects, so str(decimal.Decimal("1.5")) trapped in every Fil-C Python.

configure"MACHINE=ansi64"
1589gmp=
1589gmp

Upstream Fil-C disables this standalone assembly timing helper in generated configure; the port extractor deliberately omits that file.

use
λold
1593postPatch=
old.postPatch or ""
+
substituteInPlace configure \
--replace-fail 'SPEED_CYCLECOUNTER_OBJ_64=x86_64.lo' 'SPEED_CYCLECOUNTER_OBJ_64=' \
--replace-fail 'cyclecounter_size_64=2' 'cyclecounter_size_64='
configure"--disable-assembly"
configure"--disable-fat"

Compression

patch./ports/patch/xz-5.8.4.patch
skipCheck"too slow"

The port changes Makefile.am; regenerate with Nixpkgs' Autotools.

toolpkgs.autoreconfHook
1613zstd
patch./ports/patch/zstd-1.5.6.patch

1.5.7's pointer-select inline asm is independent of ZSTD_DISABLE_ASM.

patch./patches/zstd-pointer-select.patch
skipCheck"too slow"
addCFlag"-DZSTD_DISABLE_ASM"
1621lzo
skipTests"too slow"
configure"--disable-asm"

Networking

1628curl
argidnSupport = true;
argpslSupport = true;
argzstdSupport = true;
argbrotliSupport = true;
argscpSupport = false;
skipCheck"network tests flaky"
1637git
pin"2.46.0" "sha256-fxI0YqKLfKPr4mB0hfcWhVTCsQ38FVx+xGMAZmrCf5U="
skipPatch"git-send-email-honor-PATH.patch"

Test adjustments for newer releases; the suite is skipped below.

skipPatch"t7703-ignore-ls-total.patch"
skipPatch"expect-gui--askyesno-failure-in-t1517.patch"
patch./ports/patch/git-2.46.0.patch
argwithManual = true;
argperlSupport = false;
argpythonSupport = true;
argsendEmailSupport = false;
argzlib-ng = pkgs.zlib;
skipTests"too slow"
removeMakeFlag"ZLIB_NG=1"
1653nghttp2
configure"--disable-app"
addCFlag"-Wno-deprecated-literal-operator"
1658openssh
patch./ports/patch/openssh-10.5p1.patch
skipCheck"let's see"

preCheck preloads libredirect, whose dlsym(RTLD_NEXT, ...) interposition cannot work under Fil-C; referencing it would still build it.

usepreCheck = "";
use
1665installCheckPhase=
for binary in ssh sshd; do
echo "verifying OpenSSH version $version"
output=$($out/bin/$binary -V 2>&1)
echo "got output: $output"
echo "expected output: $(printf '^OpenSSH_%s,' "$version")"
if ! echo "$output" | grep -P "$(printf '^OpenSSH_%s,' "$version")"; then
echo "OpenSSH version verification failed"
exit 1
fi
done
argwithFIDO = false;

Cross autoconf can't run its malloc(0) test and assumes the worst, defining malloc as an rpl_malloc nobody provides. glibc's is fine.

1683davfs2
configure"ac_cv_func_malloc_0_nonnull=yes"
configure"ac_cv_func_realloc_0_nonnull=yes"
1688libssh2
skipCheck"network tests flaky"
configure"--disable-examples-build"
1693unbound
configure"ac_cv_type_pthread_spinlock_t=no"

With dnstap (unbound-full), Nixpkgs puts protobuf-c only in nativeBuildInputs, so a cross build has protoc-c but not the library.

useold: pkgs.lib.optionalAttrspkgs.lib.elem"--enable-dnstap" old.configureFlags or [ ] buildInputs = old.buildInputs ++ final.protobufc;
1707bind

Fixes CVE-2026-19630, -94300, -96888 and -97313 (2026-10-21).

pin"9.20.30" "sha256-nhRDpApyowJyy8MZbQIKay4mk3ERyD5Z4QHoLh47T+8="

Read named.conf, rndc.conf and rndc.key from /etc/bind, as Debian and ISC's image do, rather than the store; bind-dist relies on it.

configure"--sysconfdir=/etc/bind"

isc_mempool kept free lists of message names, rdatasets and netmgr sockets and requests, so a use after isc_mempool_put reached a live recycled object that Fil-C cannot flag. Free each one, as BIND does under ASan.

patch./patches/bind-mempool-no-freelist.patch

A qp-trie node kept its leaf and reader pointers split across two uint32_t halves of a 12-byte node, so every lookup read a pointer without a capability. Under Fil-C the word is a void * (16-byte nodes), tagged with pointer arithmetic.

patch./patches/bind-qp-node-pointer.patch

Under Fil-C a local whose address escapes is a zeroed heap allocation, and so is the temporary behind a large compound-literal assignment. Each query made about 60 KB of them (QP-trie chains and iterators, search contexts, the client and netmgr requests), which drove the collector. Initialize in place, allocate only what a call needs, and reuse one zone search context per thread.

patch./patches/bind-filc-heap-temporaries.patch

Three unit tests mock a library function by defining it in the test executable (doh_test's isc__nm_tcp_freebind, query_test's ns_client_error). Fil-C binds calls between a library's own translation units locally, so the mocks never run (docs/filc-findings.md); leave those tests out.

patch./patches/bind-tests-interposed-mocks.patch

Security

1740libseccomp

seccomp_init probed the seccomp() syscall (317), which Fil-C refuses by stopping the program, so every test died (rc=133). Report the syscall as missing; filters still load through prctl(PR_SET_SECCOMP), which Fil-C passes through, but without TSYNC or user notification.

patch./patches/libseccomp-filc-no-seccomp-syscall.patch

The regression suite only simulates filters; load one for real.

use
λold
1748postCheck=
old.postCheck or ""
+
-Lsrc/.libs -Wl,-rpath,"$PWD/src/.libs" -lseccomp -o prctl-filter
./prctl-filter
1769libgcrypt
configure"--disable-asm"

Upstream's port, rebased: --disable-asm alone leaves inline asm in mpi/longlong.h (bsrq in _gcry_mpi_get_nbits, used by RSA), OCB's ocb_get_l (rep;bsf, which gnupg's t-protect reached) and Keccak, all of which Fil-C traps on. sexp_null_cond selects its pointer as a pointer: rebuilt from masked integers it had no capability unless LLVM folded the round trip (filcc -O0 and nanofil trapped in gcry_pk_decrypt; nanofil/docs/ub.md).

patch./ports/patch/libgcrypt-1.12.2.patch

configure's probe mlocks malloc'ed memory, which Fil-C stops as a safety error, so it concluded mlock is broken and secure memory was never locked (GCRYCTL_INIT_SECMEM failed; t-secmem, t-sexp). The secure memory pool itself is mmapped, which mlock accepts.

configure"gnupg_cv_have_broken_mlock=no"
configure"gcry_cv_gcc_amd64_platform_as_ok=no"
useconfigurePlatforms = "host";
use
1787buildPhase=
sed -i '/HAVE_GCC_ASM_VOLATILE_MEMORY/d' config.h
touch config.status
make -j$NIX_BUILD_CORES

The default check phase runs only after the default build phase (foundMakefile), so the tests were skipped.

1794checkPhase=
runHook preCheck
make -j$NIX_BUILD_CORES check
runHook postCheck
1806libsodium
configure"--disable-ssp"
configure"--disable-asm"

sodium_free finds its guard pages from a pointer rebuilt from a masked integer, which had no capability unless LLVM folded the round trip (filcc -O0 and nanofil trapped; nanofil/docs/ub.md).

patch./ports/patch/libsodium-unprotected-ptr.patch
1815libtasn1
skipTests"one test fails"
1819libgpg-error
use
let
1822lock-obj-gnufilc0=
pkgs.writeText"lock-obj-pub.x86_64-unknown-linux-gnufilc0.h"
## File created by gen-posix-lock-obj - DO NOT EDIT
## To be included by mkheader into gpg-error.h
typedef struct
{
long _vers;
union {
volatile char _priv[40];
long _x_align;
long *_xp_align;
} u;
} gpgrt_lock_t;
#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \
0,0,0,0,0,0,0,0, \
0,0,0,0,0,0,0,0, \
0,0,0,0,0,0,0,0, \
0,0,0,0,0,0,0,0}}}
##
## Local Variables:
## mode: c
## buffer-read-only: t
## End:
##
in
1850postPatch=
cp ${lock-obj-gnufilc0} src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnufilc0.h
1853postConfigure=
cp ${lock-obj-gnufilc0} src/lock-obj-pub.native.h
1860libkrb5

The upstream patch is rooted above Nixpkgs' sourceRoot (src/).

use
λold
1863prePatch=
old.prePatch or ""

pname is cyrus-sasl, so name the attribute explicitly.

1871cyrus_sasl=
1871cyrus_sasl

Upstream backport: configure never defined HAVE_TIME_H, so time() and clock() were implicitly declared; Clang rejects that (GCC and nixpkgs only warn), and the implicit int return truncates time_t.

patch./patches/cyrus-sasl-time-h.patch

mariadb-connector-c and libmysqlclient are aliases of the 3.3 series.

1885mariadb-connector-c_3_3=
1885mariadb-connector-c_3_3

Its export map is an implicit linker script with VERSION blocks and unmangled symbol aliases; gold rejects it and only the driver's --version-script handling knows Fil-C's symbol names.

patch./patches/mariadb-connector-c-version-script.patch
1893p11-kit
skipTests"1 failure"
1897libtirpc

The source still uses K&R function definitions, which C23 removed. Autoreconf'd configure asks for -std=gnu23 (GCC accepts them there anyway; Clang does not), so keep Clang's gnu17 default.

configure"ac_cv_prog_cc_c23=no"
1904rpcbind

Same K&R definitions as libtirpc (rpcinfo.c).

configure"ac_cv_prog_cc_c23=no"
1909duktape
patch./patches/duktape-valstack-rebase.patch
use
1912doInstallCheck=
true
1913installCheckPhase=
"$out/bin/duk" ${./tests/duktape-valstack.js}

Graphics

1921pixman
usemesonFlags = "-Dgnu-inline-asm=disabled" "-Dmmx=disabled" "-Dsse2=disabled" "-Dssse3=disabled";
skipTests"some tests fail"
1937pango

1.57 requires GLib 2.82; the GLib port is 2.80.4.

use
1940version=
"1.56.3"
1941src=
pkgs.fetchurl
1942url=
"mirror://gnome/sources/pango/1.56/pango-1.56.3.tar.xz"
1943hash=
"sha256-JgYlK8Jc2NJOG39+ksOicrN6zWc0NHtztHpIKDS6JJE="
patch./ports/patch/pango-1.54.0.patch
1953graphene
patch./ports/patch/graphene-1.10.8.patch

gtk-doc generates an unported GType scanner; GIR generation stays on.

argwithDocumentation = false;
1959libepoxy

Nixpkgs ties EGL to X11, but GTK's Wayland backend also needs EGL.

use
λold
1962mesonFlags=
builtins.filterf: ¬pkgs.lib.hasPrefix"-Degl=" f old.mesonFlags ++ "-Degl=yes"
1967propagatedBuildInputs=
pkgs.lib.uniqueold.propagatedBuildInputs ++ final.libGL
1970env=
old.env // NIX_CFLAGS_COMPILE = old.env.NIX_CFLAGS_COMPILE or "" + pkgs.lib.optionalStringold.env.NIX_CFLAGS_COMPILE or "" ≡ "" " -DLIBGL_PATH=\"${pkgs.lib.getLibfinal.libGL}/lib\"";
1980fontconfig

ports/patch/fontconfig-2.15.0.patch rebased onto Nixpkgs' 2.17.

patch./patches/fontconfig-2.17-filc.patch
use
1984postPatch=
sed -i 's/ftglue.c/ftglue.c fcfilc.h fcfilc.c/' src/Makefile.am
toolpkgs.autoreconfHook
skipTests"tests pass but some test needs weird deps"
1992freetype
patch./ports/patch/freetype-2.13.3.patch
skipPatch"subpixel-rendering.patch" no need
skipPatch"enable-table-validation.patch" no need
1998harfbuzz
patch./ports/patch/harfbuzz-9.0.0.patch
argwithGraphite2 = false;
skipCheck"fuzzing fails"

The upstream 3.4.4 port also applies to Nixpkgs' 3.6.5 release.

The 1.4 series needs the EOL libsoup 2.

2046libhandy
patch./patches/libhandy-destroy-visible-child.patch
use
λold

librsvg is Rust; there is no Rust target for Fil-C. The icons are pre-rendered below.

2051checkInputs=
builtins.filterdep: ¬pkgs.lib.hasInfix"librsvg" dep.name or "" old.checkInputs or [ ]
2054postPatch=
old.postPatch or ""
+
# The target has no Rust SVG loader. Keep symbolic icon recoloring by
# embedding GTK's encoded PNG format, generated with native tools.
for icon in src/icons/scalable/*/*.svg; do
directory=$(dirname "$icon" | sed s,scalable,128x128,)
mkdir -p "$directory"
GDK_PIXBUF_MODULE_FILE=${pkgs.librsvg}/${pkgs.gdk-pixbuf.binaryDir}/loaders.cache \
${pkgs.gtk3.dev}/bin/gtk-encode-symbolic-svg "$icon" 128x128 -o "$directory"
png="$directory/$(basename "$icon" .svg).symbolic.png"
test -s "$png"
substituteInPlace src/handy.gresources.xml --replace-fail \
"<file preprocess=\"xml-stripblanks\">''${icon#src/}</file>" \
"<file>''${png#src/}</file>"
done
use
2078glib
pin"2.80.4" "sha256-JOApxd/JtE5Fc2l63zMHipgnxIk4VVAEs7kJb6TqA08="
patch./ports/patch/glib-2.80.4.patch
patch./patches/glib-gtype-api-ceiling.patch
patch./patches/glib-atomic-pointer-load.patch
patch./patches/glib-pointer-bit-wait.patch
patch./patches/glib-inline.patch
skipPatch"split-dev-programs.patch"
patch./patches/glib-split-backport.patch
arg
2088libsysprof-capture=
null

Keep the bootstrap GLib free of scanner inputs as well as GIR output.

2090withIntrospection=
false

gdbus-codegen runs on the build Python (3.13); the Fil-C set's packaging is for the ported 3.12, leaving codegen's path empty.

2093python3Packages=
pkgs.python3Packages
skipTests"many failures"
usemesonFlags = "-Ddevbindir=${placeholder"dev"}/bin" "-Dglib_debug=disabled" "-Ddocumentation=true" pkgs.lib.mesonBool"dtrace" false pkgs.lib.mesonBool"systemtap" false "-Dnls=enabled" pkgs.lib.mesonEnable"introspection" false "-Dtests=false";

gio-querymodules loads the modules it indexes, so consumers must run this one rather than the build GLib's. Meson prefers a cross file's binaries over its native pkg-config lookup.

use
λold
2112postFixup=
old.postFixup or ""
+
mkdir -p "$dev/share/meson"
cat > "$dev/share/meson/gio-querymodules.ini" <<EOF
[binaries]
gio-querymodules = '$dev/bin/gio-querymodules'
EOF
cat >> "$dev/nix-support/setup-hook" <<EOF
if (( hostOffset == 0 )) && [[ -z "\''${filcGioQuerymodulesCrossFile-}" ]]; then
filcGioQuerymodulesCrossFile=1
mesonFlagsArray+=("--cross-file=$dev/share/meson/gio-querymodules.ini")
fi
EOF
2130gobject-introspection-unwrapped=
2130gobject-introspection-unwrapped
pin"1.80.1" "sha256-od98Qk4VvaGrY5wA6QUbmt9c6hqeUS+KYDtTzRmbxtg="
patch./ports/patch/gobject-introspection-1.80.1.patch
patch./patches/gobject-introspection-filc-tools.patch
patch./patches/gobject-introspection-link-environment.patch
skipPatch"Prefer-some-getters-over-others.patch"
arg
2137propagateFullGlib=
false

Fil-C executables run directly on the build machine. Bootstrap the scanner here instead of recursively asking for a prebuilt scanner.

2140gobject-introspection-unwrapped=
null
removeMesonFlag"-Dgi_cross_use_prebuilt_gi=true"
addMesonFlag"-Dgi_cross_use_prebuilt_gi=false"
use
λold
2145nativeBuildInputs=
builtins.filterinput: input ≢ null old.nativeBuildInputs

_giscanner is compiled with Fil-C and must be loaded by Fil-C Python.

2149mesonFlags=
old.mesonFlags ++ "-Dpython=${final.python3.withPackagesps: ps.mako ps.markdown ps.setuptools}/bin/python3"
2158outputs=
builtins.filteroutput: output ≢ "devdoc" old.outputs

The installed scanner also needs this when inspecting downstream dumpers; a build-only PATH entry would leave those scans broken.

2161postPatch=
old.postPatch or ""
+
substituteInPlace giscanner/shlibs.py \
--replace-fail "['ldd', binary.args[0]]" "['${pkgs.glibc.bin}/bin/ldd', binary.args[0]]"

GLib's bootstrap build has no scanner. Install the GLib metadata generated here, which GI 1.80 otherwise keeps only for its tests. Also retain our patched test sources instead of Nixpkgs' native ones.

2168postInstall=
mkdir -p "$dev/share/gir-1.0" "$out/lib/girepository-1.0"
for namespace in GLib GObject GModule Gio; do
cp "gir/$namespace-2.0.gir" "$dev/share/gir-1.0/"
cp "gir/$namespace-2.0.typelib" "$out/lib/girepository-1.0/"
done
2183weston

The test runner collected its tests from a linker section; register them from constructors instead (upstream Fil-C's 12.0.5 patch).

patch./ports/patch/weston-15.0.1.patch

Nixpkgs' Neat VNC 1.0 update; the VNC backend is off.

skipPatch"8a1c91e771312d1e0d0cd92495ef717402784dae.patch"
argpipewireSupport = false;
argrdpSupport = false;
argremotingSupport = false;
argvaapiSupport = false;
argvncSupport = false;
argxwaylandSupport = false;
arglcmsSupport = false;
addMesonFlag"-Dsystemd=false"
2199seatd
argsystemd = final.systemdLibs;
2203alsa-lib

ALSA's .symver module assembly is not part of the Fil-C ABI.

configure"--without-versioned"
patch./patches/alsa-link-warning.patch

snd_seq_ev_ext and snd_seq_ev_quote are packed, which puts their pointers at misaligned offsets. Fil-C cannot keep a capability there (a constant initializer used to crash the compiler, and the compiler workaround was unsound), so drop packed under Fil-C. That grows snd_seq_event_t from 28 to 32 bytes, so the ALSA sequencer (MIDI via /dev/snd/seq) no longer matches the kernel; PCM audio is unaffected.

patch./patches/alsa-seq-unpacked-pointers.patch
2216spandsp

Nixpkgs passes CC=${targetPrefix}cc, which is just "cc" for Fil-C, and its depsBuildBuild puts the build GCC's cc first on PATH, so the library came out native (and PipeWire's mSBC codec failed to link).

removeMakeFlag"CC=cc"
addMakeFlag"CC=${prev.stdenv.cc}/bin/cc"
2224ffado
use
λold

Fil-C uses glibc, although nixpkgs' isGnu is false for gnufilc0. The unnecessary standalone argp overrides glibc's implementation and traps in hol_entry_short_iterate when printing --help.

2229buildInputs=
builtins.filterdep: dep.pname or "" ≢ "argp-standalone" old.buildInputs
2232env=
old.env or { } // NIX_LDFLAGS = pkgs.lib.replaceStrings"-largp" "" old.env.NIX_LDFLAGS or "";
2237postPatch=
old.postPatch or ""
+
# Fil-C programs can run on the build platform, so nixpkgs skips
# its cross substitutions, but pkg-config is still target-prefixed.
# Keep the working C/C++ probes and select the target's wrapper.
substituteInPlace SConstruct admin/pkgconfig.py \
--replace-fail 'pkg-config' "$PKG_CONFIG"
# SCons 4.9 added extra_libs before call; the old positional calls
# now try to link libraries named after each character of lrint().
substituteInPlace SConstruct \
--replace-fail '"c", "lrint(3.2);"' '"c", call="lrint(3.2);"' \
--replace-fail '"c", "lrintf(3.2);"' '"c", call="lrintf(3.2);"'
# This is a build tool, not a target library. Use its native binary
# without putting native D-Bus libraries on the Fil-C link path.
substituteInPlace SConstruct admin/dbus.py \
--replace-fail 'dbusxx-xml2cpp' \
'${pkgs.buildPackages.dbus_cplusplus}/bin/dbusxx-xml2cpp'
# Clang rejects these as C++11 user-defined literal suffixes.
substituteInPlace src/libstreaming/digidesign/DigidesignTransmitStreamProcessor.cpp \
--replace-fail '"PRIu64"' '" PRIu64 "'
# glibc's explicit-scheduling pthread_create path has an unsupported
# inline syscall. Only the debug logger uses ordinary scheduling;
# leave the audio threads' real-time behavior unchanged.
substituteInPlace config_debug.h.in \
--replace-fail 'DEBUG_MESSAGE_BUFFER_REALTIME 1' \
'DEBUG_MESSAGE_BUFFER_REALTIME 0'
2263doCheck=
true
2264checkPhase=
runHook preCheck
# SCons creates the SONAME symlink only during installation.
ln -s libffado.so src/libffado.so.2
export LD_LIBRARY_PATH="$PWD/src:''${LD_LIBRARY_PATH-}"
grep -Fx '#define HAVE_LRINT 1' config.h
grep -Fx '#define HAVE_LRINTF 1' config.h
# Hardware-free checks. The utility and buffer tests always exit
# zero even on assertion failures, so inspect their results too.
src/test-unittests-util > util.log 2>&1
cat util.log
grep -Fx 'passed: 5' util.log
grep -Fx 'failed: 0' util.log
tests/test-devicestringparser
tests/test-timestampedbuffer -v 0
tests/test-timestampedbuffer -v 0 -s 999 -c 2000
tests/test-bufferops > bufferops.log 2>&1
cat bufferops.log
test "$(grep -c 'Checking results' bufferops.log)" = 3
if grep -F 'bad result' bufferops.log; then exit 1; fi
# Device discovery, streaming and cycle-time ioctls require a
# FireWire controller/interface; build their tests, don't run them.
runHook postCheck
2288postInstallCheck=
old.postInstallCheck or ""
+
# Exercise installed tools and their argument parser, not hardware.
"$bin/bin/ffado-test" --help
"$bin/bin/ffado-dbus-server" --help
2296pipewire

1.6.6 test-loop/cancel_thread_while_dispatching aborts in pthread_cancel: "libgcc_s.so.6661 must be installed for pthread_cancel to work". The current Fil-C runtime does not support this cancellation path.

broken"PipeWire test-loop cancellation requires unsupported Fil-C pthread_cancel (libgcc_s.so.6661)"

Linker-section registration, pointer capabilities and test runtime fixes; see docs/shared-library-unblocks.md.

patch./patches/pipewire-log-topics.patch
patch./patches/pipewire-test-suites.patch
patch./patches/pipewire-pulse-modules.patch
patch./patches/pipewire-cpu-probe.patch
patch./patches/pipewire-pointer-arithmetic.patch
patch./patches/pipewire-pointer-properties.patch
patch./patches/pipewire-test-runtime.patch
use
λold

Valgrind's client requests are inline assembly on pointers, which Fil-C rejects at run time; every pwtest suite died on them.

2313env=
old.env or { } // NIX_CFLAGS_COMPILE = "-DNVALGRIND";

The Fil-C cc-wrapper shares the build GCC's role infix (x86_64_unknown_linux_gnu), so with a build compiler in depsBuildBuild it also reads the *_FOR_BUILD flags. The native GLib (for gdbus-codegen) then landed in RUNPATH ahead of the Fil-C GLib, and the modules using GLib failed to dlopen. Only the build GCC's compiler checks use these flags here.

2322preConfigure=
old.preConfigure or ""
+
unset NIX_LDFLAGS_FOR_BUILD NIX_CFLAGS_COMPILE_FOR_BUILD
2325preCheck=
old.preCheck or ""
+
export FUGC_THREADS="$NIX_BUILD_CORES"
# Two independently loaded modules share the pointer-string table
# (pipewire-pointer-properties.patch) under concurrent use.
for module in a b; do
$CC -shared -fPIC -I../spa/include \
${./tests/pipewire-pointer-module.c} -Lspa -lspa-filc-pointers \
-Wl,-rpath,"$PWD/spa" -o "pointer-$module.so"
done
$CC -O2 ${./tests/pipewire-pointer-properties.c} -ldl -pthread \
-o pointer-check
timeout 30 ./pointer-check
mesonCheckFlagsArray+=(--num-processes "$NIX_BUILD_CORES")

The GStreamer elements register GTypes through gsize once-inits.

removeMesonFlag"-Dgstreamer"
addMesonFlag"-Dgstreamer=disabled"
addMesonFlag"-Dgstreamer-device-provider=disabled"

PipeWire links libsystemd; it does not need the service manager's programs.

argsystemd = final.systemdLibs;

ROC's build takes ragel (and so colm and a target GCC) from the host package set.

argrocSupport = false;

ModemManager's libmbim, libqmi and libqrtr generate GType code that assumes integer GTypes; PipeWire only uses it for HFP modem calls.

argmodemmanager = final.modemmanager.overrideAttrsold: meta = old.meta // badPlatforms = prev.stdenv.hostPlatform.system;;;

Nixpkgs enables the native HFP backend's ModemManager support whenever BlueZ is available.

removeMesonFlag"-Dbluez5-backend-native-mm=enabled"
addMesonFlag"-Dbluez5-backend-native-mm=disabled"
2364libglvnd
configure"--disable-asm"
2368libinput
pin"1.29.1" "sha256-4BVHu9370s5hqugS/Lj/JEXwXXmmVRSMfjkvqpI9aq8="
patch./ports/patch/libinput-1.29.1.patch

1.29 predates the Lua plugin option Nixpkgs 26.05 sets.

argluaSupport = false;
removeMesonFlag"-Dlua-plugins=disabled"
arglibwacom = pkgs.hello;
addMesonFlag"-Dlibwacom=false"
addMesonFlag"-Ddebug-gui=false"
2380libxkbcommon=
2381libxkbcommon

The upstream 1.11 X11 test hunk does not apply to 1.13, and X11 is disabled here. Keep only the still-needed version-script adaptation.

patch./patches/libxkbcommon-version-scripts.patch
skipTests"eh"
addMesonFlag"-Denable-x11=false"
2400openexr
patch./patches/openexr-chunk-table-pointer.patch
patch./patches/openexr-frame-buffer-pointers.patch

Inline assembly with memory operands (the DWA AVX path, fnstcw and fldcw for FPU exceptions) is beyond Fil-C, as are the AVX2 gathers in the vendored OpenJPH.

addCMakeFlag"-DOPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX=OFF"
addCMakeFlag"-DIEX_HAVE_CONTROL_REGISTER_SUPPORT=OFF"
addCMakeFlag"-DIEX_HAVE_SIGCONTEXT_CONTROL_REGISTER_SUPPORT=OFF"
addCMakeFlag"-DOJPH_DISABLE_SIMD=ON"
use
λold

The exhaustive threaded tile matrix exceeds CTest's 1500-second default with Fil-C under load. Keep the whole test, with a larger bound.

2413postPatch=
old.postPatch or ""
+
echo 'set_tests_properties(OpenEXR.testMultiTiledPartThreading PROPERTIES TIMEOUT 7200)' >> src/test/OpenEXRTest/CMakeLists.txt

Compares OpenEXRCore's CPU detection with the C++ library's, which without the inline assembly no longer reports AVX.

2418disabledTests=
old.disabledTests or [ ] ++ "OpenEXRCore.testCPUIdent"
2435rdkafka
use
λold

The CRC32C path detects SSE 4.2 with inline cpuid, which Fil-C cannot run; every client died in rd_kafka_new(). Use the software CRC32C.

2440postPatch=
old.postPatch or ""
+
substituteInPlace packaging/cmake/config.h.in --replace-fail \
'#cmakedefine01 WITH_CRC32C_HW' '#define WITH_CRC32C_HW 0'
2448uwimap=
2448uwimap

Fil-C's libc has no vfork; c-client only uses it to spawn rsh/ssh.

addCFlag"-Dvfork=fork"
2454libraw
use
λold

The pkg-config files name GCC's C++ runtime; Fil-C's is libc++. Magick++ failed to link against -lstdc++.

2458postPatch=
old.postPatch or ""
+
substituteInPlace libraw.pc.in libraw_r.pc.in --replace-fail -lstdc++ -lc++
2464imagemagick
arg

librsvg is Rust, which has no Fil-C target.

2467librsvgSupport=
false

libheif's x265 encoder builds its 10/12-bit variants with GCC.

2469libheifSupport=
false

libjxl's Highway picks SIMD targets with xgetbv spelled as raw opcode bytes, which Fil-C refuses; past that it would dispatch to AVX2 and AVX-512 intrinsics, which Fil-C does not all lower (the AVX2 gathers in OpenEXR's OpenJPH did not).

2474libjxlSupport=
false
2478libevdev
pin"1.11.0" "sha256-Y/TqFImFihCQgOC0C9Q+TgkDoeEuqIjVgduMSVdHwtA="
patch./ports/patch/libevdev-1.11.0.patch
2483valgrind
broken"not yet ported"

objc_msgSend and the block trampolines are assembly, and Clang's GNUstep ABI registers classes and selectors through __start_/__stop_ section symbols, which Fil-C does not provide (docs/filc-findings.md).

2487gnustep-libobjc
broken"Objective-C runtime not ported"
2489cups
arggnutls = final.openssl;

Its pname is ghostscript-with-X, so name the attribute explicitly.

2500dbus
argsystemdMinimal = final.systemdLibs;
arglibapparmor = final.hello;

dbus 1.16 builds with Meson.

removeMesonFlag"-Dapparmor"
addMesonFlag"-Dapparmor=disabled"

Development Tools & Libraries

let
2512fmtPort=
λfmt argStorePatch
2514fmt for fmt

Works around Fil-C's clang passing small records that contain unions as integers, which dropped the pointers in one-argument make_format_args stores (wide and custom-type formatting).

patchargStorePatch
use

float_test.isnan: the Fil-C runtime leaves FE_INEXACT set at start. util_test.format_system_error: allocating SIZE_MAX / 2 bytes is a Fil-C safety panic, not std::bad_alloc. See docs/filc-findings.md.

2523preCheck=
export GTEST_FILTER=-float_test.isnan:util_test.format_system_error
uses for patch use
in
2535asio

Boost.Coroutine (v1) needs fcontext and is not in the Boost port; only the spawn examples use it.

removeConfigureFlag"--enable-boost-coroutine"

The same io_context executor fix as Boost.Asio's.

patch./patches/asio-io-context-executor-pointer.patch
use
λold

FilPizlonator's frame-slot coloring needs well over an hour to compile this test at -O2 (10 s at -O0); see "Frame-slot coloring is cubic" in docs/filc-findings.md. Drop it until the fork has the linear coloring.

2546postPatch=
old.postPatch or ""
+
sed -i '/^\tunit\/execution\/any_executor \\$/d' src/tests/Makefile.am
! grep -q '^.unit/execution/any_executor ' src/tests/Makefile.am
2553clucene_core

libc++ drops std::binary_function in C++17; the patch Nixpkgs uses for Darwin removes it from the (installed) headers.

patch
pkgs.fetchpatch
2558url=
"https://869170.bugs.gentoo.org/attachment.cgi?id=858825"
2559hash=
"sha256-TbAfBKdXh+1HepZc8J6OhK1XGwhwBCMvO8QBDsad998="

Nixpkgs skips the suite: cl_test is not built by default, and building it needs C++14, a missing <unistd.h>, and then fails on the contribs tests' include paths. Index and search through the installed headers.

use
2566doInstallCheck=
true
2567installCheckPhase=
runHook preInstallCheck
$CXX ${./tests/clucene-core.cpp} -I$out/include -I$out/lib \
-L$out/lib -Wl,-rpath,$out/lib -lclucene-core -lclucene-shared \
-o clucene-check
./clucene-check
runHook postInstallCheck
2578doxygen
use
λold

Release builds turn on IPO, which has CMake archive with llvm-ar (missing, and Fil-C has no LTO anyway), as Nixpkgs does on Darwin.

2582postPatch=
old.postPatch
+
substituteInPlace CMakeLists.txt \
--replace-fail 'set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)' \
'set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)'

The suite runs doxygen on each test input and compares the XML output with xmllint. 012_cite needs bibtex to resolve citations; that is not Fil-C.

2590doCheck=
true
2591nativeCheckInputs=
old.nativeCheckInputs or [ ] ++ pkgs.libxml2.bin
2592checkPhase=
runHook preCheck
ctest -E '^012_cite$' --output-on-failure -j$NIX_BUILD_CORES
runHook postCheck
2600ntk

FLTK-era sources use register, an error in Clang's default C++17.

addCFlag"-Wno-register"

Page headers and stack marks are tagged pointers stored as size_t.

patch./patches/z3-page-headers-pointers.patch
use
λold

Nixpkgs' import check runs the build platform's Python, which finds neither the Fil-C Python's site-packages nor a loadable libz3. Solve something through the bindings with the Fil-C Python instead.

2612pythonImportsCheck=
[ ]
2613postInstallCheck=
old.postInstallCheck or ""
+
PYTHONPATH=$python/${final.python3.sitePackages} ${final.python3}/bin/python3 -c '
import z3
x = z3.Int("x")
s = z3.Solver()
s.add(x > 2, x < 4)
assert s.check() == z3.sat and s.model()[x].as_long() == 3
print("z3 python ok")'
2625capstone

csh is a size_t holding the handle's address, which drops the capability; every call after cs_open trapped.

patch./patches/capstone-handle-ptrtable.patch
2631glog
patch./patches/glog-filc-refused-signals.patch
use

Excluded besides Nixpkgs' "logging":

  • striplog*: they catch LOG(FATAL)'s abort() with a SIGABRT handler, but Fil-C's abort() stops the process without raising SIGABRT (docs/filc-findings.md).
  • stacktrace, symbolize: they take code addresses of labels and functions and expect native frames; Fil-C has neither.
2640checkPhase=
runHook preCheck
ctest -E "^(logging|striplog.*|stacktrace|symbolize)$" --output-on-failure
runHook postCheck
2648unittest-cpp
use
λold

CrashingTestsAreReportedAsFailures calls a null function pointer and expects the SIGSEGV handler to turn that into a failure. Under Fil-C the call is a safety panic, and SIGSEGV handlers are refused.

2653postPatch=
old.postPatch or ""
+
substituteInPlace tests/TestTest.cpp --replace-fail \
'#if defined(NDEBUG)' '#if defined(NDEBUG) && !defined(__FILC__)'
2660doctest
addCFlag"-Wno-reserved-macro-identifier"
addCFlag"-Wl,-lm"

The self-tests install signal handlers on an alternate stack (sigaltstack) and break into the debugger with llvm.debugtrap; Fil-C supports neither. The library is header-only.

skipCheck"sigaltstack and debugtrap"
2669catch2

As for Catch2 v3 below, but v2 is a single header: turn its fatal-signal handler (sigaltstack) off by default under Fil-C.

use
λold
2673postPatch=
old.postPatch or ""
+
substituteInPlace single_include/catch2/catch.hpp --replace-fail \
'#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED' \
'#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#if defined(__FILC__) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS)
#define CATCH_CONFIG_NO_POSIX_SIGNALS
#endif'

Named explicitly: the pname is "catch2", which is Catch2 v2's attribute.

2686catch2_3=
2686catch2_3

Catch2's fatal-signal handler runs on an alternate stack (sigaltstack), which Fil-C does not support; every test run aborted in FatalConditionHandler::engage_platform. Fil-C also refuses handlers for SIGSEGV and the like, so the handler could not work anyway. The option is written to catch_user_config.hpp, so test suites that link this Catch2 skip the handler too.

addCMakeFlag"-DCATCH_CONFIG_NO_POSIX_SIGNALS=ON"

Their suites use doctest, whose signal handling needs sigaltstack.

2698nlohmann_json
addCMakeFlag"-DCMAKE_CXX_FLAGS=-DDOCTEST_CONFIG_NO_POSIX_SIGNALS"
2701toml11
addCMakeFlag"-DCMAKE_CXX_FLAGS=-DDOCTEST_CONFIG_NO_POSIX_SIGNALS"
2705gettext
useold: env = old.env // gettextNeedsLdflags = false;;
2713elfutils
configure"--disable-symbol-versioning"
configure"--disable-debuginfod"
addCFlag"-Wno-error=unused-parameter"
argenableDebuginfod = false;

0.194's configure requires pkg-config; Nixpkgs adds it only for debuginfod.

toolpkgs.pkg-config
skipTests"some tests fail"
2723libcbor
patch./patches/libcbor-test-math.patch

Fil-C emits instrumented objects; the final native linker cannot consume the LLVM bitcode produced by libcbor's automatic IPO selection.

addCMakeFlag"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF"
addCMakeFlag"-DWITH_EXAMPLES=OFF"
addCMakeFlag"-DSANITIZE=OFF"
usedoCheck = true;
2733libapparmor

Configure runs the target Python config tool when linking its extension. Since 4.1 it also imports setuptools with that interpreter.

configure"PYTHON=${final.python3.withPackagesps: ps.setuptools}/bin/python3"
configure"PYTHON_CONFIG=${final.python3}/bin/python3-config"
2743libcap_ng=
2743libcap_ng
use
λold

capng_change_id applies ambient capabilities, but the Fil-C runtime rejects prctl(PR_CAP_AMBIENT) with ENOSYS, so it returns -9.

2747postPatch=
old.postPatch or ""
+
substituteInPlace src/test/Makefile.am \
--replace-fail "thread_test change_id_test" "thread_test"
2753pam=
2753linux-pam
skipCheck"test setup issues"
2756cmocka
skipTests"some tests fail"
addCMakeFlag"-DWITH_EXAMPLES=OFF"
2761libbsd
serialize

The Fil-C compiler wrapper puts filc-glibc's headers first with -isystem, so libbsd's -isystem include/bsd overlay came after them and its #include_next wrappers never applied (setproctitle_init was undeclared). -I directories are searched before every -isystem one.

use
2768postPatch=
for f in src/Makefile.am src/Makefile.in test/Makefile.am test/Makefile.in; do
substituteInPlace $f --replace-fail '-isystem $(top_srcdir)' '-I$(top_srcdir)'
done
substituteInPlace src/libbsd-overlay.pc.in \
--replace-fail '-isystem ''${includedir}' '-I''${includedir}'
# Fil-C's syscall() stops the program on close_range (436); glibc's
# close_range() goes through the runtime.
substituteInPlace src/closefrom.c \
--replace-fail 'syscall(SYS_close_range, fd, max_fd, flags)' \
'close_range(fd, max_fd, flags)'
# Expected failures, each a Fil-C limitation rather than a libbsd bug:
# explicit_bzero's test needs sigaltstack, which the runtime does not
# support; nlist looks up C names, but Fil-C symbols are pizlonated_*;
# proctitle links libbsd-ctor, whose hand-placed .init_array entry
# Fil-C never calls, so setproctitle_init must be called explicitly.
for f in test/Makefile.am test/Makefile.in; do
echo 'XFAIL_TESTS = explicit_bzero nlist proctitle' >> $f
done
2793rhash
use
2795preConfigure=
sed -i 's/,-soname/ -Wl,-soname/' configure
addCFlag"-DRHASH_NO_ASM=1"
2802fasttext
addCFlag"-Wl,-lm"
2806scrypt
skipTests"some tests fail"
2810libmicrohttpd for pkgs.callPackage./packages/libmicrohttpd.nix { }

Languages

nixpkgs only packages Perl 5.42; the Fil-C port targets 5.40.0.

2816perl5=
2817perl5
arg
2819version=
"5.40.0"
2820sha256=
"sha256-x0A0jzVzljJ6l5XT6DI7r9D+ilx4NfwcuroMyN/nFh8="

Nixpkgs builds perl.pkgs with its own perl5 attribute; use the port.

2822self=
final.perl5

buildPerlPackage puts perl in nativeBuildInputs, which Nixpkgs 26.05 resolves to the package set's build-host splice. That was the build platform's perl, which configured XS modules with its own Config and then loaded the Fil-C objects in their tests. Fil-C programs run on the build machine, so splice the port there. Module fixes from ports/perl-modules.nix apply to the scope, so dependents and withPackages see them.

2830passthruFun=
λargs
let
2833upstream=
import"${prev.path}/pkgs/development/interpreters/perl" callPackage = f: a: a.passthruFun or final.callPackagef a;.perl5args // perlOnBuildForHost = args.self;
used by pkgs

Recover Nixpkgs' passthruFun, which calls callPackage itself.

2839pkgs=
upstream.pkgs.overrideScopeimport./ports/perl-modules.nix
uses upstream
in
//
2843inherit
pkgs
2844withPackages=
f: upstream.buildEnv.overrideextraLibs = fpkgs;
patch./ports/patch/perl-5.40.0.patch
patch./patches/perl-5.40-only-c-locale.patch
patch./patches/perl-5.40-encode-shared-ptrtable.patch
patch./patches/perl-5.40-b-overlay-key.patch
patch./patches/perl-5.40-digest-sha-ptrtable.patch
patch./patches/perl-5.40-custom-op-ptrtable.patch
patch./patches/perl-5.40-mro-ptrtable.patch
use
λold

postPatch replaces the bundled Compress-Raw-Zlib with a newer release, discarding the port's typemap change.

2857postPatch=
old.postPatch
+
substituteInPlace cpan/Compress-Raw-Zlib/typemap \
--replace-fail '$var = INT2PTR($type, tmp);' \
'$var = zptrtable_decode(Perl_xsub_ptrtable, tmp);'
skipCheck"too slow"

NO overrides arg - that breaks withPackages!

2870python312=
2870python312
pin"3.12.5" "sha256-+oouEsXmILCfU+ZbzYdVDS5aHi4Ev4upkdzFUROHY5c="
patch./ports/patch/Python-3.12.5.patch
patch./patches/python-code-header-cxx.patch
patch./patches/python-filc-triplet-detection.patch
patch./patches/python-faulthandler.patch

nixpkgs' separate debug info adds -Wa,--compress-debug-sections, which Fil-C's assembler rejects.

useseparateDebugInfo = false;
argenableLTO = false;
configure"--without-pymalloc"
configure"--without-freelists"
configure"ac_cv_func_chflags=no"
configure"ac_cv_func_lchflags=no"
configure"ac_cv_func_sigaltstack=no"
configure"ac_cv_gcc_asm_for_x64=no"
configure"ac_cv_gcc_asm_for_x87=no"
configure"ac_cv_gcc_asm_for_mc68881=no"

Nixpkgs assumes x87 double rounding when cross compiling. With no x87 inline assembly to fix the precision, that disables short float repr (repr(12.3) == '12.300000000000001'). Fil-C uses SSE2 arithmetic.

removeConfigureFlag"ac_cv_x87_double_rounding=yes"
configure"ac_cv_x87_double_rounding=no"

Fil-C's libc is libc.so.6666. CDLL("libc.so.6") loaded the runtime's inner libc instead, where no Fil-C function is found (finix's limine hook died on libc.syncfs), and find_library("c") found nothing.

use
λold
2897postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace Lib/ctypes/__init__.py --replace-fail \
' self._name = name' \
' if name == "libc.so.6": name = "libc.so.6666"
self._name = name'
substituteInPlace Lib/ctypes/util.py --replace-fail \
' # See issue #9998' \
' if name == "c": return "libc.so.6666"
# See issue #9998'
argpackageOverrides = import./ports/pythonPorts-as-overlay.nix pkgs;
2918ruby_3_3=
patch./ports/patch/ruby-3.3.10.patch

Upstream's Fil-C port uses pthread coroutines, not native assembly.

configure"--with-coroutine=pthread"

Autoconf 2.73 would record CC as "clang -std=gnu23" in rbconfig, which native gem extensions then inherit; keep the compiler default.

configure"ac_cv_prog_cc_c23=no"

Disable ractor shareability deep checking - requires rb_objspace_reachable_objects_from which isn't implemented in Fil-C. Return false = conservatively assume not shareable.

astRewrite"ractor.c" "c" "bool rb_ractor_shareable_p_continue($PARAM) { $$$BODY }" "bool rb_ractor_shareable_p_continue($PARAM) { #ifdef __FILC__ return false; #else $$$BODY #endif }"

Also patch rb_ractor_make_shareable to skip traversal

astRewrite"ractor.c" "c" "VALUE rb_ractor_make_shareable(VALUE $OBJ) { $$$BODY }" "VALUE rb_ractor_make_shareable(VALUE $OBJ) { #ifdef __FILC__ FL_SET_RAW($OBJ, RUBY_FL_SHAREABLE); return $OBJ; #else $$$BODY #endif }"

Terminal & System

2957libcap
pin"2.70" "sha256-I6bviq2vHj6HX2M7stEWz++JUtunvHxWmxNFjhlSsw8="
argwithGo = false;
argusePam = false;
2964binutils-unwrapped=
2964binutils-unwrapped
src"2.43.1" "sha256-vsqsXSleA3WHtjpC+tV/49nXuD9HjrJLZ/nuxdDxhy8=" version: "mirror://gnu/binutils/binutils-${version}.tar.bz2"
patch./ports/patch/binutils-2.43.1.patch
2972kbd

ports/patch/kbd-2.6.4.patch rebased onto Nixpkgs' 2.9.

patch./patches/kbd-2.9-filc.patch

dlopen()s zlib, bzip2, xz and zstd for compressed keymaps.

dlopenByPath

Only there to act on the .note.dlopen notes. Under Fil-C it found no notes and replaced the RUNPATH with kbd's own lib directory, dropping the Fil-C runtime's (it skips libraries beside the interpreter, which ld-fil1 does not search by default), so loadkeys could not start.

usedontAutoPatchelf = true;

Nixpkgs' own systemd (260); systemdMinimal and systemdLibs derive from this port through .override, so all three get the same fixes. patches/systemd-260-filc.patch rebases upstream Fil-C's 256.4 patch (ports/patch/systemd-256.4.patch) and adds what 260 needs; its header lists each change.

2990systemd=
2990systemd
patch./patches/systemd-260-filc.patch
argwithKexectools = false;
argwithLibseccomp = false;

EFI/BPF/kexec emit kernel or firmware code, outside Fil-C userspace.

arg
2996withLibBPF=
false
2997withEfi=
false
2998withBootloader=
false

257+ dlopen()s zstd, lz4, xz, kmod, cryptsetup, PAM, ...; without the notes the initrd gets no libkmod and loads no kernel modules.

dlopenByPath
use

the automatic patchelf hook was segfaulting while trying to patch some debug info files?!

3006separateDebugInfo=
false

Nixpkgs 26.05 bans bash from the closure; libapparmor's Python bindings bring the Fil-C interpreter (and its bash) along.

3009disallowedRequisites=
[ ]

this seems to not be a real problem

useautoPatchelfIgnoreMissingDeps = "*";
broken"not yet ported"

The tests run texi2any with the build platform's Perl, which cannot load the Fil-C build's XS modules (and its headers lack crypt.h).

3024texinfoInteractive=
3024texinfoInteractive
skipCheck"tests run the build platform's Perl against Fil-C XS modules"
3029ttyd
skipCheck"network service tests"
3033acl

The *xattrat calls and openat2 went through raw syscall(), which stops a Fil-C program; setfacl died in NixOS's resolvconf service.

patch./patches/acl-2.4-filc.patch
3043e2fsprogs
argwithFuse = false;
skipTests"requires special setup"
3048sqlite
arginteractive = true;
skipCheck"too slow"
removeCFlag"-DSQLITE_ENABLE_STMT_SCANSTATUS"

The suite dumps deeply nested values recursively; Fil-C frames are larger than native ones and overflow the default 8 MiB stack.

use
λold
3058preInstallCheck=
old.preInstallCheck or ""
+
ulimit -s 65536

callPackage splices python3Packages by name, and the build platform's is 3.13, so setuptools came from 3.13 while the build ran the ported 3.12. The 3.12 set splices against its own build-platform 3.12.

3067nixos-rebuild-ng
argpython3Packages = final.python312.pkgs;

A test uses Generator's one-argument form, which needs Python 3.13.

use
λold
3071postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace tests/test_tmpdir.py \
--replace-fail 'typing.Generator[None]' 'typing.Generator[None, None, None]'

Fil-C's libc has no vfork. At shutdown PID 1 vforks a child to reboot and stays suspended until the child is gone; fork and wait for it instead.

3083finit
use
λold
3085postPatch=
old.postPatch or ""
+
"\n"
+
substituteInPlace src/sig.c --replace-fail 'if (vfork()) {' \
'if (({ pid_t p = fork(); if (p > 0) waitpid(p, NULL, 0); p; })) {'

Fil-C's syscall() stops the program on clone3 instead of returning ENOSYS, so PID 1 died starting its first service. Start with finit's own fork() fallback, which moves the child into its cgroup after the fork.

+
substituteInPlace src/clone3.c --replace-fail \
'static int use_clone3 = 1;' 'static int use_clone3 = 0;'

Found by Fil-C: keventd NUL-terminates what recv returned, so a uevent that fills its 1024-byte buffer (common during coldplug) wrote one byte past it. Leave room for the terminator.

+
substituteInPlace src/keventd.c --replace-fail \
'recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT)' \
'recv(pfd.fd, buf, sizeof(buf) - 1, MSG_DONTWAIT)'

The upstream port (ports/patch/dhcpcd-10.0.8.patch) predates the move of compat/rbtree.h to vendor/; without it dhcpcd stopped at startup.

3117strace
usepostPatch = "sed -i 's/ vfork/ fork/g' */strace.c";

libunwind's register-level unwinder is hand-written assembly without SaRCAsm annotations. strace uses elfutils for -k instead.

arglibunwind = null;

Web & Network Services

3130redis

Aligned encoded reply buffers; no madvise on the heap after fork.

patch./patches/redis-filc.patch
use
λold
3134makeFlags=
old.makeFlags
++

Redis's default -O3 turns on LTO, which Fil-C does not have.

"OPTIMIZATION=-O2"

The test modules' Makefile hard-codes gcc.

"CC=cc"
"LD=cc"

The tests call pgrep; Nixpkgs' ps here is procps' ps alone.

3142nativeCheckInputs=
old.nativeCheckInputs ++ pkgs.procps
3143checkPhase=
let
3145skips=

The jemalloc shim ignores malloc_conf, and has no per-size accounting or active defragmentation, so fragmentation always reads 1.00.

"--tags -defrag"
''--skiptest "je_malloc_conf compile-time tuning is active"''
''--skiptest "Reduce defrag CPU usage when module data can't be defragged"''

Fil-C gives the program copies of argv, so rewriting them does not change /proc/<pid>/cmdline.

''--skiptest "Process title set as expected"''

Crash reports need SIGSEGV handlers, which Fil-C refuses.

"--skipunit unit/moduleapi/crash"

The key metadata API passes pointers as uint64_t, which drops their capability; the test modules store strings that way.

"--skipunit unit/moduleapi/keymeta"
"--skipunit unit/moduleapi/ksn_notify_side_effect"

They load payloads that request exabyte allocations and expect zmalloc to fail; Fil-C stops the program instead.

''--skiptest "corrupt payload: fuzzer findings - OOM in dictExpand"''
''--skiptest "corrupt payload: fuzzer findings - huge string"''

Crash reports with stack traces: SIGSEGV handlers again, and the port builds without backtrace support.

"--skipunit integration/logging"

redis-cli's cluster tests start nodes and give them a fixed time to agree on the cluster. Under load the Fil-C nodes missed it in two of them (add-node, and functions on add-node) on swa.

"--skipunit unit/cluster/cli"
3173last=
''--skiptest "Check MEMORY USAGE for embedded key strings with jemalloc"''
in
assert pkgs.lib.hasInfixlast old.checkPhase
builtins.replaceStrings"./runtest \\\n" last
"set -o pipefail\n./runtest \\\n"
pkgs.lib.concatMapStringss: s + " \\\n " skips + last + " 2>&1 | sed -u -e 's/\\r/\\n/g' -e 's/\\x1b\\[[0-9;]*m//g'"

The test runner redraws lines with carriage returns and colours them, which leaves the Nix log blank.

old.checkPhase
3192postPatch=
old.postPatch or ""
+
# Nixpkgs' system-jemalloc patch still builds deps/jemalloc, whose
# configure fails; Redis links the jemalloc shim instead.
sed -i 's/^\tDEPENDENCY_TARGETS+= jemalloc$//' src/Makefile
! grep -q 'DEPENDENCY_TARGETS+= jemalloc' src/Makefile
# runtest invokes make itself, outside stdenv's makeFlags. Bind Fil-C
# descriptors to each module's entrypoint even when the built-in
# vectorset also exports RedisModule_OnLoad.
substituteInPlace tests/modules/Makefile --replace-fail \
'SHOBJ_LDFLAGS ?= -shared' 'SHOBJ_LDFLAGS ?= -shared -Wl,-Bsymbolic'

nginx builds, but its worker processes share pointers through shared memory zones, which Fil-C capabilities do not survive; the same rule refuses the PostgreSQL server on Fil-C systems (lib/block-rust-go.nix). Refuse it at evaluation, saying what to do instead.

let
3212refuse=
λold
3213meta=
old.meta or { }
//
3214problems=
old.meta.problems or { }
//
3215filc=
3216kind=
"broken"
3217message=
"nginx cannot be Fil-C: its processes share memory that holds pointers, and a Fil-C pointer's capability does not cross processes. Use lighttpd, or keep nginx native with filc.native = native: { inherit (native) nginxStable; };"
uses use
in
3224nginxStable=
3224nginxStable
refuse
3225nginxMainline=
3225nginxMainline
refuse
3230apacheHttpd=
3230apacheHttpd

Nixpkgs links libgcc_s for pthread_cancel, which the Fil-C libc has.

useold: env = old.env or { } // NIX_LDFLAGS = "";;

Its pointer-size check runs a program, assumed to fail when cross-compiling.

configure"ap_cv_void_ptr_lt_long=no"

A pointer one process stores in shared memory has no capability in another. mod_auth_digest's client table links entries by rmm offset instead; mod_ldap's shared cache, which is pointers and callbacks throughout, gives way to its per-process cache.

patch./patches/httpd-auth-digest-shm-offsets.patch
patch./patches/httpd-ldap-per-process-cache.patch
3248postgresql_18=
3248postgresql_18

x86 inline asm (spinlock, atomics, popcnt) becomes __sync builtins; Datum, which carries pointers, becomes a pointer type; and sorts swap elements whole, so their pointers keep their capabilities.

patch./patches/postgresql-filc.patch

Its libpq, as in the libpq port: Fil-C's filc_allocate_without_exiting is not exit.

use
λold
3256postPatch=
old.postPatch or ""
+
substituteInPlace src/interfaces/libpq/Makefile \
--replace-fail '-e __tsan_func_exit' '-e __tsan_func_exit -e _without_exiting'

No LTO linker plugin for Fil-C; see libpq. Setting CFLAGS drops configure's -O2, and at -O0 Fil-C takes over 15 silent minutes on the grammar (gram.c), which builders stop. Datum is a pointer here, so int-to-Datum conversions are implicit.

useold: env = old.env // CFLAGS = "-O2 -Wno-int-conversion -fdata-sections -ffunction-sections -Wl,--gc-sections";;

Configure assumes a cross build's linker lacks it, and the server's modules need its symbols.

configure"LDFLAGS_EX_BE=-Wl,--export-dynamic"

Glibc's sync_file_range makes its system call with inline asm.

configure"ac_cv_func_sync_file_range=no"

Its tests run a server, whose backends share pointers.

skipTests"the server's processes share pointers"
arg
3278jitSupport=
false
3279perlSupport=
false
3280pythonSupport=
false
3281tclSupport=
false
3286lighttpd
patch./patches/lighttpd-filc.patch
patch./patches/lighttpd-ls-hpack-pointers.patch

The Fil-C glibc's preadv2 makes the system call with inline assembly, which stops the program; lighttpd reads static files for HTTP/2 with it. Without it, lighttpd uses pread.

configure"ac_cv_func_preadv2=no"
argenableMagnet = true;
argenableWebDAV = true;
argenablePam = true;
arglua5_1 = pkgs.lua5;
skipCheck"test suite issues"
3300tor
arg
3302systemd=
final.systemdLibs
3303libseccomp=
null

libcap = null;

configure"ac_cv_header_execinfo_h=no"
configure"ac_cv_func_backtrace=no"
configure"ac_cv_func_backtrace_symbols=no"
configure"ac_cv_func_backtrace_symbols_fd=no"
configure"ac_cv_search_backtrace=no"
addCFlag"-DED25519_NO_INLINE_ASM=1"

dimap_search picked the onion key by masking uintptr_t copies of two pointers, which drops the capability: every ntor v3 handshake trapped. The patch selects from a pointer pair by index instead, still without a branch on the keys; recheck its assembly when the toolchain changes (docs/filc-findings.md).

patch./patches/tor-dimap-search-pointer.patch

20 pass, 2 skip, 3 fail: test-memwipe reads freed memory on purpose, and the hashx and equix tests want HashX's JIT, which Fil-C can't run.

skipTests"memwipe reads freed memory; hashx and equix want a JIT"
3323torsocks
toolpkgs.glibc.bin
arglibcap = null;
use
3327postPatch=
sed -i \
-e 's,\(local app_path\)=`which $1`,\1=`type -P $1`,' \
src/bin/torsocks.in
skipTests"2 failing tests"

Alternative Implementations & VMs

3339tinycc=
3339tinycc
patch./patches/tinycc-alignment.patch
use
λold
3342preConfigure=
echo ${old.version} > VERSION
3345configureFlags=
"--cc=$CC" "--ar=$AR" "--crtprefix=${pkgs.glibc}/lib" "--sysincludepaths={B}/include:${pkgs.glibc.dev}/include" "--libpaths=$lib/lib/tcc:$lib/lib:${pkgs.glibc}/lib" "--elfinterp=${pkgs.glibc}/lib/ld-linux-x86-64.so.2"
toolpkgs.glibc.bin
skipTests"-run feature incompatible with Fil-C"
3359quickjs

Nixpkgs' 2026-06-04 release rather than upstream Fil-C's 2024-02-14 snapshot: the old one crashed on greedy regexps under Fil-C and is far too slow for yt-dlp's challenge solver (it asks for >= 2025-04-26).

patch./patches/quickjs-2026-filc.patch

Fil-C frames are larger; the native 1 MiB JS stack limit overflows on yt-dlp's solver, which runs qjs without --stack-size.

addCFlag"-DJS_DEFAULT_STACK_SIZE=4194304"
use
λold
3368doCheck=
true
3369checkTarget=
"test"
3370postCheck=
old.postCheck or ""
+
$CC -UNDEBUG -I. ${./tests/quickjs-sab.c} libquickjs.a \
-lm -lpthread -ldl -o quickjs-sab-test
./quickjs-sab-test
cp ${./tests/quickjs-worker-sab.js} tests/quickjs-worker-sab.js
./qjs tests/quickjs-worker-sab.js

The install check reuses $out for a temporary file.

3378postInstallCheck=
old.postInstallCheck or ""
+
${builtins.placeholder"out"}/bin/qjs ${./tests/quickjs-regexp.js}
3384trealla
arglineEditingLibrary = "readline";
use
3387version=
"unstable-2026-09-05"

GitHub's archive bytes for this commit changed; hash the contents.

3389src=
pkgs.fetchFromGitHub
3390owner=
"trealla-prolog"
3391repo=
"trealla"
3392rev=
"12f4cbd7fc2269265e7306775ded2f6410671499"
3393hash=
"sha256-PL5RyiakGDyFLnoSiOS5/b2AoRNwqoG7W+ShYsNl5a4="
use
λold
3397postPatch=
builtins.replaceStrings"Makefile" "GNUmakefile" old.postPatch
3400makeFlags=
old.makeFlags ++ "READLINE=1" "LIBDIR=$(out)/share/trealla"
3404postInstall=
old.postInstall or ""
+
mkdir -p $out/share/trealla/library
find library -name '*.pl' -exec cp --parents -t $out/share/trealla {} +
patch./patches/trealla-filc-ffi-zptrtable.patch
patch./patches/trealla-filc-tabling-cursors.patch
patch./patches/trealla-goal-expansion-share-cells.patch
skipTests"runtime coverage lives in checks.x86_64-linux.trealla"

SWI-Prolog with the core and its packages that need no further libraries, plus PCRE, YAML and SSL. Left out: Java (JPL), ODBC/CQL, Berkeley DB, Python (janus, MQI), xpce and the Qt console, the archive package, readline and libedit, the C++ interface (cpp) and tcmalloc. The patch keeps capabilities where SWI stores pointers as integers (VM code arguments, stack offsets, foreign redo contexts, PL_put_pointer through an exact ptrtable), rebases pointers into moved blocks instead of adding the distance moved, leaves objects other threads may still read to Fil-C's collector, and measures the C stack at the frame setjmp records rather than at a local's address, which Fil-C may keep in the heap. Pointers that other threads replace (by CAS or assignment) while one reads them without a lock are declared ATOMIC_PTR(T), _Atomic(T), so every access is atomic: under Fil-C a plain pointer load reads address and capability separately, tears against a racing store and traps (nanofil/docs/m4.md, SWI-Prolog).

3431swi-prolog
arg
3433withDb=
false
3434withJava=
false
3435withOdbc=
false
3436withPython=
false
3437withGui=
false
3438withNativeCompiler=
false
patch./patches/swi-prolog-9.2.9-filc.patch
use
λold
3442buildInputs=
builtins.filterp: ¬builtins.elemp.pname or "" "gperftools" "libarchive" "readline" "libedit" old.buildInputs
3451cmakeFlags=
old.cmakeFlags
++
"-DUSE_TCMALLOC=OFF"
"-DINSTALL_DOCUMENTATION=OFF"

Fil-C has no sigaltstack; it catches stack overflow itself.

"-DHAVE_SIGALTSTACK="
"-DSWIPL_PACKAGE_LIST=chr;clib;clpqr;inclpr;http;nlp;paxos;redis;stomp;pengines;pldoc;plunit;protobufs;RDF;semweb;sgml;table;utf8proc;zlib;pcre;yaml;ssl"
3458doCheck=
true
3459checkPhase=
runHook preCheck
# Only http:proxy runs once more when it alone failed: its
# "unused" port is one it found free and released, which a test
# running beside it can take.
ctest -j$NIX_BUILD_CORES --timeout 900 --output-on-failure || {
! grep -qv ':http:proxy$' Testing/Temporary/LastTestsFailed.log &&
ctest --rerun-failed --timeout 900 --output-on-failure
}
runHook postCheck

A smoke test of the installed swipl and its libraries.

3471doInstallCheck=
true
3472installCheckPhase=
runHook preInstallCheck
cat >smoke.pl <<'EOF'
:- use_module(library(clpfd)).
:- use_module(library(sgml)).
:- use_module(library(crypto)).
:- use_module(library(pcre)).
:- initialization(main, main).
main :-
X is 2^200 mod 1000000007, X =:= 499445072,
length(L, 8), L ins 1..8, all_different(L), sum(L, #=, 36),
once(labeling([], L)), L == [1,2,3,4,5,6,7,8],
thread_create(numlist(1, 100000, _), T), thread_join(T, true),
load_html(string("<p class=a>hi</p>"), [element(p, [class=a], [hi])], []),
crypto_data_hash(abc, H, [algorithm(sha256)]),
sub_atom(H, 0, _, _, ba7816bf),
re_matchsub("(\\d+)-(\\d+)", "x 12-34 y", Sub, []),
get_dict(1, Sub, "12"),
garbage_collect, garbage_collect_atoms,
writeln('swipl ok').
EOF
$out/bin/swipl smoke.pl
runHook postInstallCheck
3504kittydoom=
3507luajit
broken"JIT compiler not compatible with Fil-C"
3511rspamd
argwithLuaJIT = false;

Emacs

3518emacs30=
3518emacs30
arg
3520gnutls=
null
3521dbus=
null
3522withX=
false
3523withGTK3=
false
3524withXwidgets=
false
3525withMailutils=
false
3526withNS=
false
3527withPgtk=
false
3528withImageMagick=
false
3529withGpm=
false
3530withSystemd=
true
3531withNativeCompilation=
false
3532withCsrc=
true
3533withCairo=
false
3534withAthena=
false
3535withMotif=
false
3536withDbus=
false
3537withAlsaLib=
false
3538withGlibNetworking=
false
3539withXinput2=
false
3540withJansson=
true

The fork below is a git tree without a generated configure.

3542srcRepo=
true
pin"30.1" "sha256-eTWjpRgLXbA9OQZnbrWPIHPcbj/QYkv58I3IWx5lCIQ="
linkfinal.zlib
use
3547src=
pkgs.fetchFromGitHub
3548owner=
"mbrock"
3549repo=
"emacs"
3550rev=
"5b417a5303636d4b3fbed28d9ff6b41e148caa9b"
3551hash=
"sha256-E/weXr9KaUMSZiVHMphPsfhvlX9RgeUpQSuH52JwQUY="

Nixpkgs' patches target 30.2; the fork is based on 30.1.

skipPatch"02_all_ts-query-pred.patch"
patch./patches/emacs-fork-ts-query-pred.patch
skipPatch"CVE-2026-79992.patch"
patch./patches/emacs-fork-CVE-2026-79992.patch
configure"--with-gnutls=ifavailable"
configure"--with-dumping=none"
configure"--with-pdumper=no"
configure"--with-unexec=no"
configure"--with-native-compilation=yes"
configure"--with-native-compilation-backend=comphack"
configure"--with-comphack-cc=${final.gnufilc0}/bin/clang"
addMakeFlag"NATIVE_COMP_ZYGOTE=yes"
addMakeFlag"NATIVE_COMP_ZYGOTE_JOBS=12"
use
λold
3569preBuild=
old.preBuild or ""
+
# Fil-C's larger native frames overflow the usual 8 MiB stack while
# Comphack compiles large preloaded files such as window.el.
ulimit -S -s 65536
3574postInstall=
old.postInstall or ""
+
# A no-dump Emacs runs loadup.el at startup before startup.el can
# process EMACSNATIVELOADPATH. Make the installed ELNs visible at
# the early path derived from the executable prefix.
ln -s "lib/emacs/${old.version}/native-lisp" "$out/native-lisp"

Fil-C sizes the main thread's stack from RLIMIT_STACK at startup. Byte-compiling large packages such as eat overflows 8 MiB too, so raise the soft limit in every build that uses this Emacs.

3583setupHook=
pkgs.writeText"emacs-setup-hook.sh"
builtins.readFileold.setupHook
+
if [[ $(ulimit -S -s) != unlimited && $(ulimit -S -s) -lt 65536 ]]; then
ulimit -S -s 65536 2>/dev/null || true
fi
skipCheck"some tests fail"

Python Variants

3600python311=
3600python311
broken"use python 3.12"
3604python313=
3604python313
broken"use python 3.12"

Broken / WIP

3611colm
broken"null pointer dereference in bootstrap"

Keyed as written: Nixpkgs' ragel is ragelStable, so ragel follows it.

3617ragelStable=
3617ragelStable
broken"depends on colm which is broken"
3622gnutls

Upstream's 3.8.7.1 fix also applies to Nixpkgs' 3.8.9 release.

patch./ports/patch/gnutls-3.8.7.1.patch
configure"--disable-hardware-acceleration"
3628at-spi2-core
src"2.60.5" "sha256-YFmnfVB0OP9sjW0GAl+Pn1d0+g+Oq+nJsFmxzEHhu8A=" v: "https://download.gnome.org/sources/at-spi2-core/2.60/at-spi2-core-${v}.tar.xz"
patch./ports/patch/at-spi2-core-2.60.5.patch
toolpkgs.python3
addMesonFlag"-Dintrospection=enabled"

glibmm 2.88 needs GLib 2.87; 2.80 is the newest series that accepts the Fil-C GLib 2.80.

3650glibmm_2_68=
3650glibmm_2_68
src"2.80.1" "sha256-8aDA7FFON3S/mTOW8X9yEGtAkSx9fMnRDaMboVUX4/U=" v: "mirror://gnome/sources/glibmm/2.80/glibmm-${v}.tar.xz"
patch./patches/glibmm-gtype.patch

Match the Fil-C GTK 4.14; gtkmm 4.22 needs GTK 4.22.

3657gtkmm4=
3657gtkmm4
src"4.14.0" "sha256-k1CgREt0TKPcaVhuvRtnB1IJIrbZ9PIyEDzmA6Jx7No=" v: "mirror://gnome/sources/gtkmm/4.14/gtkmm-${v}.tar.xz"
use

Fil-C GTK has no X11 backend; run the tests on Broadway instead of Xvfb.

3664nativeCheckInputs=
[ ]
3665checkPhase=
runHook preCheck
export XDG_RUNTIME_DIR="$TMPDIR/runtime"
mkdir -m 700 "$XDG_RUNTIME_DIR"
export GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 GTK_A11Y=none
${final.gtk4.out}/bin/gtk4-broadwayd :5 &
broadway_pid=$!
for _ in $(seq 100); do
[ -S "$XDG_RUNTIME_DIR/broadway6.socket" ] && break
sleep 0.1
done
meson test --print-errorlogs
kill "$broadway_pid"
runHook postCheck

Its pname is libdbusmenu-glib.

3695libgsf
patch./patches/libgsf-gtype-switch.patch

Every test is skipped without unzip on PATH.

useold: nativeCheckInputs = old.nativeCheckInputs ++ pkgs.unzip;
3703libhighscore

--doc-format appeared in gobject-introspection 1.83.2; the Fil-C GI is 1.80, pinned with GLib 2.80. It only selects the doc comment syntax recorded in the GIR.

use
λold
3708postPatch=
old.postPatch or ""
+
substituteInPlace src/meson.build --replace-fail "'--doc-format=gi-docgen'," ""
3711doCheck=
true
3719vala

The build valac has the same patch (ports/build-tools.nix), and its setup hook has the shipped C regenerated.

patch./patches/vala-pointer-once.patch
patch./patches/vala-gen-introspect-gtype.patch
3726dconf
patch./patches/dconf-filc-gtype.patch

Vala is used only to generate API metadata here, not linked into dconf.

arg
3730vala=
pkgs.vala
3731withDocs=
false
use
λold
3734postPatch=
old.postPatch or ""
+
# Keep the ABI checks, comparing against Fil-C's exported names.
sed -i 's/^/pizlonated_/' client/symbols.txt gsettings/symbols.txt

Named explicitly: the pname is "gtk+". GTK 2 has no upstream Fil-C port; this applies the GTK 3 port's pointer-GType changes to 2.24.33 (see docs/gtk-ports.md).

3749gtk3=
3749gtk3
pin"3.24.52" "sha256-gJMfpHKne5oWT2dA48C0RPrGdwBUYy01p/+dZ55ee58="
patch./ports/patch/gtk-3.24.52.patch

GTK3 does not request GLib among its generator inputs itself.

toolfinal.buildPackages.glib
removeMesonFlag"-Dgtk_doc=true"
addMesonFlag"-Dgtk_doc=false"
useold: outputs = builtins.filteroutput: output ≢ "devdoc" old.outputs;
arg
3760x11Support=
false
3761xineramaSupport=
false
3762waylandSupport=
true
3763broadwaySupport=
true
3767gtk4=
3767gtk4
pin"4.14.5" "sha256-VUfyufAGsTOZPgcLh8F4BOBR79o5E/6soRCPor5B4k0="

Nixpkgs' 32-bit Vulkan fix targets newer releases; Vulkan is off here.

skipPatch"fix-32bit-VkImage-null.patch"
patch./ports/patch/gtk-4.14.5.patch
patch./patches/gtk4-broadway-node-alignment.patch
linkfinal.libdrm
addMesonFlag"-Dintrospection=enabled"

Keep the UI toolkit independent of the optional GStreamer video backend and its complete codec/plugin dependency tree.

addMesonFlag"-Dmedia-gstreamer=disabled"
useold: buildInputs = builtins.filterinput: ¬builtins.eleminput.pname or "" "gst-plugins-base" "gst-plugins-bad" old.buildInputs;
arg
3788x11Support=
false
3789xineramaSupport=
false
3790waylandSupport=
true
3791broadwaySupport=
true
3792vulkanSupport=
false
3793trackerSupport=
false
3802graphite2
patch./patches/graphite2-program-pool-capabilities.patch
patch./patches/graphite2-justify-alignment.patch
patch./patches/graphite2-python-pointer-results.patch
use
λold

Let the Fil-C driver supply its runtime, not upstream's explicit GCC runtime. The C linker language and no-libstdc++ test remain.

3809postPatch=
old.postPatch or ""
+
substituteInPlace src/CMakeLists.txt \
--replace-fail '-nodefaultlibs ' "" \
--replace-fail 'target_link_libraries(graphite2 c gcc)' 'target_link_libraries(graphite2 c)'

The text comparison tests load graphite2 through ctypes.

3815nativeBuildInputs=
builtins.filterp: ¬pkgs.lib.hasPrefix"python3" p.pname or p.name or "" old.nativeBuildInputs ++ final.python3.withPackagesps: ps.fonttools

Compare JSON traces as well as printed shaping goldens.

3823cmakeFlags=
old.cmakeFlags ++ "-DGRAPHITE2_NTRACING=OFF"
3827xapian

With more than one descriptor, glibc's nftw opens subdirectories through __openat64_nocancel, a raw syscall that Fil-C's libc still lacks (docs/filc-findings.md). One descriptor avoids that path.

use
λold
3832postPatch=
old.postPatch or ""
+
substituteInPlace tests/harness/unixcmds.cc --replace-fail \
'nftw(filename.c_str(), rm_rf_nftw_helper, 10, flags)' \
'nftw(filename.c_str(), rm_rf_nftw_helper, 1, flags)'
3840proj

The unit tests link GoogleTest, so they need the Fil-C build of it; Nixpkgs lists gtest as a native check input.

use
λold
3844nativeCheckInputs=
builtins.filterp: p.pname or "" ≢ "gtest" old.nativeCheckInputs ++ pkgs.buildPackages.sqlite

test_projinfo.sh runs sqlite3, which a native build finds through the sqlite build input.

3849checkInputs=
old.checkInputs or [ ] ++ final.gtest
3857potrace

Its bsf/bsr helpers branch inside the asm (jnz), which Fil-C's safe inline assembly does not accept. Use the portable versions.

use
λold
3861postPatch=
old.postPatch or ""
+
substituteInPlace src/bitops.h --replace-fail \
'#if defined(HAVE_I386)' '#if defined(HAVE_I386) && !defined(__FILC__)'
3881rsync

The test LD_PRELOADs a shim that finds the real read() with dlsym(RTLD_NEXT, ...), which Fil-C refuses (docs/filc-findings.md).

use
λold
3885preCheck=
old.preCheck
+
export RSYNC_EXCLUDE="$RSYNC_EXCLUDE,source-change-size-continues"
3891kronosnet

Cross builds skip configure's doxygen2man search and leave DOXYGEN2MAN empty, so no man pages are made and install-man3 fails.

configure"DOXYGEN2MAN=${pkgs.buildPackages.libqb}/bin/doxygen2man"

The LanguageMachines stack (ticcutils, timbl, frog, ...).

let

AX_CHECK_ZLIB, AX_CXX_COMPILE_STDCXX_17 and friends come from autoconf-archive. Nixpkgs lists it in buildInputs, where a cross build's aclocal does not look.

3903autoconfArchive=
toolpkgs.buildPackages.autoconf-archive
uses tool

The libraries use ICU's regex and transliterator (icu-i18n) but link only icu-uc and icu-io. GNU ld finds i18n through icu-io's DT_NEEDED; Fil-C's gold does not, so programs linking them failed.

3907icuI18n=
λold
3908postPatch=
old.postPatch or ""
+
substituteInPlace configure.ac --replace-fail \
'[icu-uc >= 50 icu-io]' '[icu-uc >= 50 icu-io icu-i18n]'
uses use
3913port=
λsteps name
3914inherit
name
3915value=
3915… for pkgs.${name}
steps
uses for
in
builtins.listToAttrsmapportautoconfArchive icuI18n "frog" "libfolia" "mbt" "ticcutils" "timbl" "timblserver" ++ mapportautoconfArchive "frogdata" "uctodata"
//
3938ucto=
3938ucto
autoconfArchive
icuI18n

configure asks a bare pkg-config (absent in a cross build) for uctodata's prefix, so the data directory was compiled in as /share/ucto/ and ucto (and frog) found no languages.

use
λold
3945postPatch=
old.postPatch or ""
+
substituteInPlace configure.ac --replace-fail \
'`pkg-config --' '`$PKG_CONFIG --'
3954recode

The warning setup adds gnulib's lib/ with -isystem, which comes after the Fil-C libc's -isystem, so lib/fcntl.h (O_BINARY) was shadowed by libc's. Plain -I searches it first.

configure"--disable-gcc-warnings"

The tests build a Fil-C extension module (from Cython's C output) and import it, so they need the Fil-C Python rather than the build's, without the build Python's module path and sysconfig name.

use
λold
3963preCheck=
old.preCheck or ""
+
unset PYTHONPATH _PYTHON_HOST_PLATFORM _PYTHON_SYSCONFIGDATA_NAME
3966checkFlags=
old.checkFlags or [ ] ++ "PYTHON=${final.python3.withPackagesps: ps.setuptools}/bin/python3"
3972rustc
broken"oh sweet summer child"