Skip to content

Commit

Permalink
feat: add cargoLlvmCov (#267)
Browse files Browse the repository at this point in the history
* feat: add cargoLlvmCov
* cargoHelperFunctionsHook: prefer `--release` over `--profile release`
Some tools (e.g. cargo-llvm-cov) don't understand `--profile release` as
an alias for `--release`, so `cargoWithProfile` should prefer passing
`--release` when `$CARGO_PROFILE` == "release"

---------

Co-authored-by: Ivan Petkov <[email protected]>
  • Loading branch information
figsoda and ipetkov authored Mar 19, 2023
1 parent 56b875b commit 475de74
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Add a stubbed binary target to each "dummy" crate generated to support
["artifact dependencies" nightly feature](https://doc.rust-lang.org/cargo/reference/unstable.html#artifact-dependencies)
in case a crate is used as `bin` artifact dependency.
* Add `cargoLlvmCov` to run `cargo llvm-cov`

## [0.11.3] - 2023-02-19

Expand All @@ -26,6 +27,9 @@ in case a crate is used as `bin` artifact dependency.
= "...";` explicitly on the derivation.
* A warning will now be emitted if `src` and `dummySrc` are passed to
`buildDepsOnly` as `dummySrc` will take priority
* cargo is now invoked with `--release` when `$CARGO_PROFILE == release` instead
of passing in `--profile release` to better support tools which do not
understand the latter

## [0.11.2] - 2023-02-11

Expand Down
19 changes: 19 additions & 0 deletions checks/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ in
onlyDrvs (lib.makeScope myLib.newScope (self:
let
callPackage = self.newScope { };
myLibLlvmTools = myLib.overrideToolchain (pkgs.rust-bin.stable.latest.minimal.override {
extensions = [ "llvm-tools" ];
});
x64Linux = pkgs.hostPlatform.system == "x86_64-linux";
in
{
Expand Down Expand Up @@ -35,6 +38,22 @@ in

cargoAuditTests = callPackage ./cargoAudit.nix { };

cargoLlvmCov = myLibLlvmTools.cargoLlvmCov {
src = ./simple;
cargoArtifacts = myLib.buildDepsOnly {
src = ./simple;
};
};

cargoLlvmCovNextest = myLibLlvmTools.cargoLlvmCov {
src = ./simple;
cargoLlvmCovCommand = "nextest";
cargoArtifacts = myLib.buildDepsOnly {
src = ./simple;
};
nativeBuildInputs = [ pkgs.cargo-nextest ];
};

# NB: explicitly using a github release (not crates.io release)
# which lacks a Cargo.lock file, so we can test adding our own
cargoLockOverride = myLib.buildPackage rec {
Expand Down
50 changes: 50 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,56 @@ environment variables during the build, you can bring them back via
* `cargoExtraArgs`
* `rustFmtExtraArgs`

### `lib.cargoLlvmCov`

`cargoLlvmCov :: set -> drv`

Create a derivation which will run a `cargo llvm-cov` invocation in a cargo
workspace.

Except where noted below, all derivation attributes are delegated to
`mkCargoDerivation`, and can be used to influence its behavior.
* `buildPhaseCargoCommand` will be set to run `cargo llvm-cov test --release` in
the workspace.
* `installPhaseCommand` will be set to `""`, as the default settings creates
a file instead of directory at `$out`.
* `doInstallCargoArtifacts` will be set to `false` for the same reason as
`installPhaseCommand`
* `pnameSuffix` will be set to `"-llvm-cov"`

#### Required attributes
* `cargoArtifacts`: A path (or derivation) which contains an existing cargo
`target` directory, which will be reused at the start of the derivation.
Useful for caching incremental cargo builds.
- This can be prepared via `buildDepsOnly`
- Alternatively, any cargo-based derivation which was built with
`doInstallCargoArtifacts = true` will work as well

#### Optional attributes
* `cargoExtraArgs`: additional flags to be passed in the cargo invocation
- Default value: `""`
* `cargoLlvmCovCommand`: cargo-llvm-cov command to run
- Default value: `"test"`
* `cargoLlvmCovExtraArgs`: additional flags to be passed in the cargo
llvm-cov invocation
- Default value: `"--lcov --output-path $out"`

#### Native build dependencies
The `cargo-llvm-cov` package is automatically appended as a native build input to any
other `nativeBuildInputs` specified by the caller.

Note that this would require the `llvm-tools-preview` component for the Rust toolchain,
which you would need to provide yourself using fenix or rust-overlay.

#### Remove attributes
The following attributes will be removed before being lowered to
`mkCargoDerivation`. If you absolutely need these attributes present as
environment variables during the build, you can bring them back via
`.overrideAttrs`.
* `cargoExtraArgs`
* `cargoLlvmCovCommand`
* `cargoLlvmCovExtraArgs`

### `lib.cargoNextest`

`cargoNextest :: set -> drv`
Expand Down
23 changes: 21 additions & 2 deletions examples/quick-start/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
crane = {
url = "github:ipetkov/crane";
inputs.nixpkgs.follows = "nixpkgs";
inputs.fenix.follows = "fenix";
};

fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.rust-analyzer-src.follows = "";
};

flake-utils.url = "github:numtide/flake-utils";
Expand All @@ -17,7 +24,7 @@
};
};

outputs = { self, nixpkgs, crane, flake-utils, advisory-db, ... }:
outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
Expand All @@ -44,6 +51,13 @@
# MY_CUSTOM_VAR = "some value";
};

craneLibLLvmTools = craneLib.overrideToolchain
(fenix.packages.${system}.complete.withComponents [
"cargo"
"llvm-tools"
"rustc"
]);

# 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;
Expand Down Expand Up @@ -100,7 +114,12 @@
});
};

packages.default = my-crate;
packages = {
default = my-crate;
my-crate-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // {
inherit cargoArtifacts;
});
};

apps.default = flake-utils.lib.mkApp {
drv = my-crate;
Expand Down
4 changes: 3 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@
let
pkgsChecks = import nixpkgs {
inherit system;
overlays = [ rust-overlay.overlays.default ];
overlays = [
rust-overlay.overlays.default
];
};
in
pkgsChecks.callPackages ./checks {
Expand Down
31 changes: 31 additions & 0 deletions lib/cargoLlvmCov.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{ mkCargoDerivation
, cargo-llvm-cov
}:

{ cargoExtraArgs ? ""
, cargoLlvmCovCommand ? "test"
, cargoLlvmCovExtraArgs ? "--lcov --output-path $out"
, ...
}@origArgs:

let
args = builtins.removeAttrs origArgs [
"cargoExtraArgs"
"cargoLlvmCovCommand"
"cargoLlvmCovExtraArgs"
];
in

mkCargoDerivation (args // {
pnameSuffix = "-llvm-cov";

nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ cargo-llvm-cov ];

doInstallCargoArtifacts = false;

buildPhaseCargoCommand = ''
cargoWithProfile llvm-cov "${cargoLlvmCovCommand}" ${cargoExtraArgs} ${cargoLlvmCovExtraArgs}
'';

installPhaseCommand = "";
})
1 change: 1 addition & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ in
cargoDoc = callPackage ./cargoDoc.nix { };
cargoFmt = callPackage ./cargoFmt.nix { };
cargoHelperFunctionsHook = callPackage ./setupHooks/cargoHelperFunctions.nix { };
cargoLlvmCov = callPackage ./cargoLlvmCov.nix { };
cargoNextest = callPackage ./cargoNextest.nix { };
cargoTarpaulin = callPackage ./cargoTarpaulin.nix { };
cargoTest = callPackage ./cargoTest.nix { };
Expand Down
8 changes: 7 additions & 1 deletion lib/setupHooks/cargoHelperFunctionsHook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ cargo() {
# Injects `--profile $CARGO_PROFILE` into a particular cargo invocation
# if the environment variable is set
cargoWithProfile() {
cargo "${@:1:1}" ${CARGO_PROFILE:+--profile ${CARGO_PROFILE}} "${@:2}"
local profileArgs
if [[ "${CARGO_PROFILE}" == "release" ]]; then
profileArgs="--release"
else
profileArgs="${CARGO_PROFILE:+--profile ${CARGO_PROFILE}}"
fi
cargo "${@:1:1}" ${profileArgs} "${@:2}"
}

0 comments on commit 475de74

Please sign in to comment.