feat(nix): enable cross compilation

Adds packages for every member of systems from any of the systems. Since
rust-overlay is more or less basically like rustup, we get to just have
all of those targets without having to build quite as much of the
toolchain.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Thomas Mühlbacher 2025-03-21 16:34:01 +00:00 committed by Kent Overstreet
parent 1a8e684ae0
commit 00dd889d33

236
flake.nix
View File

@ -63,104 +63,183 @@
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
rustfmtToml = builtins.fromTOML (builtins.readFile ./rustfmt.toml);
craneLib = crane.mkLib pkgs;
rev = self.shortRev or self.dirtyShortRev or (substring 0 8 self.lastModifiedDate);
makefileVersion = removePrefix "VERSION=" (
findFirst (line: hasPrefix "VERSION=" line) "VERSION=0.0.0" (split "\n" (readFile ./Makefile))
);
version = "${makefileVersion}+${rev}";
commonArgs = {
inherit version;
src = self;
mkCommon =
{
crane,
pkgs,
rustVersion ? "latest",
env = {
PKG_CONFIG_SYSTEMD_SYSTEMDSYSTEMUNITDIR = "${placeholder "out"}/lib/systemd/system";
PKG_CONFIG_UDEV_UDEVDIR = "${placeholder "out"}/lib/udev";
# build time
buildPackages,
pkg-config,
rustPlatform,
stdenv,
# run time
attr,
keyutils,
libaio,
libsodium,
liburcu,
libuuid,
lz4,
udev,
zlib,
zstd,
}:
let
inherit (stdenv) cc hostPlatform;
craneLib = (crane.mkLib pkgs).overrideToolchain (
p: p.rust-bin.stable."${rustVersion}".minimal.override { extensions = [ "clippy" ]; }
);
args = {
inherit version;
src = self;
strictDeps = true;
env = {
PKG_CONFIG_SYSTEMD_SYSTEMDSYSTEMUNITDIR = "${placeholder "out"}/lib/systemd/system";
PKG_CONFIG_UDEV_UDEVDIR = "${placeholder "out"}/lib/udev";
CARGO_BUILD_TARGET = hostPlatform.rust.rustcTargetSpec;
"CARGO_TARGET_${hostPlatform.rust.cargoEnvVarTarget}_LINKER" = "${cc.targetPrefix}cc";
HOST_CC = "${cc.nativePrefix}cc";
TARGET_CC = "${cc.targetPrefix}cc";
};
makeFlags = [
"INITRAMFS_DIR=${placeholder "out"}/etc/initramfs-tools"
"PREFIX=${placeholder "out"}"
"VERSION=${version}"
];
dontStrip = true;
depsBuildBuild = [
buildPackages.stdenv.cc
];
nativeBuildInputs = [
pkg-config
rustPlatform.bindgenHook
];
buildInputs = [
attr
keyutils
libaio
libsodium
liburcu
libuuid
lz4
udev
zlib
zstd
];
meta = {
description = "Userspace tools for bcachefs";
license = lib.licenses.gpl2Only;
mainProgram = "bcachefs";
};
};
cargoArtifacts = craneLib.buildDepsOnly args;
in
{
inherit args cargoArtifacts craneLib;
};
common = pkgs.callPackage mkCommon { inherit crane; };
makeFlags = [
"INITRAMFS_DIR=${placeholder "out"}/etc/initramfs-tools"
"PREFIX=${placeholder "out"}"
"VERSION=${version}"
];
mkPackage =
{ common, name }:
common.craneLib.buildPackage (
common.args
// {
inherit (common) cargoArtifacts;
pname = name;
dontStrip = true;
enableParallelBuilding = true;
buildPhaseCargoCommand = ''
make ''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}} $makeFlags
'';
doNotPostBuildInstallCargoBinaries = true;
installPhaseCommand = ''
make ''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}} $makeFlags install
'';
nativeBuildInputs = with pkgs; [
pkg-config
rustPlatform.bindgenHook
];
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
buildInputs = with pkgs; [
attr
keyutils
libaio
libsodium
liburcu
libuuid
lz4
udev
zlib
zstd
];
test "$($out/bin/bcachefs version)" = "${version}"
meta = {
description = "Userspace tools for bcachefs";
license = lib.licenses.gpl2Only;
mainProgram = "bcachefs";
};
};
runHook postInstallCheck
'';
}
);
cargoArtifacts = craneLib.buildDepsOnly (commonArgs // { pname = cargoToml.package.name; });
mkPackages =
name: systems:
let
packagesForSystem =
crossSystem:
let
localSystem = system;
pkgs' = import nixpkgs {
inherit crossSystem localSystem;
overlays = [ (import rust-overlay) ];
};
common = pkgs'.callPackage mkCommon { inherit crane; };
package = pkgs'.callPackage mkPackage { inherit common name; };
packageFuse = package.overrideAttrs (
final: prev: {
makeFlags = prev.makeFlags ++ [ "BCACHEFS_FUSE=1" ];
buildInputs = prev.buildInputs ++ [ pkgs'.fuse3 ];
}
);
in
[
(lib.nameValuePair "${name}-${crossSystem}" package)
(lib.nameValuePair "${name}-fuse-${crossSystem}" packageFuse)
];
in
lib.listToAttrs (lib.flatten (map packagesForSystem systems));
in
{
packages.default = config.packages.bcachefs-tools;
packages.bcachefs-tools = craneLib.buildPackage (
commonArgs
packages =
let
inherit (cargoToml.package) name;
in
(mkPackages name systems)
// {
inherit cargoArtifacts;
${name} = config.packages."${name}-${system}";
"${name}-fuse" = config.packages."${name}-fuse-${system}";
default = config.packages.${name};
};
enableParallelBuilding = true;
buildPhaseCargoCommand = ''
make ''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}} $makeFlags
'';
installPhaseCommand = ''
make ''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}} $makeFlags install
'';
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
test "$($out/bin/bcachefs version)" = "${version}"
runHook postInstallCheck
'';
}
);
packages.bcachefs-tools-fuse = config.packages.bcachefs-tools.overrideAttrs (
final: prev: {
makeFlags = prev.makeFlags ++ [ "BCACHEFS_FUSE=1" ];
buildInputs = prev.buildInputs ++ [ pkgs.fuse3 ];
}
);
checks.cargo-clippy = craneLib.cargoClippy (
commonArgs
checks.cargo-clippy = common.craneLib.cargoClippy (
common.args
// {
inherit cargoArtifacts;
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
inherit (common) cargoArtifacts;
cargoClippyExtraArgs = "--all-targets --all-features -- --deny warnings";
}
);
# we have to build our own `craneLib.cargoTest`
checks.cargo-test = craneLib.mkCargoDerivation (
commonArgs
checks.cargo-test = common.craneLib.mkCargoDerivation (
common.args
// {
inherit cargoArtifacts;
inherit (common) cargoArtifacts;
doCheck = true;
enableParallelChecking = true;
@ -188,9 +267,12 @@
cargo-audit
cargo-outdated
clang-tools
clippy
rust-analyzer
rustc
(rust-bin.stable.latest.minimal.override {
extensions = [
"rust-analyzer"
"rust-src"
];
})
];
};