-
Notifications
You must be signed in to change notification settings - Fork 118
Description
Describe the bug
Ok, this is a weird one and took me quite a few hours to sus out. The problem is that if you do not include cargoArtifacts as part of a buildPackage, it gives you only a warning that it will not reuse artifacts. "Cool, whatever right, just build the thing", is what I thought, but then I got sent down a rabbit hole as to why my lib.fileset.toSource was somehow not what I had specified. I added a ton of traces to see all the way through my logic, and found no errors. Every step along the way the file I needed in my sources was found, but then why during the build was it not found? I thought, "ok what exactly did I do differently here that I never did anywhere else" and so I tried adding back in the cargoArtifacts and bam, it worked again. Somewhere during the unpackPhase, my guess is that because cargoArtifacts isn't present it just decides that the src it was given should be disregarded.
Reproduction
Here is my situation:
I wrote a cargo plugin which uses a config file called reaper.toml or .reaper.toml. I'm writing some checks using some test data (just some cargo projects that use the cargo plugin I wrote and have a reaper.toml in their directory) that I'm re-using the craneLib from my flake that I use to build the cargo plugin. So the whole project sort of looks like this:
Cargo.toml Cargo.lock src flake.nix flake.lock test_data
And in test data there are multiple cargo projects for testing which are not part of the workspace.
Here is the code I wrote that produced the error:
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
crane.url = "github:ipetkov/crane";
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.rust-analyzer-src.follows = "";
};
nix-core = {
url = "github:Cloud-Scythe-Labs/nix-core";
inputs.nixpkgs.follows = "nixpkgs";
inputs.fenix.follows = "fenix";
};
flake-utils.url = "github:numtide/flake-utils";
advisory-db = {
url = "github:rustsec/advisory-db";
flake = false;
};
};
outputs =
{ self
, nixpkgs
, crane
, fenix
, nix-core
, flake-utils
, advisory-db
, ...
}:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
};
inherit (pkgs) lib;
rustToolchain = nix-core.toolchains.${system}.mkRustToolchainFromTOML
./.rust-toolchain.toml
"sha256-KUm16pHj+cRedf8vxs/Hd2YWxpOrWZ7UOrwhILdSJBU=";
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain.fenix-pkgs;
src = craneLib.cleanCargoSource ./.;
# Common arguments can be set here to avoid repeating them later
commonArgs = {
inherit src;
strictDeps = true;
buildInputs = [
rustToolchain.darwin-pkgs
];
};
# Build *just* the cargo dependencies, so we can reuse
# all of that work (e.g. via cachix) when running in CI
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
# Build the actual crate itself, reusing the dependency
# artifacts from above.
cargo-reaper-drv = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
doCheck = false;
});
in
{
checks =
let
buildReaperExtension = { package, plugin ? package, ... }@crateArgs:
craneLib.buildPackage (crateArgs // {
pname = package;
src = (builtins.trace "found cargo-reaper config in fileset ${crateArgs.src} with file type '${(builtins.readDir crateArgs.src).${"reaper.toml"}}'" crateArgs.src);
nativeBuildInputs = (crateArgs.nativeBuildInputs or []) ++ [
# Add `cargo-reaper` as a build time dependency of this derivation.
self.packages.${system}.default
];
# Run `cargo-reaper`, passing trailing args to the cargo invocation.
# We do not symlink the plugin since the `UserPlugins` directory is in
# the `$HOME` directory which is inaccessible to the sandbox.
buildPhaseCargoCommand = ''
ls . # somehow the source here is wrong even though up to this point everything is fine?
cargo reaper build --no-symlink \
-p ${package} --lib \
--release
'';
# Include extension plugin in the build result.
installPhaseCommand = ''
mkdir -p $out/lib
mv target/release/${plugin}.* $out/lib
'';
# Bypass crane checks for target install paths.
doNotPostBuildInstallCargoBinaries = true;
});
cargoReaperConfigFilter = from:
lib.fileset.fileFilter (file:
let
found = (lib.match "\.?reaper\.toml" file.name) != null;
in
builtins.trace (if found then "cargo-reaper config successfully located: ${from}" else "unable to locate cargo-reaper config file") found)
from;
testArgs = src: {
inherit src;
version = "0.1.0";
strictDeps = true;
};
in
{
# Build the crate as part of `nix flake check` for convenience
inherit cargo-reaper-drv;
test-cargo-reaper-build =
let
root = ./tests/test_data/package_manifest;
src = lib.fileset.toSource {
inherit root;
fileset = lib.fileset.unions [
(root + "/Cargo.toml")
(root + "/Cargo.lock")
(root + "/src")
(cargoReaperConfigFilter (root + "/reaper.toml"))
];
};
cargoReaperBuildArgs = testArgs (builtins.trace "found cargo-reaper config in fileset ${src} with file type '${(builtins.readDir src).${"reaper.toml"}}'" src);
in
buildReaperExtension (cargoReaperBuildArgs // {
package = "package_extension";
plugin = "reaper_package_ext";
});
};
packages = rec {
cargo-reaper = cargo-reaper-drv;
default = cargo-reaper;
};
});
}And adding this fixes it:
test-cargo-reaper-build =
let
root = ./tests/test_data/package_manifest;
src = lib.fileset.toSource {
inherit root;
fileset = lib.fileset.unions [
(root + "/Cargo.toml")
(root + "/Cargo.lock")
(root + "/src")
(cargoReaperConfigFilter (root + "/reaper.toml"))
];
};
cargoReaperBuildArgs = testArgs (builtins.trace "found cargo-reaper config in fileset ${src} with file type '${(builtins.readDir src).${"reaper.toml"}}'" src);
+ cargoReaperCargoArtifacts = craneLib.buildDepsOnly cargoReaperBuildArgs;
in
buildReaperExtension (cargoReaperBuildArgs // {
+ cargoArtifacts = cargoReaperCargoArtifacts;
package = "package_extension";
plugin = "reaper_package_ext";
});