buildRustCrate calls rustc directly, so there is no built-in equivalent
of `cargo clippy`. The capLints doc already hints at the existing
workaround — overriding the `rust` attribute with a wrapper script that
sniffs argv for build_script_build and routes everything else to
clippy-driver. That works because clippy-driver IS rustc internally
(rustc_driver plus lint passes) and produces compatible rlibs and
metadata, but the wrapper is fragile and every downstream reinvents it.
Add a `useClippy` boolean (default false) that swaps the lib/bin/test
compilation to clippy-driver while keeping plain rustc for build.rs —
the same lib-vs-build-script split as extraRustcOptsForBuildRs, since
build scripts are typically auto-generated and clippy noise there is
not actionable. The clippy-driver binary comes from a new `clippy`
parameter, auto-filled from pkgs.clippy by callPackage and overridable
alongside `rust` for toolchain bundles that ship their own.
Implemented by introducing a RUSTC_DRIVER shell variable in
build-crate.nix that lib.sh's build_lib/build_bin consume; the
build_script_build path in configure-crate.nix never sees it.
Note that the default `capLints = "allow"` cap suppresses clippy lints
along with everything else, so `useClippy` is usually paired with
`capLints = "warn"` and `-W clippy::*`/`-D warnings` flags via
extraRustcOpts. Documented in the manual.
Test fixtures cover the three load-bearing properties: a denied clippy
lint fails the build (proving clippy-driver ran), the default capLints
silences clippy lints just like rustc lints, and an rlib emitted by
clippy-driver is link-compatible with a plain-rustc dependent.
Collect binary targets into a bash associative array (name→path), then
generate a Makefile on the fly and pipe it to `make -j`. Make handles
parallel execution and the jobserver protocol natively, so rustc
invocations share the same token pool via MAKEFLAGS.
Also fix build_bin error propagation: add `|| return 1` to the rustc
invocation so failures are not silently swallowed when the crate name
has no hyphens and the mv rename is skipped.
Cargo sets `CARGO_BIN_EXE_<name>` when compiling integration tests so
they can locate the crate's own binaries via `env!()` and exec them
as subprocesses. buildRustCrate previously compiled bin targets as
test harnesses only (via `--test`) when buildTests=true, so the real
binary never existed and the env var was never set.
When buildTests is set, now first build the real (non-test) binaries
to `target/cargo-bin-exe/`, install them to `$out/bin/`, and expose
`CARGO_BIN_EXE_<name>` to subsequent rustc invocations via an `env`
prefix. Using `env` rather than bash `export` is necessary because
hyphenated binary names (`CARGO_BIN_EXE_my-crate`) produce env var
names that bash rejects as invalid identifiers; `env` sets them via
execve's envp array directly and has no such restriction.
The env array is populated by iterating `target/cargo-bin-exe/` at
build time, so it covers all binary-target shapes: explicit `crateBin`
entries, auto-detected `src/main.rs`, and auto-detected `src/bin/*.rs`.
`build_bin` in lib.sh gains an optional third argument for the output
directory so the real binary and the `--test` harness can coexist
without colliding in `target/bin/`. The lib-test build is reordered to
after the real-bin build so its compilation also sees the env vars.
build_bin_test_file derives the test binary name by replacing `/` with
`_`, stripping the `tests_` prefix and `.rs` suffix. For the
subdirectory integration-test layout `tests/<dir>/main.rs`, this
produces `<dir>_main`, but cargo names that binary `<dir>` per its
auto-discovery rules. Tools that expect the cargo convention
(cargo-nextest binaries-metadata, IDE test runners) cannot find the
binaries.
Strip the trailing `_main` when the source file is `*/main.rs`. The
guard is needed so a flat-style `tests/<name>_main.rs` keeps its
suffix.
Add `expectedTestBinaries` to the test harness so binary naming can be
asserted, and cover both the subdir case (suffix stripped) and the
flat case with a literal `_main` in the filename (suffix kept). Also
fix a typo in `removeAttrs` that leaked `expectedTestOutputs` into the
crate args.
lib.sh previously hardcoded `--cap-lints allow` in both build_lib and
build_bin. Since rustc only honours the first `--cap-lints` it sees,
appending a different level via `extraRustcOpts` had no effect, making
it impossible to run clippy (or any lint-based tooling) through
buildRustCrate without wrapper scripts that strip the argument.
This adds a `capLints` parameter (default `"allow"`, preserving current
behaviour) that can be set per-crate or via `.override`:
(myCrate { }).override { capLints = "warn"; }
These are currently broken because buildRustCrate will try to mv from
an underscored name to a hyphenated name, but will only try to move an
unsuffixed name; rustc generates wasm binaries with a .wasm suffix.
Fixes#204051. I have tried this on the reproducer stated in the ticket.
```
[nix-develop]$ $(nix-build -I nixpkgs=/home/shana/programming/nixpkgs --no-out-link)/tests/foo
running 1 test
test check_module_name ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
With Rust 1.61, it is necessary to link to external static/dynamic libaries
when building the rlib that uses them, rather than when linking the final
binary. In fact, it is no longer necessary to specify the libraries to link
when building the final binary, but the library search path flags must still
be included.
According to the Cargo documentation:
> The build script does not have access to the dependencies listed in
> the dependencies or dev-dependencies section (they’re not built
> yet!). Also, build dependencies are not available to the package
> itself unless also explicitly added in the [dependencies] table.
https://doc.rust-lang.org/cargo/reference/build-scripts.html
This change separates linkage of regular dependencies and build
dependencies.
* Make errors include the crate name and make them much more prominent.
* Move more code into lib.sh
* Already source generated logging code and lib.sh in configure
This helps us instruct rustc to build tests instead of binaries. The
actual build will then ONLY produce test executables. This is a first
step towards having rust crate tests within nixpkgs.
We default back to only a single output in test cases since that is the
only reasonable thing to do here.
Producing libraries or binaries in addition to tests would theoretically
be feasible but usually generates different dependency trees. It is very
common to have some libraries in `[dev-depdendencies]` within Cargo.toml
just for your tests. To not start mixing things up going with a
dedicated derivation for the test build sounds like the best choice for
now.
To use this you must provide a proper test dependency chain to
`buildRustCrate` (as you would usually do with your non-test inputs).
And then set the `buildTests` attribute to `true`. The derivation will
then contain all tests that were built in `$out/tests`. All common test
patterns and directories should be supported and tested by this change.
Below is an example how you would run a single test from the derivation.
This commit contains some more examples in the `buildRustCrateTests`
attribute set that might be helpful.
```
let
drv = buildRustCrate {
…
buildTests true;
};
in runCommand "test-my-crate" {} ''
touch $out
exec ${drv}/tests/my-test
''
```