Fil-C on Nix

Filnix wiki

mbrock/filnix

flake.nix

2description=

Fil-C wrapped as a Nix stdenv

4inputs=

Modified nixpkgs with Fil-C cross-compilation support filc-aarch64: 118d872 plus aarch64 in the gnufilc0 ABI assertion.

7nixpkgs.url=
"github:lessrest/filnixpkgs/e63c68034d742160a48ca80640442337e6356cf4"
8nixpkgs.flake=
false

For the example finix machine and its test (finix/demo.nix). The last revision before finix required finit 5; filnix's Nixpkgs has finit 4.17.

11finix.url=
"github:finix-community/finix/9fafdc3f091e963585a0dd4df028d58c2d66d815"
12finix.flake=
false
15outputs=
λself, nixpkgs, finix, …
let

The system-independent outputs (overlays, NixOS modules and machines) come from x86_64-linux; everything keyed by system comes from both.

26perSystem=
λsystem
let
31filcc=
import./toolchain.nix inherit pkgs;
used by cc
32stagingSources=
33inherit
pkgs
34variant=
"staging"
used by filcc-staging
36filcc-staging=
37inherit
pkgs
uses stagingSources used by cc
40sarcasm=
import./packages/sarcasm.nix inherit pkgs;
41sarcasm-prolog=
42inherit
pkgs filcc
43trealla=
pkgsFilc.trealla
uses pkgsFilc
45zstd-sarcasm=
46inherit
pkgs
47zstd=
uses pkgsFilc
49projeny=
uses pkgs
50runfilc=
import./tools/runfilc.nix inherit pkgs filcc;

The Fil-C package set. blockRustGo marks Rust and Go packages broken (lib/block-rust-go.nix); crossOverlays apply after the ports.

54mkPkgsFilc=
λstaging?, blockRustGo?, crossOverlays?, permittedInsecurePackages?
stagingdefault false
blockRustGodefault false
crossOverlaysdefault [ ]
permittedInsecurePackagesdefault [ ]
let
in
importnixpkgs
65localSystem=
66crossSystem.config=
"${pkgs.stdenv.hostPlatform.parsed.cpu.name}-unknown-linux-gnufilc0"
67config.permittedInsecurePackages=
68config.replaceCrossStdenv=
λbuildPackages, baseStdenv
let
71stdenv=
baseStdenv.overrideinherit cc;
in
→
import./lib/block-rust-go.nix inherit buildPackages lib stdenvAdapters; stdenv
else
81crossOverlays=
final: prev: gnufilc0 = cc; import./ports/overlay.nix pkgs ++ final: prev: tzdata = prev.tzdata.overrideAttrscheckTarget = "check_mild back.ck";; ++ crossOverlays

tzdata's now.ck compares zones from the build date on, so 2026c fails it from 2026-11-01 (Vancouver and Phoenix agree from then). It lints the data, not zic or zdump; run the rest.

The package set of a whole Fil-C system (lib/filc-system.nix): Rust and Go refused, and the native exceptions taken from a native Nixpkgs, the built-in ones for os and those native picks from it.

108mkPkgsFilcSystem=
λos, native?, nativePackages?, nativeNix?
os
nativedefault _: { }
nativePackagesdefault pkgs
nativeNixdefault true
let
116builtin=
nixlib.filterAttrsname: e: nixlib.elemos e.os ∧ name ≢ "nix" ∨ nativeNix import./lib/native-exceptions.nix
uses nixlib
in
121blockRustGo=
true
122crossOverlays=
final: prev: nixlib.mapAttrsname: _: nativePackages.${name} builtin // nativenativePackages

Shared by every system that adds no exceptions of its own.

131pkgsFilcSystem=
nixlib.genAttrs"nixos" "finix" os: mkPkgsFilcSysteminherit os;

Explicit reproduction outputs only; the ordinary package set still refuses this vulnerable PHP unless the caller opts in.

137pkgsFilcPhp84_25=
mkPkgsFilcpermittedInsecurePackages = "php-8.4.25" "php-with-extensions-8.4.25";
143optfil=
import./packages/optfil inherit pkgs pkgsFilc filcc sarcasm;

On staging, the PostgreSQL server marks its main segment with zmark_shared and is built with -fzmark-shared (docs/zmark-shared.md). Release systems still refuse it (lib/block-rust-go.nix).

154pkgsFilcStaging=
155staging=
true
156crossOverlays=
λfinal prev
158postgresql_18=
prev.postgresql_18.overrideAttrs
λold
160env=
old.env // CFLAGS = old.env.CFLAGS + " -fzmark-shared";
168filc-shell-stuff=
169inherit
pkgs filcc runfilc
177filc-world-shell=
filc-shell-stuff.filc-world-shell
178baseline=
179inherit
pkgs filcc sarcasm projeny
uses pkgsFilc
188virt=
189inherit
pkgs filcc
world-pkgs
194emacs-safe=
import./emacs/emacs.nix inherit pkgs pkgsFilc;
used by demo
198emacs-unsafe=
199inherit
pkgs
200pkgsFilc=
uses pkgs
203makeLibei=
erlang: pkgsFilc.callPackage./packages/libei.nix inherit erlang;
205libei=
206libei_27=
makeLibeipkgs.erlang_27
207libei_28=
makeLibeipkgs.erlang_28
209demo=
210inherit
pkgs pkgsFilc filcc libei
216filc-emacs=
emacs-safe.filc-emacs
219nixosImage=
220inherit
pkgs
221inherit self.nixosConfigurations.base
config

Ruby with individual gems for testing - auto-generated for all available gems

225rubyWithGem=
pkgs.lib.mapAttrsname: _: pkgsFilc.ruby.withPackagesps: ps.${name} pkgsFilc.rubyPackages
in
230lib.${system}=
232inherit
mkPkgsFilc mkPkgsFilcSystem

The native Nixpkgs that a Fil-C system's exceptions come from.

234nativePackages=

Fil-C docs, pass and runtime at the pin, for reading (lib/sources.nix): nix build .#lib.x86_64-linux.filc-ref-src

237filc-ref-src=
import./lib/sources.nix inherit pkgs;.filc-ref-src
238filc-staging-ref-src=
import./lib/sources.nix inherit pkgs; variant = "staging";.filc-ref-src

checks.nanofil with arguments, such as { shard = "2/6"; } or { withTrealla = true; } (.github/workflows/nanofil.yml).

245nanofil-check=
λargs

Unsupported ports and known release gaps stay strict and opt-in, outside the ordinary passing contract of flake check.

256diagnostics=
257pipewire=
import./tests/pipewire.nix inherit pkgs pkgsFilc filcc;.pipewire
259pipewire-runtime=
import./tests/pipewire.nix inherit pkgs pkgsFilc filcc;.runtime
261release-fork-known-gaps=
262inherit
pkgsFilc
263suite=
"release-known-gaps"
268checks.${system}=

Bare ports that land on another attribute than the one written.

270port-names=
import./tests/port-names.nix inherit pkgs pkgsFilc;
271port-version-refresh=
import./tests/port-version-refresh.nix inherit pkgs pkgsFilc;
274staging-fork-regressions=
277staging-llvm-jit=
280staging-sealed-closures=
283staging-cxx-coroutines=
286staging-fenv=
289staging-gc-local-arrays=
292staging-link-hygiene=
295staging-wrapper-roles=
298staging-zmark-shared=
302staging-sarcasm=
306staging-sarcasm-fixes=
310unsafe-call-boundary=
import./tests/unsafe-call-boundary.nix inherit pkgs filcc;
313nanofil=
317nanofil-rocq=
321nanofil-docs=
325nanofil-rocq-parse=
import./nanofil/nix/rocq.nix inherit pkgs; filcc = filcc-staging;.parse

The extracted validator on every -O module of the corpus, hello, zlib, Lua and SQLite (.github/workflows/nanofil-gate.yml).

332nanofil-rocq-gate=
333inherit
pkgs
335driver=
import./nanofil/nix/rocq.nix inherit pkgs; filcc = filcc-staging;.model.driver
341nanofil-rocq-full=
342inherit
pkgs
344full=
true
346nanofil-logic-spikes=
347inherit
pkgs
349model=
import./nanofil/nix/rocq.nix inherit pkgs; filcc = filcc-staging;.model

Programs linked with nanofil's IR of user glibc, proved (nanofil/docs/glibc-ir.md); off the main path.

357nanofil-glibc=
358inherit
pkgs
360model=
import./nanofil/nix/rocq.nix inherit pkgs; filcc = filcc-staging;.model
366nanofil-backend=
370nanofil-backend-full=
371inherit
pkgs
373full=
true

The same backend extracted to C++ by Crane.

376nanofil-backend-crane=
379nanofil-hello=

Hello's linked checked module, the Iris proof's fixture.

384nanofil-hello-fixture=
388nanofil-zlib=
392nanofil-lua=
396nanofil-bzip2=
400nanofil-lz4=
404nanofil-sqlite=
408nanofil-sed=
412nanofil-jq=
416nanofil-dash=
420nanofil-xz=
424nanofil-make=
428nanofil-coreutils=
432nanofil-bash=
436nanofil-swipl=
441inherit import./nanofil/nix/python.nix inherit pkgs; filcc = filcc-staging;
nanofil-python nanofil-python-regrtest-plain
449sarcasm-prolog=
450inherit
pkgs filcc sarcasm-prolog
451trealla=
pkgsFilc.trealla
453trealla=
454inherit
pkgs filcc
455trealla=
pkgsFilc.trealla
457zstd-sarcasm=
458inherit
pkgs filcc
461baseline=
baseline.baseline
462openssl-sarcasm=
463inherit
pkgs filcc
464openssl=
pkgsFilc.openssl-sarcasm
466sarcasm=
import./tests/sarcasm.nix inherit pkgs filcc;
467sarcasm-fixes=
import./tests/sarcasm-fixes.nix inherit pkgs filcc;
470libtool-symbols=
import./tests/libtool-symbols.nix inherit pkgs filcc;
473inherit
projeny
474libffi=
475inherit
pkgs filcc
476inherit pkgsFilc
libffi
478gtk2-runtime=
import./tests/gtk2-runtime.nix inherit pkgs pkgsFilc;
481gtk3-runtime=
482inherit
pkgs pkgsFilc
483major=
3
485gnutls-tls=
import./tests/gnutls-tls.nix inherit pkgs pkgsFilc;

The StealMyBitcoin exploit works end to end on the unstripped Nixpkgs PHP 8.4.25 and is thwarted by pkgsFilc.php84_25, the same vulnerable release under Fil-C (docs/php.md).

491php-stealmybitcoin=
492inherit
pkgs
493native=
pkgs.php84.overrideAttrsold: dontStrip = true; separateDebugInfo = false;.withExtensions
λenabled, …
map
λext
ext.extensionName ≡ "pcntl"
→
ext.overrideAttrs
λold

Nix sandboxes may exclude CPU 0. Exercise affinity on allowed CPUs rather than assuming CPUs 0 and 1 exist.

506postPatch=
old.postPatch or ""
+
substituteInPlace ext/pcntl/tests/pcntl_cpuaffinity.phpt \
--replace-fail '$mask = [0, 1];' \
'$mask = array_slice(pcntl_getcpuaffinity(), 0, 2);' \
--replace-fail '["0", "1"]' 'array_map("strval", $mask)'
else
517filc=
519utf8-locale=
import./tests/locale.nix inherit pkgsFilc;
520pthread-pi=
import./tests/pthread-pi.nix inherit pkgsFilc;
521pthread-spin=
import./tests/pthread-spin.nix inherit pkgsFilc;
522fenv=
import./tests/fenv.nix inherit pkgsFilc;
523glibc-dirwalk=
import./tests/glibc-dirwalk.nix inherit pkgsFilc;
524glibc-settimezone=
import./tests/glibc-settimezone.nix inherit pkgsFilc;
527glibc-syscall-fallbacks=
import./tests/glibc-syscall-fallbacks.nix inherit pkgsFilc;
530runtime-prctl-caps=
import./tests/runtime-prctl-caps.nix inherit pkgsFilc;

Boots the exact nixos-image file and checks its userland.

534nixos-image-boot=
535native-exceptions-table=

Boots finixConfigurations.filc-demo; see finix/test.nix.

539finix-filc-demo=
540inherit
pkgs finix
541filnix=
543wrapper-roles=
import./tests/wrapper-roles.nix inherit pkgsFilc;
544gc-local-arrays=
import./tests/gc-local-arrays.nix inherit pkgsFilc;
545pch-union=
import./tests/pch-union.nix inherit pkgsFilc;
546nix-eval=
import./tests/nix-eval.nix inherit pkgsFilc;
547perl-xs-pointers=
import./tests/perl-xs-pointers.nix inherit pkgsFilc;
548python-decimal=
import./tests/python-decimal.nix inherit pkgsFilc;
549python-protobuf=
import./tests/python-protobuf.nix inherit pkgs pkgsFilc;
552cxx-coroutines=
import./tests/cxx-coroutines.nix inherit pkgsFilc;
553pointer-tagging=
import./tests/pointer-tagging.nix inherit pkgsFilc;
554link-hygiene=
import./tests/link-hygiene.nix inherit pkgsFilc;
555fork-regressions=
556inherit
pkgsFilc
557suite=
"release"
559icu=
import./tests/icu.nix inherit pkgs pkgsFilc;
562boost-context=
import./tests/boost-context.nix inherit pkgsFilc;
563qnode=
import./tests/qnode.nix inherit pkgs pkgsFilc;
564protobuf=
import./tests/protobuf.nix inherit pkgs pkgsFilc;
565protobuf_33=
566inherit
pkgs pkgsFilc
567protobuf=
pkgsFilc.protobuf_33
569protobuf_21=
570inherit
pkgs pkgsFilc
571protobuf=
pkgsFilc.protobuf_21
573re2=
import./tests/re2.nix inherit pkgs pkgsFilc;
574emacs-treesit=
import./tests/emacs-treesit.nix inherit pkgs pkgsFilc;
577libsoup3-runtime=
import./tests/libsoup.nix inherit pkgs pkgsFilc;
580gi-link-environment=
import./tests/gi-link-environment.nix inherit pkgs pkgsFilc;
583generator-precedence=
import./tests/generator-precedence.nix inherit pkgs pkgsFilc;
586media-foundations=
import./tests/media-foundations.nix inherit pkgs pkgsFilc;
589graphite2-runtime=
import./tests/graphite2.nix inherit pkgs pkgsFilc;
592glib-atomic=
import./tests/glib-atomic.nix inherit pkgs pkgsFilc;
593glib-gtype=
import./tests/glib-gtype.nix inherit pkgs pkgsFilc;
594glib-enums=
import./tests/glib-enums.nix inherit pkgs pkgsFilc;
595dbus-glib=
import./tests/dbus-glib.nix inherit pkgs pkgsFilc;
596glibmm=
import./tests/glibmm.nix inherit pkgs pkgsFilc;.glibmm
597glibmm_2_68=
import./tests/glibmm.nix inherit pkgs pkgsFilc;.glibmm_2_68
599gtkmm3-runtime=
600inherit
pkgs pkgsFilc
601major=
3
603gtkmm4-runtime=
604inherit
pkgs pkgsFilc
605major=
4
607glib-networking=
import./tests/glib-networking.nix inherit pkgs pkgsFilc;
610pygobject=
import./tests/pygobject.nix inherit pkgs pkgsFilc;
613gtk4-runtime=
614inherit
pkgs pkgsFilc
615major=
4
619overlays.default=

A NixOS or finix system whose pkgs is the Fil-C package set; see lib/filc-system.nix and docs/nixos.md.

623nixosModules.default=
import./nixos filnix = self;
624finixModules.default=
import./finix filnix = self;

A Fil-C NixOS, with the NixOS modules of filnix's own Nixpkgs: the Fil-C ports (systemd's above all) are built and tested against those, not against another release's.

628lib.nixosSystem=
args: import"${nixpkgs}/nixos/lib/eval-config.nix" system = null; // args // modules = self.nixosModules.default filc.enable = nixlib.mkDefaulttrue; ++ args.modules or [ ];

The base machine of the images; see nixos/base.nix.

645nixosModules.base=
import./nixos/base.nix filnix = self;
646nixosConfigurations.base=
self.lib.nixosSystemmodules = self.nixosModules.base;

The same machine on EC2, for the public AMI; see nixos/amazon.nix.

650nixosConfigurations.amazon=
self.lib.nixosSystemmodules = import./nixos/amazon.nix filnix = self;;

https://filc.less.rest, on that AMI; see nixos/demo-wiki.nix.

654nixosConfigurations.demo-wiki=
self.lib.nixosSystemmodules = import./nixos/demo-wiki.nix filnix = self;;

The finix machine with a Fil-C userland; see finix/demo.nix.

659finixConfigurations.filc-demo=
importfinix.lib.finixSystem
661modules=
self.finixModules.default "${finix}/modules/virtualisation/qemu.nix" ./finix/demo.nix filc.system = system;

Export the full cross-compiled package sets

670legacyPackages.${system}=
671inherit
pkgsFilc pkgsFilcStaging pkgsFilcSystem

A package set, not a derivation; .#rubyWithGem.<gem> still works.

673inherit
rubyWithGem

NixOS VM tests of Fil-C systems; see tests/nixos/default.nix.

675nixosTests=
676inherit
pkgs pkgsFilc
677filcModule=
self.nixosModules.default
678filnix=
682packages.${system}=
nixlib.optionalAttrssystem ≡ "x86_64-linux"

The base Fil-C NixOS as a compressed qcow2, and a VM that boots it (nixos/image.nix).

686nixos-image=
687nixos-vm=

Its EC2 variant as a VHD, which .github/workflows/ami.yml imports.

689nixos-ami=
self.nixosConfigurations.amazon.config.system.build.ami
//
692default=
693baseline=
baseline.baseline

Fil-C, runtime and native ELF files in a closure (docs/nixos.md).

695filc-audit=
pkgs.writeShellApplication
696name=
"filc-audit"
697runtimeInputs=
pkgs.binutils-unwrapped pkgs.findutils
701text=
builtins.readFile./lib/filc-audit.sh
703baseline-shell=
baseline.shell
704inherit
filcc filcc-staging projeny sarcasm sarcasm-prolog zstd-sarcasm
712inherit sarcasm
minilute
713inherit pkgsFilc
openssl-sarcasm
714php-dist=
import./packages/php-dist inherit pkgs pkgsFilc;

Vulnerable PHP for reproductions, never the default or :latest.

716php84_25=
717php84_25-dist=
718inherit
pkgs
720base=
722php84_25-docker=
723inherit
pkgs
724dist=
self.packages.${system}.php84_25-dist

Experimental: opcache's JIT, compiled through C (docs/php.md).

727php-jit=
pkgsFilc.php84-jit

Native against Fil-C PHP 8.5 on real applications (bench/php).

729php-bench=
import./bench/php inherit pkgs pkgsFilc pkgsFilcStaging;

PHP 8.5 with the same JIT, on the staging toolchain.

731php85-jit=
pkgsFilcStaging.php85-jit
732php74-dist=
733inherit
pkgs pkgsFilc
734php=
pkgsFilc.php74.withExtensionsenabled, all: enabled ++ with all; bz2 shmop sysvmsg sysvshm
745inherit
optfil
746filroot=
import./packages/filroot inherit pkgs optfil;

The GitHub Pages site: pages/ and the rendered docs/.

748site=
749inherit
pkgs nixpkgs
751filnix=

The site's SWI-Prolog 10, which nixpkgs does not have; ship publishes it so the Pages build substitutes it.

755site-swipl=
import./nanofil/web/play/swipl.nix inherit pkgs;

The site's nanofil playground, built with the staging toolchain; ship publishes it so Pages does not rebuild staging clang.

758site-play=
self.packages.${system}.site.play
759php-docker=
760inherit
pkgs
761dist=
import./packages/php-dist inherit pkgs pkgsFilc;
763bind-dist=
import./packages/bind-dist inherit pkgs pkgsFilc;
764bind-docker=
765inherit
pkgs
766dist=
import./packages/bind-dist inherit pkgs pkgsFilc;

The PostgreSQL server with -fzmark-shared (docs/zmark-shared.md), staging only; the campaign builds it (scripts/ci-outputs.txt).

770postgresql-staging-zmark=
pkgsFilcStaging.postgresql_18

Release alternates on the staging toolchain: unreleased compiler and runtime changes, faster but less reviewed (docs/php.md).

773php85-staging-dist=
774inherit
pkgs
777suffix=
"-staging"
779php85-staging-docker=
780inherit
pkgs
781dist=
782inherit
pkgs
785suffix=
"-staging"
788bind-staging-dist=
789inherit
pkgs
791suffix=
"-staging"
793bind-staging-docker=
794inherit
pkgs
795dist=
796inherit
pkgs
798suffix=
"-staging"
801inherit
libei libei_27 libei_28
807inherit
filc-world-shell
808inherit virt
filc-nspawn filc-qemu filc-docker
809inherit demo
lighttpd-demo ttyd-emacs-demo lua-with-stuff python-with-stuff python-web-demo perl-demos perl-with-stuff libei-ping-demo sinatra-demo
821push-baseline=
pkgs.writeShellApplication
822name=
"filc-push-baseline"
823runtimeInputs=
pkgs.nix pkgs.cachix pkgs.coreutils pkgs.writeScriptBin"filc-verify-cache" "#!${pkgs.python3}/bin/python3\n" + builtins.readFile./scripts/verify-cache.py
832text=
837push-filcc=
pkgs.writeShellScriptBin"push-filcc"
${pkgs.cachix}/bin/cachix push filc ${filcc}
841push-pkg=
pkgs.writeShellScriptBin"push-pkg"
for pkg in "$@"; do
${pkgs.cachix}/bin/cachix push filc $(${pkgs.nix}/bin/nix build .#"$pkg" --print-out-paths --no-link)
done
847inherit
runfilc
filc-emacs
850emacs30=
pkgsFilc.emacs30
851emacs=
emacs-safe.filc-emacs
852emacs-unsafe=
emacs-unsafe.filc-emacs
855apps.${system}=
virt.apps
//
856zstd-sarcasm=
857type=
"app"
858program=
"${zstd-sarcasm.bin}/bin/zstd"
860baseline=
861type=
"app"
862program=
"${baseline.shell}/bin/filc-baseline-shell"
864openssl-sarcasm=
865type=
"app"
866program=
"${pkgsFilc.openssl-sarcasm.bin}/bin/openssl"
868filcc=
869type=
"app"
870program=
"${filcc}/bin/clang"
872filcc-staging=
873type=
"app"
874program=
"${filcc-staging}/bin/clang"
877"filc++"=
878type=
"app"
879program=
"${filcc}/bin/clang++"
881"filc++-staging"=
882type=
"app"
883program=
"${filcc-staging}/bin/clang++"
887formatter.${system}=
pkgs.nixfmt
889devShells.${system}=

Full Fil-C compilation environment (opt-in with 'nix develop .#world')

Incremental Fil-C LLVM hacking; see docs/llvm-dev.md

896filc-llvm=
import./shells/filc-llvm.nix inherit pkgs;
897filc-llvm-staging=

Fil-C is Linux-only, but Macs still run the git hooks and scripts/ship (which builds through a Linux builder or the publisher host), so they get the host tools those need and the default dev shell.

907hostTools=
λsystem
let
910pkgs=
importnixpkgs inherit system;
used by projeny
911projeny=
uses pkgs
in
914packages.${system}=
915inherit
projeny
918formatter.${system}=
pkgs.nixfmt
919devShells.${system}.default=

What scripts/git-hooks and scripts/ship run, so that they work without nix develop.

924devtoolsFor=
λpkgs
pkgs.buildEnv
927name=
"filnix-devtools"
928paths=
with pkgs; treefmt nixfmt actionlint shellcheck python3 git
938devShellFor=
λpkgs projeny
pkgs.mkShell
941name=
"filnix-dev"
942packages=
with pkgs

Nix development tools

nixfmt
treefmt
nixd
nil
python3

General development tools

git
direnv
nix-direnv
958shellHook=
git config core.hooksPath scripts/git-hooks
in
nixlib.foldl'nixlib.recursiveUpdate { } hostTools"aarch64-darwin" hostTools"x86_64-darwin" builtins.removeAttrsperSystem"aarch64-linux" "overlays" "nixosModules" "nixosConfigurations" "finixModules" "finixConfigurations" perSystem"x86_64-linux"