ports.nix
Fil-C package ports - list-based structure
Each port: (for pkgs.package [transforms...])
Explicit names: { bash = for pkgs.bash [...]; }
Nixpkgs' Bash patches use -p0; the pinned importer emits -p1 paths. Apply our unwind buffer fix separately without changing their strip level.
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.
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.
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.
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.
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.
Nixpkgs adds LLVM's OpenMP when the compiler is Clang.
Core Libraries
| patch | ./ports/patch/boost-filc.patch | |
1.86's B2 still accepts context-impl from the Context Jamfile. | ||
| pkgs.lib.optional | pkgs.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. | |
| arg | ||
| use | true 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' \ | diff -u ${./tests/boost-test.expected} - done runHook postCheck | |
| map | patch patches | |
| tool | pkgs.autoreconfHook | |
| tool | pkgs.pkg-config | |
| use | Nixpkgs unpacks into icu/source; the upstream tree has icu4c/source. "-p3" ICU disables its upstream suite for cross builds; its "test" target is just a directory. Exercise the real target libraries explicitly. true 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 |
The 78.3 refresh also applies cleanly to 77.1.
Node.js, Ladybird and onlyoffice pin ICU 78.
abseil-cpp is an alias of this LTS branch, so both names get the port.
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 | |
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.
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.
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.
CMake's env emulator must not replace ctest's target path lookup. | ||
| patch | ./patches/ada-cross-emulator-test.patch | |
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 | ||
GTK 2 only serves the gtv demo player; SDL_mixer needs just the library, so keep GTK 2 out of its closure. | ||
| use | old: 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. | ||
| link | final.libx11 | |
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.
Replace inline asm mfence with __atomic_thread_fence (Fil-C can't handle inline asm) | ||
| use | λattrs 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)
])
| pin | "2.7.1" "sha256-NUVSVEuPmQEuUGL31XDsd/FLQSo/9cfY0NrmLA0hfDA=" | |
| patch | ./ports/patch/expat-2.7.1.patch |
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 | ||
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. 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. 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. true 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 | |
| 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 | |
| tool | pkgs.autoreconfHook | |
| configure | "--disable-static" | |
| configure | "--disable-exec-static-tramp" | |
| 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" | |
| arg | nasm = pkgs.hello; | |
| patch | ./ports/patch/libxml2-2.14.4.patch | |
| arg | pythonSupport = false; | |
| skipCheck | "python tests fail" |
| patch | ./ports/patch/libuv-1.52.1.patch | |
| skipTests | "one test failed" |
| patch | ./ports/patch/libxcrypt-4.5.2.patch | |
| skipCheck | "one test fails" |
db and db5 are aliases of db53; override it so all three get the port.
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 | ||
| removeConfigureFlag | "--enable-fat" | |
| configure | "--disable-assembler" |
| pin | "20240808-3.1" "sha256-XwVzNJ13xKSJZxkc3WY03Xql9jmMalf+A3zAJpbWCZ8=" | |
| patch | ./ports/patch/libedit-20240808-3.1.patch |
Special case - libiconv comes from glibc in cross-compilation
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 | ||
Core Utilities
| arg | interactive = true; | |
unwind_protect saves jmp_bufs in a misaligned buffer, losing their capabilities: | ||
| bashUnwindPatch | ||
| skipCheck | "interactive mode issues" | |
| arg | interactive = false; | |
unwind_protect saves jmp_bufs in a misaligned buffer, losing their capabilities: | ||
| bashUnwindPatch | ||
| skipCheck | "test issues" | |
| arg | ||
The Makefile calls plain | ||
| use | ||
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 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. | ||
| use | separateDebugInfo = false; | |
| pin | "0.5.12" "sha256-akdKxG6LCzKRbExg32lMggWNMpfYs4W3RQgDDKSo8oo=" | |
| patch | ./ports/patch/dash-0.5.12.patch |
Pointers that Guile keeps as scm_t_bits words, weak tables on FUGC, continuations without C stack copying: see docs/guile.md.
| 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 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. true 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.
| use | old: nativeBuildInputs = old.nativeBuildInputs ++ filcGuileForBuild; |
Pure Guile. As with gnu-shepherd, configure needs a guile, and its tests run with the Fil-C one.
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. | |
| 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. builtins.filterd: ¬pkgs.lib.hasPrefix"guile" d.name or "" old.nativeBuildInputs ++ guileForBuild 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. 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. 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);' | |
| guileTestsOnFilc |
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 | ||
| guileTestsOnFilc |
| guileTestsOnFilc |
| guileTestsOnFilc |
| 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 | ||
Clang reports an unused static function that GCC does not. | ||
| addCFlag | "-Wno-error=unused-function" | |
| guileTestsOnFilc | ||
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. 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. "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. | |
| use | old: nativeBuildInputs = old.nativeBuildInputs ++ filcGuileForBuild; |
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. 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). 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. 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] == ';')" | |
| patch | ./ports/patch/grep-3.12.patch | |
| skipCheck | "too slow" |
| patch | ./ports/patch/make-4.4.1.patch | |
| arg | guileSupport = false; |
| patch | ./ports/patch/sed-4.10.patch | |
| skipCheck | "too slow" |
| patch | ./ports/patch/tar-1.35.patch | |
| skipPatch | "acl-2.4.0-name-conflicts.patch" | also part of the port |
| arg | aclSupport = false; |
Build Tools
| patch | ./ports/patch/bison-3.8.2.patch | |
| skipTests | "too slow" |
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.
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.
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. 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 | ||
Build without the x86 assembly and intrinsics dispatch. | ||
| removeConfigureFlag | "--target=x86_64-linux-gcc" | |
| configure | "--target=generic-gnu" | |
| arg | runtimeCpuDetectSupport = false; | |
| 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 | ||
Video codecs: build the portable C code paths, without hand-written assembly or intrinsics dispatch.
| removeCMakeFlag | "-DSVT_AV1_LTO=ON" | |
| addCMakeFlag | "-DCOMPILE_C_ONLY=ON" |
Honor allocation-failure returns for sizes that cannot be C objects. | ||
| patch | ./patches/libavif-allocation-size.patch | |
| addCMakeFlag | "-DAOM_TARGET_CPU=generic" | |
Keep the owning malloc pointer's capability in the aligned header. | ||
| patch | ./patches/libaom-allocation-pointer.patch | |
| use | old: passthru = old.passthru or { } // tests = old.passthru.tests or { } // allocation-encoder = import./tests/libaom.nix pkgs = final;;;; | |
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" | |
| ||
| patch | ./patches/onetbb-fil-c.patch | |
| use | λold 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. | |
| addCMakeFlag | "-DBLAKE3_SIMD_TYPE=none" |
Its MMX/SSE routines are yasm assembly, which Fil-C cannot link.
| patch | ./ports/patch/opus-1.5.2.patch | |
Without the x86 intrinsics and their run-time CPU dispatch. | ||
| addMesonFlag | "-Dintrinsics=disabled" | |
| addMesonFlag | "-Drtcd=disabled" | |
| 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.
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. 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 C implementations instead of the perlasm AES, SHA, bignum and RC4 routines.
| addCMakeFlag | "-DENABLE_ASM=OFF" | |
| use |
pname is crypto++.
| use | λold Plain C++ instead of the inline asm and SIMD intrinsics; e.g. SecureWipeBuffer's 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))' |
| use | λold RTENTRY__ annotates the real-time entry points with __attribute__((annotate)), which crashes FilPizlonator. | |
| removeMesonFlag | "-Dtests=disabled" | |
| addMesonFlag | "-Dtests=enabled" |
LTTng-UST tracepoints; the tracer's own tests exercise signal and namespace machinery Fil-C does not provide. | ||
| arg | ||
The experimental Python bindings would need the Fil-C Python. | ||
| addMesonFlag | "-Dpycamera=disabled" | |
| patch | ./patches/libcamera-no-dynamic.patch | |
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" | |
The tests preload umockdev, whose Vala-generated code assumes integer GTypes, and LD_PRELOAD interposition does not apply to Fil-C symbols. | ||
| use | λold false GType is a pointer in Fil-C's GLib. 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'," | |
| 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" | |
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. | |
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 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 | |
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" | |
| patch | ./patches/mbedtls-test-cli-crt-ec-der-len.patch | |
AES-NI, PadLock and bignum inline assembly pass pointers to asm. | ||
| use | ||
libpq refuses to link anything named like exit. Fil-C 0.687 lowers small allocas to filc_allocate_without_exiting, which never exits. | ||
| use | ||
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. | ||
| use | old: 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. | ||
| tool | pkgs.removeReferencesTo | |
| use | ||
Meson's default b_lto would hand bitcode to the linker. | ||
| addMesonFlag | "-Db_lto=false" | |
Compression
| 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" | |
Networking
| 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 | |
| arg | withManual = true; | |
| arg | perlSupport = false; | |
| arg | pythonSupport = true; | |
| arg | sendEmailSupport = false; | |
| arg | zlib-ng = pkgs.zlib; | |
| skipTests | "too slow" | |
| removeMakeFlag | "ZLIB_NG=1" | |
| 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. | ||
| use | preCheck = ""; | |
| use | 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 | |
| arg | withFIDO = 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.
| 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. | ||
| use | old: pkgs.lib.optionalAttrspkgs.lib.elem"--enable-dnstap" old.configureFlags or [ ] buildInputs = old.buildInputs ++ final.protobufc; | |
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
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 old.postCheck or "" + $CC -Iinclude ${./tests/libseccomp-prctl-filter.c} \ -Lsrc/.libs -Wl,-rpath,"$PWD/src/.libs" -lseccomp -o prctl-filter ./prctl-filter | |
| patch | ./ports/patch/keyutils-1.6.3.patch | |
| skipPatch | "after_eq" |
| 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" | |
| use | configurePlatforms = "host"; | |
| use | ||
| 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 | |
| use | let 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 cp ${lock-obj-gnufilc0} src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnufilc0.h cp ${lock-obj-gnufilc0} src/lock-obj-pub.native.h |
The upstream patch is rooted above Nixpkgs' sourceRoot (src/). | ||
| use | λold old.prePatch or "" + patch -p2 < ${./ports/patch/krb5-1.22.2.patch} | |
pname is cyrus-sasl, so name the attribute explicitly.
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.
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 | |
| patch | ./patches/duktape-valstack-rebase.patch | |
| use | true "$out/bin/duk" ${./tests/duktape-valstack.js} |
Graphics
| patch | ./ports/patch/graphene-1.10.8.patch | |
gtk-doc generates an unported GType scanner; GIR generation stays on. | ||
| arg | withDocumentation = false; | |
ports/patch/fontconfig-2.15.0.patch rebased onto Nixpkgs' 2.17. | ||
| patch | ./patches/fontconfig-2.17-filc.patch | |
| use | sed -i 's/ftglue.c/ftglue.c fcfilc.h fcfilc.c/' src/Makefile.am | |
| tool | pkgs.autoreconfHook | |
| skipTests | "tests pass but some test needs weird deps" | |
| patch | ./ports/patch/freetype-2.13.3.patch | |
| skipPatch | "subpixel-rendering.patch" | no need |
| skipPatch | "enable-table-validation.patch" | no need |
| patch | ./ports/patch/harfbuzz-9.0.0.patch | |
| arg | withGraphite2 = false; | |
| skipCheck | "fuzzing fails" |
The upstream 3.4.4 port also applies to Nixpkgs' 3.6.5 release.
| patch | ./patches/gtksourceview4-signal-types.patch | |
| use | ||
| use | doCheck = true; |
The 1.4 series needs the EOL libsoup 2.
| patch | ./patches/gupnp-gtype.patch |
| 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. 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" ${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 |
| 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 | ||
| skipTests | "many failures" | |
| use | mesonFlags = "-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 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 | |
| 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 | ||
| removeMesonFlag | "-Dgi_cross_use_prebuilt_gi=true" | |
| addMesonFlag | "-Dgi_cross_use_prebuilt_gi=false" | |
| use | λold _giscanner is compiled with Fil-C and must be loaded by Fil-C Python. The installed scanner also needs this when inspecting downstream dumpers; a build-only PATH entry would leave those scans broken. 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. 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 |
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" | |
| arg | pipewireSupport = false; | |
| arg | rdpSupport = false; | |
| arg | remotingSupport = false; | |
| arg | vaapiSupport = false; | |
| arg | vncSupport = false; | |
| arg | xwaylandSupport = false; | |
| arg | lcmsSupport = false; | |
| addMesonFlag | "-Dsystemd=false" | |
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 | ||
| patch | ./patches/alsa-seq-unpacked-pointers.patch | |
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" | |
| 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. 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' true 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 |
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. 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. 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. | ||
| arg | systemd = final.systemdLibs; | |
ROC's build takes ragel (and so colm and a target GCC) from the host package set. | ||
| arg | rocSupport = false; | |
ModemManager's libmbim, libqmi and libqrtr generate GType code that assumes integer GTypes; PipeWire only uses it for HFP modem calls. | ||
| arg | modemmanager = 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" | |
| 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. | ||
| arg | luaSupport = false; | |
| removeMesonFlag | "-Dlua-plugins=disabled" | |
| arg | libwacom = pkgs.hello; | |
| addMesonFlag | "-Dlibwacom=false" | |
| addMesonFlag | "-Ddebug-gui=false" | |
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" | |
| 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. | |
| patch | ./patches/libmemcached-clang.patch |
| arg | librsvg is Rust, which has no Fil-C target. false libheif's x265 encoder builds its 10/12-bit variants with GCC. 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). false |
| pin | "1.11.0" "sha256-Y/TqFImFihCQgOC0C9Q+TgkDoeEuqIjVgduMSVdHwtA=" | |
| patch | ./ports/patch/libevdev-1.11.0.patch |
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).
Its pname is ghostscript-with-X, so name the attribute explicitly.
| patch | ./patches/ghostscript-filc.patch |
| arg | systemdMinimal = final.systemdLibs; | |
| arg | libapparmor = final.hello; | |
dbus 1.16 builds with Meson. | ||
| removeMesonFlag | "-Dapparmor" | |
| addMesonFlag | "-Dapparmor=disabled" | |
Development Tools & Libraries
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). | ||
| patch | argStorePatch | |
| 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. export GTEST_FILTER=-float_test.isnan:util_test.format_system_error | |
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. | |
libc++ drops std::binary_function in C++17; the patch Nixpkgs uses for Darwin removes it from the (installed) headers. | ||
| patch | ||
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 | true 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 | |
| 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. 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. true runHook preCheck ctest -E '^012_cite$' --output-on-failure -j$NIX_BUILD_CORES runHook postCheck |
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. [ ] | |
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 | |
| patch | ./patches/glog-filc-refused-signals.patch | |
| use | Excluded besides Nixpkgs' "logging":
runHook preCheck ctest -E "^(logging|striplog.*|stacktrace|symbolize)$" --output-on-failure runHook postCheck |
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 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.
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.
| addCMakeFlag | "-DCMAKE_CXX_FLAGS=-DDOCTEST_CONFIG_NO_POSIX_SIGNALS" |
| addCMakeFlag | "-DCMAKE_CXX_FLAGS=-DDOCTEST_CONFIG_NO_POSIX_SIGNALS" |
| 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" | |
| use | doCheck = true; | |
| skipTests | "some tests fail" | |
| addCMakeFlag | "-DWITH_EXAMPLES=OFF" |
| 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 | 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 | |
Languages
nixpkgs only packages Perl 5.42; the Fil-C port targets 5.40.0.
| arg | 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. λargs | |
| 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 | ||
| skipCheck | "too slow" |
NO overrides arg - that breaks withPackages!
| 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. | ||
| use | separateDebugInfo = false; | |
| arg | enableLTO = 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 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' | |
| arg | packageOverrides = import./ports/pythonPorts-as-overlay.nix pkgs; | |
| 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
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. | ||
| use | dontAutoPatchelf = 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.
| patch | ./patches/systemd-260-filc.patch | |
| arg | withKexectools = false; | |
| arg | withLibseccomp = false; | |
EFI/BPF/kexec emit kernel or firmware code, outside Fil-C userspace. | ||
| arg | ||
257+ dlopen()s zstd, lz4, xz, kmod, cryptsetup, PAM, ...; without the notes the initrd gets no libkmod and loads no kernel modules. | ||
| dlopenByPath | ||
| use | ||
this seems to not be a real problem | ||
| use | autoPatchelfIgnoreMissingDeps = "*"; | |
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 | |
| arg | interactive = true; | |
| skipCheck | "too slow" | |
| removeCFlag | "-DSQLITE_ENABLE_STMT_SCANSTATUS" |
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.
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.
| use | λold 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.
Web & Network Services
Aligned encoded reply buffers; no madvise on the heap after fork. | ||
| patch | ./patches/redis-filc.patch | |
| use | λold The tests call pgrep; Nixpkgs' let 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" ''--skiptest "Check MEMORY USAGE for embedded key strings with jemalloc"'' in builtins.replaceStrings"./runtest \\\n" last 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.
Nixpkgs links libgcc_s for pthread_cancel, which the Fil-C libc has. | ||
| use | old: 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 | |
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 | ||
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. | ||
| use | old: 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 | ||
| 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" | |
| arg | enableMagnet = true; | |
| arg | enableWebDAV = true; | |
| arg | enablePam = true; | |
| arg | lua5_1 = pkgs.lua5; | |
| skipCheck | "test suite issues" | |
| arg | ||
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" | |
Alternative Implementations & VMs
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 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. old.postInstallCheck or "" + ${builtins.placeholder"out"}/bin/qjs ${./tests/quickjs-regexp.js} | |
| arg | lineEditingLibrary = "readline"; | |
| use | ||
| use | ||
| 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).
| arg | ||
| patch | ./patches/swi-prolog-9.2.9-filc.patch | |
| use | λold 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" true 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. true 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 |
Emacs
| arg | null null false false false false false false false false true false true false false false false false false false true The fork below is a git tree without a generated configure. true | |
| pin | "30.1" "sha256-eTWjpRgLXbA9OQZnbrWPIHPcbj/QYkv58I3IWx5lCIQ=" | |
| link | final.zlib | |
| use | ||
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 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. | |
| skipCheck | "some tests fail" | |
Python Variants
Broken / WIP
Keyed as written: Nixpkgs' ragel is ragelStable, so ragel follows it.
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" | |
| 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 | |
| tool | pkgs.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.
Match the Fil-C GTK 4.14; gtkmm 4.22 needs GTK 4.22.
| 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. [ ] 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.
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 | |
| patch | ./patches/dconf-filc-gtype.patch | |
Vala is used only to generate API metadata here, not linked into dconf. | ||
| arg | ||
| use | ||
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).
| 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. | ||
| tool | final.buildPackages.glib | |
| removeMesonFlag | "-Dgtk_doc=true" | |
| addMesonFlag | "-Dgtk_doc=false" | |
| use | old: outputs = builtins.filteroutput: output ≢ "devdoc" old.outputs; | |
| arg | ||
| 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 | |
| link | final.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" | |
| use | old: buildInputs = builtins.filterinput: ¬builtins.eleminput.pname or "" "gst-plugins-base" "gst-plugins-bad" old.buildInputs; | |
| arg | ||
| 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. The text comparison tests load graphite2 through ctypes. |
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 | ||
The test LD_PRELOADs a shim that finds the real read() with dlsym(RTLD_NEXT, ...), which Fil-C refuses (docs/filc-findings.md). | ||
| use | ||
The LanguageMachines stack (ticcutils, timbl, frog, ...).
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.
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.
| autoconfArchive | ||
| icuI18n | ||
configure asks a bare | ||
| use | ||
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 | ||