Files
sausage/flake.nix
T

155 lines
6.7 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";
};
outputs = { nixpkgs, flake-utils, rust-overlay, crane, ... }:
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" ];
};
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";
};
wasiCc = pkgs.pkgsCross.wasi32.stdenv.cc;
wasiCcEnv = {
CC_wasm32_wasip2 = "${wasiCc}/bin/${wasiCc.targetPrefix}cc";
AR_wasm32_wasip2 = "${wasiCc}/bin/${wasiCc.targetPrefix}ar";
};
craneLib = (crane.mkLib pkgs).overrideToolchain rust;
# Preserve the embedded JavaScript and WIT alongside Cargo's sources.
hostSrc = pkgs.lib.cleanSourceWith {
src = ./.;
filter = path: type:
let relative = pkgs.lib.removePrefix (toString ./. + "/") path;
in !(pkgs.lib.hasPrefix "userland/" relative || pkgs.lib.hasPrefix "spikes/" relative)
&& (craneLib.filterCargoSources path type
|| pkgs.lib.hasSuffix ".wit" path || pkgs.lib.hasSuffix ".js" path);
};
v8Archive = pkgs.fetchurl {
url = "https://github.com/denoland/rusty_v8/releases/download/v150.4.0/librusty_v8_release_${pkgs.stdenv.hostPlatform.rust.rustcTarget}.a.gz";
hash = {
x86_64-linux = "sha256-WGn9twcbHyHyAKl86X0gElh34PMc2ALtmd4sU/SIsGw=";
aarch64-linux = "sha256-txd9Uq0zNycv4NO453gjnIIalcJdWVnexiue/WVPfdM=";
x86_64-darwin = "sha256-5ex9E/kUgT6/IB1Ee/j9J2h7exkuFsR/KCb+VBUXHyk=";
aarch64-darwin = "sha256-zNj4FIW4IsWxiuun+d65KaM4LYasZzu/DzZvBod+axA=";
}.${system};
};
common = {
pname = "sausage";
version = "0.3.0";
src = hostSrc;
strictDeps = true;
RUSTY_V8_ARCHIVE = v8Archive;
buildInputs = [ pkgs.openssl ];
nativeBuildInputs = [ pkgs.pkg-config pkgs.cmake pkgs.python3 pkgs.perl ] ++ mold;
} // moldEnv;
cargoArtifacts = craneLib.buildDepsOnly (common // {
doCheck = false;
});
brushSource = pkgs.fetchFromGitHub {
owner = "reubeno";
repo = "brush";
rev = "943553433ae04f5b3bd55d2cf207e39eb9ef2af7";
hash = "sha256-a1eMkqx4nBqJ8R+h+rxtU35pAungcEnXoxwZnb1poH8=";
};
userlandSrc = pkgs.lib.cleanSourceWith {
src = ./.;
filter = path: type:
let relative = pkgs.lib.removePrefix (toString ./. + "/") path;
in type == "directory" || pkgs.lib.hasPrefix "userland/" relative
|| pkgs.lib.hasPrefix "host/wit/" relative;
};
userlandCommon = {
pname = "sausage-userland";
version = "0.3.0";
src = userlandSrc;
strictDeps = true;
cargoVendorDir = craneLib.vendorMultipleCargoDeps {
cargoLockList = [ ./userland/Cargo.lock ./userland/brush/Cargo.lock ];
};
nativeBuildInputs = [ pkgs.nushell pkgs.wasm-tools pkgs.git pkgs.pkg-config ] ++ mold;
postPatch = ''
cp -r ${brushSource} userland/brush/source
chmod -R u+w userland/brush/source
# The fixed-output source fetch replaces the development checkout's Git check.
substituteInPlace userland/brush/build.nu --replace-fail \
${pkgs.lib.escapeShellArg "if (^git -C $source rev-parse HEAD | str trim) != $revision { error make {msg: 'unexpected brush revision'} }"} \
'# Revision verified by the fixed-output Nix fetch.'
patchShebangs userland/cwd-init/link.nu
'';
preBuild = ''
export CARGO_TARGET_DIR="$PWD/target"
'';
buildPhaseCargoCommand = "nu userland/bundle.nu";
doCheck = false;
} // wasiCcEnv // moldEnv;
# Keep the real local patch crates: registry dependencies use their full APIs.
userlandArtifacts = craneLib.buildDepsOnly (userlandCommon // {
dummySrc = userlandSrc;
});
userland = craneLib.mkCargoDerivation (userlandCommon // {
cargoArtifacts = userlandArtifacts;
installPhaseCommand = ''
mkdir -p $out
cp -a target/userland/bin $out/bin
'';
doInstallCargoArtifacts = false;
});
sausage = craneLib.buildPackage (common // {
inherit cargoArtifacts;
cargoExtraArgs = "--locked -p sausage";
doCheck = false;
nativeBuildInputs = common.nativeBuildInputs ++ [ pkgs.makeWrapper ];
postInstall = ''
wrapProgram $out/bin/sausage --set-default SAUSAGE_USERLAND ${userland}/bin
'';
meta.mainProgram = "sausage";
});
in {
packages.default = sausage;
checks.package = sausage;
checks.tests = craneLib.cargoTest (common // wasiCcEnv // {
inherit cargoArtifacts;
cargoExtraArgs = "--workspace --lib --test harness --test p1 --test layers --test regressions --test streams --test wasi";
preCheck = ''
mkdir -p target/userland
ln -s ${userland}/bin target/userland/bin
'';
doInstallCargoArtifacts = false;
});
checks.shell = pkgs.runCommand "sausage-shell" { } ''
${sausage}/bin/sausage sh "$TMPDIR/world" -c \
'ls /bin | wc -l; echo hi | tr a-z A-Z; git --version; rg --version' > output
cat output
grep -qx HI output
grep -q 'git version' output
grep -q ripgrep output
touch $out
'';
apps.default = { type = "app"; program = "${sausage}/bin/sausage"; };
devShells.default = pkgs.mkShell (wasiCcEnv // moldEnv // {
packages = [ rust pkgs.wasmtime pkgs.wasm-tools pkgs.openssl pkgs.pkg-config ] ++ mold;
shellHook = ''
export CARGO_HOME="$PWD/.cargo-home"
'';
});
});
}