Files
sausage/flake.nix
T

166 lines
8.3 KiB
Nix

{
description = "Sausage: a world of WASI programs and durable agents";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay.url = "github:oxalica/rust-overlay";
rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
crane.url = "github:ipetkov/crane";
kache = {
url = "github:kunobi-ninja/kache/stable";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, flake-utils, rust-overlay, crane, kache, ... }:
flake-utils.lib.eachSystem flake-utils.lib.allSystems (system:
let
pkgs = import nixpkgs { inherit system; overlays = [ rust-overlay.overlays.default ]; };
rust = pkgs.rust-bin.stable.latest.default.override {
targets = [ "wasm32-wasip2" ];
extensions = [ "rust-src" ];
};
craneLib = (crane.mkLib pkgs).overrideToolchain rust;
src = pkgs.nix-gitignore.gitignoreSource [] ./.;
mold = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.mold ];
hostTarget = pkgs.lib.toUpper (builtins.replaceStrings [ "-" ] [ "_" ] pkgs.stdenv.hostPlatform.rust.rustcTarget);
moldVar = "CARGO_TARGET_${hostTarget}_RUSTFLAGS";
moldEnv = pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { ${moldVar} = "-C link-arg=-fuse-ld=mold"; };
builderTools = [ kache.packages.${system}.default pkgs.bubblewrap pkgs.nushell pkgs.wasm-tools pkgs.bash pkgs.coreutils ];
runtimePath = pkgs.lib.makeBinPath ([ rust pkgs.stdenv.cc ] ++ builderTools ++ mold);
wasiCc = pkgs.pkgsCross.wasi32.stdenv.cc;
wasiCcEnv = {
CC_wasm32_wasip2 = "${wasiCc}/bin/${wasiCc.targetPrefix}cc";
AR_wasm32_wasip2 = "${wasiCc}/bin/${wasiCc.targetPrefix}ar";
};
v8Archive = pkgs.fetchurl {
url = "https://github.com/denoland/rusty_v8/releases/download/v150.4.0/librusty_v8_simdutf_release_${pkgs.stdenv.hostPlatform.rust.rustcTarget}.a.gz";
hash = {
x86_64-linux = "sha256-9IdiyhDR8fxgWkQcWuQw7Izh6egPFNePvELLh4wwtHY=";
aarch64-linux = "sha256-U54oOBWjlqV5bzKFi0LlF7hY66rqqtBdAykO6MhkpSc=";
x86_64-darwin = "sha256-p1AnH+xrIRRX7Qpc99LqsZJLJlYhqC2oarlZ1v8II+Q=";
aarch64-darwin = "sha256-Wu/9jVoMG3msHXCvg9WxkJllX9nGRaeU3EPxAfd5g4w=";
}.${system};
};
# rusty_v8's documented archive hook prevents downloads inside the Nix sandbox.
v8Env = { RUSTY_V8_ARCHIVE = v8Archive; };
cwdInit = pkgs.runCommand "sausage-cwd-init" { nativeBuildInputs = [ rust pkgs.nushell pkgs.wasm-tools ]; } ''
cp -r ${./userland/cwd-init} cwd-init
chmod -R u+w cwd-init
nu cwd-init/build.nu
mkdir $out
cp cwd-init/init.o $out/
'';
linker = pkgs.writeScript "sausage-wasi-link.nu" ("#!${pkgs.nushell}/bin/nu\n" + builtins.readFile ./userland/cwd-init/link.nu);
members = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.members;
commands = builtins.filter (p: pkgs.lib.hasPrefix "userland/" p && !(pkgs.lib.hasPrefix "userland/brush/" p)) members;
commandArgs = pkgs.lib.concatMapStringsSep " " (p: "-p " + (builtins.fromTOML (builtins.readFile (./. + "/${p}/Cargo.toml"))).package.name) commands;
common = {
pname = "sausage";
version = "0.3.0";
inherit src;
strictDeps = true;
buildInputs = [ pkgs.openssl ];
nativeBuildInputs = [ pkgs.pkg-config pkgs.cmake pkgs.python3 pkgs.perl pkgs.nushell pkgs.wasm-tools pkgs.go ] ++ mold;
SAUSAGE_CWD_INIT = "${cwdInit}/init.o";
CARGO_TARGET_WASM32_WASIP2_LINKER = linker;
CARGO_TARGET_WASM32_WASIP2_RUSTFLAGS = "-C link-arg=sausage-cwd-init";
GOTOOLCHAIN = "local";
} // v8Env // wasiCcEnv // moldEnv;
cargoArtifacts = craneLib.buildDepsOnly (common // {
# Registry gix crates need the real APIs of the local WASI patches.
extraDummyScript = ''
chmod -R u+w $out/userland/git/vendor
cp -r ${./userland/git/vendor}/. $out/userland/git/vendor/
'';
buildPhaseCargoCommand = ''
cargoWithProfile build --locked -p sausage -p sausage-vfs
cargoWithProfile build --locked --target wasm32-wasip2 ${commandArgs}
cargoWithProfile build --locked --target wasm32-wasip2 -p brush-shell --no-default-features --features minimal,tokio/time
'';
doCheck = false;
});
userland = craneLib.mkCargoDerivation (common // {
inherit cargoArtifacts;
pname = "sausage-userland";
preBuild = ''
export CARGO_TARGET_DIR="$PWD/target"
export GOCACHE="$TMPDIR/go-cache"
'';
buildPhaseCargoCommand = "nu userland/bundle.nu";
doCheck = false;
installPhaseCommand = ''
mkdir -p $out
cp -a target/userland/bundle/. $out/
test -f $out/bin/web.wasm
test -f $out/srv/www/index.html
test -f $out/etc/systemd/system/web.service
test -f $out/etc/systemd/system/multi-user.target.wants/web.service
'';
doInstallCargoArtifacts = false;
dontCheckForBrokenSymlinks = true;
});
sausageUnwrapped = craneLib.buildPackage (common // {
inherit cargoArtifacts;
doNotRemoveReferencesToVendorDir = true;
cargoExtraArgs = "--locked -p sausage";
doCheck = false;
});
# Keep the wrapper separate from crane's removal of toolchain references.
sausage = pkgs.symlinkJoin {
name = "sausage-${sausageUnwrapped.version}";
paths = [ sausageUnwrapped ];
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/sausage --set-default SAUSAGE_USERLAND ${userland} \
--prefix PATH : ${runtimePath} \
--set-default CC_wasm32_wasip2 ${wasiCcEnv.CC_wasm32_wasip2} \
--set-default AR_wasm32_wasip2 ${wasiCcEnv.AR_wasm32_wasip2} \
${pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isLinux "--set-default ${moldVar} '-C link-arg=-fuse-ld=mold'"}
'';
meta.mainProgram = "sausage";
};
in {
packages.default = sausage;
checks.package = sausage;
checks.tests = craneLib.mkCargoDerivation (common // {
inherit cargoArtifacts;
pnameSuffix = "-test";
nativeBuildInputs = common.nativeBuildInputs ++ [ pkgs.git ];
doCheck = true;
buildPhaseCargoCommand = "";
checkPhaseCargoCommand = ''
cargoWithProfile test --locked -p sausage -p sausage-vfs --lib
cargoWithProfile test --locked -p sausage --test it -- harness:: p1:: durable:: cred:: cred_ --skip undo_harness::
cargoWithProfile test --locked -p sausage-vfs --test layers --test regressions --test streams --test wasi
'';
preCheck = ''
export SAUSAGE_USERLAND="${userland}"
export SAUSAGE_CACHE="$TMPDIR/sausage-cache"
export CARGO_TARGET_DIR="$PWD/target"
export RUST_BACKTRACE=1
mkdir -p target/userland
ln -s ${userland} target/bundle
ln -s ${userland} target/userland/bundle
'';
doInstallCargoArtifacts = false;
});
checks.shell = pkgs.runCommand "sausage-shell" { } ''
export SAUSAGE_CACHE="$TMPDIR/sausage-cache"
${sausage}/bin/sausage sh "$TMPDIR/world" -c \
'set -e; echo hi | tr a-z A-Z; git --version; rg --version; awk "BEGIN {print 42}"; echo payload > /payload; tar -cf /test.tar /payload; tar -tf /test.tar; qjs -e "console.log(42)"; box --help; cargo --help; undo list' > output
cat output
grep -qx HI output
grep -q 'git version' output
grep -q ripgrep output
grep -qx 42 output
grep -q payload output
test -d "$TMPDIR/world/world/src/sausage/extensions"
touch $out
'';
apps.default = { type = "app"; program = "${sausage}/bin/sausage"; };
devShells.default = pkgs.mkShell (v8Env // wasiCcEnv // moldEnv // {
packages = [ rust pkgs.wasmtime pkgs.openssl pkgs.pkg-config ] ++ builderTools ++ mold;
});
});
}