Project:Rust/rust-dev

From Gentoo Wiki
Jump to: navigation, search

About

The rust-dev overlay is a prototype experiment for building crates as individual crate units.

This overlay handles each crate similarly to how non-binary programming languages like Perl, Python and Ruby work, by installing (possibly augmented) copies of the extracted crate archives, constructing a local directory registry source as described in source replacement in the cargo book, while deferring actual binary compilation to the relevant target leaves, leveraging slot-operator deps for automatic rebuilds.

But its currently a very complicated mountain of work and not quite ready for prime-time.

Repositories

Common Pitfalls

denied warnings

Many crates employ a rust attribute macro of some variation of:

   #[deny(warnings)]

This makes all warnings fatal, but this is only typically visible when directly compiling or testing a crate, as cargo automatically passes --cap-lints warn when building dependencies.

Typically, you can circumvent this issue with something like

   src_test() {
       RUSTFLAGS="${RUSTFLAGS} --cap-lints warn" rust-crate_src_test
   }

Which will usually turn them back into just loud warnings.

further caveats

However, due to a few rust bugs, this approach does not work. More over, some of these warnings may eventually become fatal in future rusts, so its pertinent to see them and possibly get them fixed upstream. This means in some cases one has to patch out the relevant #[deny( .. )] lines to allow tests to pass / binaries to compile. But in some cases, one may instead wish to patch out the reasons for the warnings and get it fixed upstream.

Relevant bugs:

apparently required non-target dependencies

Standard crates have several kinds of dependency grades:

  • [dependencies]
  • [dependencies] with optional = true
  • [dev-dependencies]
  • [build-dependencies]
  • [target.*] specific verisions of the above

But unfortunately, depending on aspects of the crate, all of these can be required to satisfy the src_compile section of the crate, which invokes :

   ecargo package --allow-dirty --no-metadata --no-verify

( to re-roll the patched sources back into a cargo-repository compatible format )

Solutions

Removing non-essential binaries

One of the thing that causes spurious dependencies to be deemed "mandatory" are binary asepcts, namely:

  • installable executables
  • examples
  • tests ( which are compiled executables )

These can take a variety of forms:

  • [[bin]] sections in Cargo.toml
  • [[example]] sections in Cargo.toml
  • Any file called src/main.rs, src/bin/*.rs, or src/*/main.rs
  • Any file called *.rs under examples/

For the most part, I've just opted to remove these binary aspects entirely, as its usually examples which trigger this, and also patch out any relevant lines in Cargo.toml, including pruning any [dev-dependencies] that are proven to only be needed for examples.

Very few crates have actual binaries that need to be installed, and doing that while keeping dependencies slim is a bit of a mess right now, so look at this example case for now

Removing non-target platform dependencies

Many crates have target-specific dependencies using prefixes like:

   [target."cfg(target_os = \"fuchsia\")".dependencies.fuchsia-zircon]
   version = "0.3.2"
   
   [target."cfg(target_os = \"fuchsia\")".dependencies.fuchsia-zircon-sys]
   version = "0.3.2"
   
   [target."cfg(unix)".dependencies.libc]
   version = "0.2.42"
   
   [target."cfg(windows)".dependencies.kernel32-sys]
   version = "0.2"
   
   [target."cfg(windows)".dependencies.miow]
   version = "0.2.1"
   
   [target."cfg(windows)".dependencies.winapi]
   version = "0.2.6"

Unfortunately, the way cargo works is it can require these crates to be present in the registry in order to build Cargo.lock, which is presently rediculous as our dominant audience is served by cfg(unix), and if these dependencies are shipped, it lends to massive dependency graphs.

Its simpler to simply cull those sections with a patch, so only dependencies which would be used on unix are included (eg: leaving cfg(unix) intact).

Conventions

Version Mapping

I've been using an approach that closely maps upstream version declarations in Cargo.toml to Gentoo compatible dependency syntax, as this allows at least some level of "version changes == slot changes == dependents rebuild automatically".


Caret (^) versions

Cargo Specification

"Caret" versions are defined as either:

  • 1.0.0 ( "Bare" representation )
  • ^1.0.0

Major 1 or greater

When major is 1 or greater, ( that is, x.y.z where x ≥1 ), x.y.z implies a supported range < (x+1).0.0 and ≥ x.y.z

In ebuilds, I translate this as:

   ( =dev-rust/cratename-x*:= >=dev-rust/cratename-x.y.z )

As x*:= supports the range from x.0.0 ... <(x+1).0.0 , and the second part limits the minimum version.

When upstream declares it as the simpler form:

  • ^1

Then it can be translated adequately with simply

   =dev-rust/cratename-x*:=

Where the := binds the slot ( which for all packages using rust-crate.eclass, defaults to "${PV}/${PR}" ) such that when any crate with a version already in that range, gets upgraded to another version in that range, will trigger a rebuild ( but only at depth 1, because there's currently no mechanism in portage for transitive propagation of slot-op changes )

Major 0 Minor 1 or greater

When upstream indicates a dependency version in the form:

  • 0.1.0
  • ^0.1.0

( that is, 0.x.y where x ≥1 )

This implies a supported range from 0.x.y to <0.(x+1).0

This can be thought of similar to the major form, but shifted one place to the right.

So that, 0.x.y translates as:

   ( =dev-rust/cratename-0.x*:= >=dev-rust/cratename-0.x.y )

And as with the major form, when y is 0, it can be written as simply:

    =dev-rust/cratename-0.x*:=

And the implicit slot binding magic again works within the same ranges.

Major 0 Minor 0

Rust's implementation of semver in regards to caret versions is that versions in the form 0.0.x are not API-compatible with any other value of X.

This in effect is basically the same as 0.x.0, but shifted right once yet again.

Presently I don't know what happens if somebody ships something like 0.0.1.4, because I've never seen rust versions with 4 parts, but I suspect all versions of 0.0.1.x are inter-compatible.

So I tend to write these as:

   =dev-rust/cratename-0.0.x*:=

just in case there's some mechanism to ship sub-versions, ( even if they may only be gentoo-side subversions )

Bare (unprefixed) versions

Versions with no special prefixes or modifiers are just caret versions, treat them the same

Cargo Specification

Tilde (~) versions

Cargo Specification

Tilde versions are mostly equivalent to the same dependency spec in portage, suffixed by "*".

That is, the number of specified components is the significant part, and the missing components are effectively wildcarded.

Though for whatever reason, this description doesn't adequately explain the tested cases below:

  • ~1 ( ≥1, <2 ) → =dev-rust/foo-1*:=
  • ~1.0 ( ≥1.0, <1.1 ) → =dev-rust/foo-1.0*:=
  • ~1.1 ( ≥1.1, <1.2 ) → =dev-rust/foo-1.1*:=
  • ~1.0.0 ( ≥1.0.0, <1.1 ) → =dev-rust/foo-1.0*:=
  • ~1.0.1 ( ≥1.0.1, <1.1 ) → ( =dev-rust/foo-1.0*:= >=dev-rust/foo-1.0.1 )
  • ~1.1.0 ( ≥1.1.0, <1.2 ) → =dev-rust/foo-1.1*:=
  • ~1.1.1 ( ≥1.1.1, <1.2 ) → ( =dev-rust/foo-1.1*:= >=dev-rust/foo-1.1.1 )

Wildcard (*) versions

Cargo Specification

Running Tests

Running tests through portage with rust is especially painful to do at scale, due to many crates incurring circular dependencies in their test dependency graph.

There usually isn't much circularity between a crate and itself at depth 1, but beyond that, it gets messy, with things like syn having test dependencies, which in turn, have a test dependency on syn.

Subsequently a global FEATURES=test of any kind is completely impossible.

A demonstration

Just so you can see how terrible this is, here's what portage does for dev-rust/syn with global FEATURES=test (after appeasing a dozen USE changes)

[ebuild  N     ] dev-rust/syn-1.0.7:1.0.7/r0::rust-dev  USE="printing proc-macro test" 0 KiB
[ebuild  N     ]  dev-rust/proc-macro2-1.0.5:1.0.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/unicode-xid-0.2.0:0.2.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/quote-1.0.2:1.0.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/rustversion-0.1.4:0.1.4/r0::rust-dev  USE="test" 12 KiB
[ebuild  N     ]    dev-rust/trybuild-1.0.17:1.0.17/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/glob-0.3.0:0.3.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/tempdir-0.3.7:0.3.7/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/rand-0.4.6:0.4.6/r0::rust-dev  USE="std test" 0 KiB
[ebuild  N     ]        dev-rust/libc-0.2.65:0.2.65/r0::rust-dev  USE="test -rustc-dep-of-std" 0 KiB
[ebuild  N     ]         dev-rust/rustc-std-workspace-core-1.0.0:1.0.0/r0::rust-dev  USE="test" 1 KiB
[ebuild  N     ]       dev-rust/remove_dir_all-0.5.2:0.5.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/doc-comment-0.3.1:0.3.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/lazy_static-1.4.0:1.4.0/r0::rust-dev  USE="test -spin-no-std" 0 KiB
[ebuild  N     ]      dev-rust/spin-0.5.2:0.5.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/serde-1.0.101:1.0.101/r0::rust-dev  USE="derive test" 0 KiB
[ebuild  N     ]      dev-rust/serde_derive-1.0.89-r1:1.0.89/r1::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/proc-macro2-0.4.30:0.4.30/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/unicode-xid-0.1.0:0.1.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/quote-0.6.13:0.6.13/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/syn-0.15.29-r1:0.15.29/r1::rust-dev  USE="printing proc-macro test" 0 KiB
[ebuild  N     ]     dev-rust/serde_json-1.0.41:1.0.41/r0::rust-dev  USE="test -indexmap" 0 KiB
[ebuild  N     ]      dev-rust/itoa-0.4.4:0.4.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/ryu-1.0.1:1.0.1/r0::rust-dev  USE="test -no-panic" 0 KiB
[ebuild  N     ]       dev-rust/num_cpus-1.10.1:1.10.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/rand-0.5.6:0.5.6/r0::rust-dev  USE="std test -log -serde1" 0 KiB
[ebuild  N     ]        dev-rust/rand_core-0.3.1:0.3.1/r0::rust-dev  USE="serde1 test" 0 KiB
[ebuild  N     ]         dev-rust/rand_core-0.4.2:0.4.2/r0::rust-dev  USE="serde1 test" 0 KiB
[ebuild  N     ]        dev-rust/bincode-1.2.0:1.2.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/byteorder-1.3.2:1.3.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]          dev-rust/quickcheck-0.8.5:0.8.5/r0::rust-dev  USE="regex test use-logging" 0 KiB
[ebuild  N     ]           dev-rust/rand-0.6.5:0.6.5/r0::rust-dev  USE="std test -serde1" 0 KiB
[ebuild  N     ]            dev-rust/rand_chacha-0.1.1:0.1.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/autocfg-0.1.6:0.1.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/rand_hc-0.1.0:0.1.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/rand_isaac-0.1.1:0.1.1/r0::rust-dev  USE="serde1 test" 0 KiB
[ebuild  N     ]            dev-rust/rand_jitter-0.1.4:0.1.4/r0::rust-dev  USE="test -log" 0 KiB
[ebuild  N     ]             dev-rust/log-0.4.8:0.4.8/r0::rust-dev  USE="test -serde -sval" 0 KiB
[ebuild  N     ]              dev-rust/cfg-if-0.1.10:0.1.10/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/sval-0.4.7:0.4.7/r0::rust-dev  USE="test -arbitrary-depth -derive -serde" 0 KiB
[ebuild  N     ]               dev-rust/quickcheck-0.9.0:0.9.0/r0::rust-dev  USE="regex test use-logging" 0 KiB
[ebuild  N     ]                dev-rust/rand-0.7.2:0.7.2/r0::rust-dev  USE="std test -log -serde1 -small_rng" 0 KiB
[ebuild  N     ]                 dev-rust/rand_core-0.5.1:0.5.1/r0::rust-dev  USE="serde1 std test" 0 KiB
[ebuild  N     ]                  dev-rust/getrandom-0.1.13:0.1.13/r0::rust-dev  USE="test -log" 0 KiB
[ebuild  N     ]                 dev-rust/rand_chacha-0.2.1:0.2.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                  dev-rust/c2-chacha-0.2.3:0.2.3/r0::rust-dev  USE="rustcrypto-api test" 0 KiB
[ebuild  N     ]                   dev-rust/ppv-lite86-0.2.6:0.2.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                   dev-rust/stream-cipher-0.3.2:0.3.2/r0::rust-dev  USE="test -dev" 0 KiB
[ebuild  N     ]                    dev-rust/generic-array-0.12.3:0.12.3/r0::rust-dev  USE="test -serde" 0 KiB
[ebuild  N     ]                     dev-rust/typenum-1.11.2:1.11.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                    dev-rust/blobby-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                   dev-rust/hex-literal-0.2.1:0.2.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                    dev-rust/hex-literal-impl-0.2.1:0.2.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                     dev-rust/proc-macro-hack-0.5.11:0.5.11/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]                 dev-rust/rand_hc-0.2.0:0.2.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/rand_pcg-0.2.1:0.2.1/r0::rust-dev  USE="test -serde1" 0 KiB
[ebuild  N     ]                dev-rust/env_logger-0.6.2:0.6.2/r0::rust-dev  USE="atty humantime regex termcolor test" 0 KiB
[ebuild  N     ]                 dev-rust/atty-0.2.13:0.2.13/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/humantime-1.3.0:1.3.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                  dev-rust/quick-error-1.2.2:1.2.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                  dev-rust/time-0.1.42:0.1.42/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]                 dev-rust/regex-1.3.1:1.3.1/r0::rust-dev  USE="perf-cache perf-literal test" 0 KiB
[ebuild  N     ]                  dev-rust/regex-syntax-0.6.12:0.6.12/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                  dev-rust/aho-corasick-0.7.6:0.7.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                   dev-rust/memchr-2.2.1:2.2.1/r0::rust-dev  USE="test -libc" 0 KiB
[ebuild  N     ]                  dev-rust/thread_local-0.3.6:0.3.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/termcolor-1.0.5:1.0.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/smallvec-0.6.10:0.6.10/r0::rust-dev  USE="test -serde" 0 KiB
[ebuild  N     ]               dev-rust/sval_derive-0.4.7:0.4.7/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/serde_test-1.0.102:1.0.102/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/rand_pcg-0.1.2:0.1.2/r0::rust-dev  USE="test -serde1" 0 KiB
[ebuild  N     ]            dev-rust/rand_xorshift-0.1.1:0.1.1/r0::rust-dev  USE="serde1 test" 0 KiB
[ebuild  N     ]            dev-rust/rand_os-0.1.3:0.1.3/r0::rust-dev  USE="test -log" 0 KiB
[ebuild  N     ]            dev-rust/average-0.9.4:0.9.4/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]             dev-rust/conv-0.3.3:0.3.3/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]              dev-rust/custom_derive-0.1.7:0.1.7/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/rustc-serialize-0.3.24:0.3.24/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/rand-0.3.23:0.3.23/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/float-ord-0.2.0:0.2.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/num-integer-0.1.41:0.1.41/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/num-traits-0.2.8:0.2.8/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/rand_xoshiro-0.1.0:0.1.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/serde_bytes-0.11.2:0.11.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/no-panic-0.1.11:0.1.11/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]      dev-rust/indexmap-1.3.0:1.3.0/r0::rust-dev  USE="-rayon -serde -test" 0 KiB
[ebuild  N     ]     dev-rust/toml-0.5.3:0.5.3/r0::rust-dev  USE="test -preserve-order" 0 KiB
[ebuild  N     ]      dev-rust/linked-hash-map-0.5.2:0.5.2/r0::rust-dev  USE="test -heapsize-impl -serde-impl" 0 KiB
[ebuild  N     ]       dev-rust/heapsize-0.4.2:0.4.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]  dev-rust/insta-0.11.0:0.11.0/r0::rust-dev  USE="test -redactions -ron" 0 KiB
[ebuild  N     ]   dev-rust/console-0.8.0:0.8.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/clicolors-control-1.0.1:1.0.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/unicode-width-0.1.6:0.1.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/termios-0.3.1:0.3.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/difference-2.0.0:2.0.0/r0::rust-dev  USE="test -bin" 0 KiB
[ebuild  N     ]    dev-rust/getopts-0.2.21:0.2.21/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/quickcheck-0.4.1:0.4.1/r0::rust-dev  USE="test use-logging" 0 KiB
[ebuild  N     ]     dev-rust/env_logger-0.3.5:0.3.5/r0::rust-dev  USE="regex test" 0 KiB
[ebuild  N     ]      dev-rust/log-0.3.9:0.3.9/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/regex-0.1.80:0.1.80/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/aho-corasick-0.5.3:0.5.3/r0::rust-dev  USE="test -dot" 0 KiB
[ebuild  N     ]        dev-rust/memchr-0.1.11:0.1.11/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/quickcheck-0.2.27:0.2.27/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/thread_local-0.2.7:0.2.7/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/thread-id-2.0.0:2.0.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/kernel32-sys-0.2.2:0.2.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]          dev-rust/winapi-0.2.8:0.2.8/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]          dev-rust/winapi-build-0.1.1:0.1.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/regex-syntax-0.3.9:0.3.9/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/utf8-ranges-0.1.3:0.1.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/lazy_static-0.1.16:0.1.16/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/term-0.2.14:0.2.14/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/serde_yaml-0.8.11:0.8.11/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/dtoa-0.4.4:0.4.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/yaml-rust-0.4.3:0.4.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/quickcheck-0.7.2:0.7.2/r0::rust-dev  USE="regex test use-logging" 0 KiB
[ebuild  N     ]      dev-rust/rand_core-0.2.2:0.2.2/r0::rust-dev  USE="test -serde1" 0 KiB
[ebuild  N     ]      dev-rust/env_logger-0.5.13:0.5.13/r0::rust-dev  USE="regex test" 0 KiB
[ebuild  N     ]    dev-rust/unindent-0.1.5:0.1.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/uuid-0.7.4:0.7.4/r0::rust-dev  USE="serde test v4 -slog -u128 -v3 -v5" 0 KiB
[ebuild  N     ]    dev-rust/md5-0.6.1:0.6.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/sha1-0.6.0:0.6.0/r0::rust-dev  USE="-serde -test" 0 KiB
[ebuild  N     ]    dev-rust/slog-2.5.2:2.5.2/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]   dev-rust/pest-2.1.2:2.1.2/r0::rust-dev  USE="test -pretty-print" 0 KiB
[ebuild  N     ]    dev-rust/ucd-trie-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/pest_derive-2.1.0:2.1.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/pest_generator-2.1.1:2.1.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/pest_meta-2.1.2:2.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/maplit-1.0.2:1.0.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/sha_1-0.8.1:0.8.1/r0::rust-dev  USE="test -asm" 0 KiB
[ebuild  N     ]       dev-rust/block-buffer-0.7.3:0.7.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/block-padding-0.1.4:0.1.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/byte-tools-0.3.1:0.3.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/digest-0.8.1:0.8.1/r0::rust-dev  USE="dev test" 0 KiB
[ebuild  N     ]       dev-rust/fake-simd-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/opaque-debug-0.2.3:0.2.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/sha1-asm-0.4.3:0.4.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/cc-1.0.46:1.0.46/r0::rust-dev  USE="-bin -parallel -test" 0 KiB
[ebuild  N     ]       dev-rust/hex-literal-0.1.4:0.1.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/hex-literal-impl-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/proc-macro-hack-0.4.2:0.4.2/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]          dev-rust/proc-macro-hack-impl-0.4.2:0.4.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/ron-0.5.1:0.5.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/base64-0.10.1:0.10.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/bitflags-1.2.1:1.2.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/serde_bytes-0.10.4:0.10.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/bincode-0.8.0:0.8.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/num-traits-0.1.43:0.1.43/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]  dev-rust/rayon-1.2.0:1.2.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/crossbeam-deque-0.7.1:0.7.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/crossbeam-epoch-0.7.2:0.7.2/r0::rust-dev  USE="std test" 0 KiB
[ebuild  N     ]     dev-rust/arrayvec-0.4.12:0.4.12/r0::rust-dev  USE="test -serde-1" 0 KiB
[ebuild  N     ]      dev-rust/nodrop-0.1.14:0.1.14/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/matches-0.1.8:0.1.8/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]     dev-rust/crossbeam-utils-0.6.6:0.6.6/r0::rust-dev  USE="std test" 0 KiB
[ebuild  N     ]     dev-rust/memoffset-0.5.1:0.5.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]      dev-rust/rustc_version-0.2.3:0.2.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]       dev-rust/semver-0.9.0:0.9.0/r0::rust-dev  USE="test -ci" 0 KiB
[ebuild  N     ]        dev-rust/semver-parser-0.7.0:0.7.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]        dev-rust/crates-index-0.5.1:0.5.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/git2-0.6.11:0.6.11/r0::rust-dev  USE="curl https ssh test" 0 KiB
[ebuild  N     ]          dev-rust/bitflags-0.9.1:0.9.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]          dev-rust/libgit2-sys-0.6.19:0.6.19/r0::rust-dev  USE="curl https ssh test" 0 KiB
[ebuild  N     ]           dev-rust/libz-sys-1.0.25:1.0.25/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/pkg-config-0.3.16:0.3.16/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/cmake-0.1.42:0.1.42/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/curl-sys-0.4.23:0.4.23/r0::rust-dev  USE="ssl test -http2 -mesalink -static-ssl" 0 KiB
[ebuild  N     ]            dev-rust/openssl-sys-0.9.52:0.9.52/r0::rust-dev  USE="test vendored" 0 KiB
[ebuild  N     ]             dev-rust/openssl-src-111.6.0:111.6.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/libnghttp2-sys-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/mesalink-1.1.0:1.1.0/r0::rust-dev  USE="test -jemalloc-allocator" 0 KiB
[ebuild  N     ]             dev-rust/enum_to_u8_slice_derive-0.1.1:0.1.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/quote-0.3.15:0.3.15/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/syn-0.11.11:0.11.11/r0::rust-dev  USE="parsing printing test" 0 KiB
[ebuild  N     ]               dev-rust/unicode-xid-0.0.4:0.0.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/synom-0.11.3:0.11.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/parking_lot-0.9.0:0.9.0/r0::rust-dev  USE="test -deadlock-detection -owning-ref -serde" 0 KiB
[ebuild  N     ]              dev-rust/lock_api-0.3.1:0.3.1/r0::rust-dev  USE="owning-ref serde test" 0 KiB
[ebuild  N     ]               dev-rust/scopeguard-1.0.0:1.0.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/owning_ref-0.4.0:0.4.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/stable_deref_trait-1.1.1:1.1.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/parking_lot_core-0.6.2:0.6.2/r0::rust-dev  USE="deadlock-detection test" 0 KiB
[ebuild  N     ]               dev-rust/petgraph-0.4.13:0.4.13/r0::rust-dev  USE="graphmap test -all -serde-1" 0 KiB
[ebuild  N     ]                dev-rust/fixedbitset-0.1.9:0.1.9/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/ordermap-0.3.5:0.3.5/r0::rust-dev  USE="test -serde-1" 0 KiB
[ebuild  N     ]                 dev-rust/fnv-1.0.6:1.0.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/itertools-0.7.11:0.7.11/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]                  dev-rust/either-1.5.3:1.5.3/r0::rust-dev  USE="test -serde" 0 KiB
[ebuild  N     ]                 dev-rust/quickcheck-0.6.2:0.6.2/r0::rust-dev  USE="regex test use-logging" 0 KiB
[ebuild  N     ]                dev-rust/defmac-0.1.3:0.1.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/odds-0.2.26:0.2.26/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]               dev-rust/thread-id-3.3.0:3.3.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/backtrace-0.3.38:0.3.38/r0::rust-dev  USE="libbacktrace test -cpp-demangle -gimli-symbolize -serialize-rustc -serialize-serde" 0 KiB
[ebuild  N     ]                dev-rust/rustc-demangle-0.1.16:0.1.16/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/backtrace-sys-0.1.31:0.1.31/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/cpp_demangle-0.2.13:0.2.13/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]                dev-rust/addr2line-0.10.0:0.10.0/r0::rust-dev  USE="cpp-demangle rustc-demangle std-object -test" 0 KiB
[ebuild  N     ]                 dev-rust/fallible-iterator-0.2.0:0.2.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/gimli-0.19.0:0.19.0/r0::rust-dev  USE="write -test" 0 KiB
[ebuild  N     ]                 dev-rust/intervaltree-0.2.4:0.2.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/lazycell-1.2.1:1.2.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                 dev-rust/object-0.12.0:0.12.0/r0::rust-dev  USE="compression test wasm" 0 KiB
[ebuild  N     ]                  dev-rust/goblin-0.0.22:0.0.22/r0::rust-dev  USE="alloc test" 0 KiB
[ebuild  N     ]                   dev-rust/scroll-0.9.2:0.9.2/r0::rust-dev  USE="derive test" 0 KiB
[ebuild  N     ]                    dev-rust/scroll_derive-0.9.5:0.9.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                   dev-rust/plain-0.2.3:0.2.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                  dev-rust/flate2-1.0.13:1.0.13/r0::rust-dev  USE="rust-backend -test" 0 KiB
[ebuild  N     ]                   dev-rust/crc32fast-1.2.0:1.2.0/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]                   dev-rust/futures-0.1.29:0.1.29/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                   dev-rust/miniz_oxide-0.3.5:0.3.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                    dev-rust/adler32-1.0.4:1.0.4/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                  dev-rust/parity-wasm-0.38.0:0.38.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/findshlibs-0.5.0:0.5.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/goblin-0.0.24:0.0.24/r0::rust-dev  USE="alloc test" 0 KiB
[ebuild  N     ]                dev-rust/memmap-0.7.0:0.7.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/ring-0.16.9:0.16.9/r0::rust-dev  USE="dev-urandom-fallback test" 0 KiB
[ebuild  N     ]              dev-rust/untrusted-0.7.0:0.7.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/rustls-0.16.0:0.16.0/r0::rust-dev  USE="logging test" 0 KiB
[ebuild  N     ]              dev-rust/sct-0.6.0:0.6.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/webpki-0.21.0:0.21.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/base64-0.9.3:0.9.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/safemem-0.3.3:0.3.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/tempfile-3.1.0:3.1.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/webpki-roots-0.17.0:0.17.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/walkdir-2.2.9:2.2.9/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/same-file-1.0.5:1.0.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/jemallocator-0.3.2:0.3.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/jemalloc-sys-0.3.2:0.3.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/fs_extra-1.1.0:1.1.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]              dev-rust/jemalloc-ctl-0.3.3:0.3.3/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]               dev-rust/paste-0.1.6:0.1.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]                dev-rust/paste-impl-0.1.6:0.1.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/libssh2-sys-0.2.13:0.2.13/r0::rust-dev  USE="test -vendored-openssl" 0 KiB
[ebuild  N     ]          dev-rust/url-1.7.2:1.7.2/r0::rust-dev  USE="test -heap-size -query-encoding -rustc-serialize -serde" 0 KiB
[ebuild  N     ]           dev-rust/idna-0.1.5:0.1.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/unicode-bidi-0.3.4:0.3.4/r0::rust-dev  USE="test -with-serde" 0 KiB
[ebuild  N     ]            dev-rust/unicode-normalization-0.1.8:0.1.8/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/rustc-test-0.3.0:0.3.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]             dev-rust/term-0.4.6:0.4.6/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/percent-encoding-1.0.1:1.0.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/encoding-0.2.33:0.2.33/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/encoding-index-singlebyte-1.20141219.5:1.20141219.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/encoding-index-korean-1.20141219.5:1.20141219.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/encoding-index-japanese-1.20141219.5:1.20141219.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/encoding-index-simpchinese-1.20141219.5:1.20141219.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/encoding-index-tradchinese-1.20141219.5:1.20141219.5/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/serde-0.8.23:0.8.23/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]           dev-rust/serde_json-0.8.6:0.8.6/r0::rust-dev  USE="-test" 0 KiB
[ebuild  N     ]            dev-rust/itoa-0.1.1:0.1.1/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]            dev-rust/dtoa-0.2.2:0.2.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]          dev-rust/openssl-probe-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]         dev-rust/glob-0.2.11:0.2.11/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/rayon-core-1.6.0:1.6.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/crossbeam-queue-0.1.2:0.1.2/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]    dev-rust/scoped-tls-1.0.0:1.0.0/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]  dev-rust/ref-cast-0.2.7:0.2.7/r0::rust-dev  USE="test" 0 KiB
[ebuild  N     ]   dev-rust/ref-cast-impl-0.2.7:0.2.7/r0::rust-dev  USE="test" 0 KiB

Total: 256 packages (256 new), Size of downloads: 13 KiB

 * Error: circular dependencies:

(dev-rust/quote-1.0.2:1.0.2/r0::rust-dev, ebuild scheduled for merge) depends on
 (dev-rust/proc-macro2-1.0.5:1.0.5/r0::rust-dev, ebuild scheduled for merge) (buildtime_slot_op)
  (dev-rust/quote-1.0.2:1.0.2/r0::rust-dev, ebuild scheduled for merge) (buildtime_slot_op)

It might be possible to break this cycle
by applying the following change:
- dev-rust/proc-macro2-1.0.5 (Change USE: -test)

Cure

Instead, one needs to, for each crate one wants to test, invoke portage as follows.

  1. Install the crate with FEATURES=-test emerge -1 =dev-rust/crate-name-1.2.3
  2. Install the crates test dependencies using FEATURES=-test emerge --with-test-deps --onlydeps -1 =dev-rust/crate-name-1.2.3
  3. Run the crates tests with FEATURES=test emerge -1 =dev-rust/crate-name-1.2.3

This process is what I do when packaging rust crates, in addition to invoking a command to uninstall all crates prior to step 1, and each stage above must complete successfully in order to commit it.

Other testers and maintainers really aught to do the same, and it may help to even write a small script to simplify this, as you'll likely need it a lot

It is also very beneficial to include -j10 -q in steps 1 and 2, regardless of how many cores you actually have, as the "compile" ( which is just an unpackage, patch, repackage, roll out to dir) for rust crates is incredibly IO bound, and running it quietly allows the graph to be installed in parallel, greatly reducing install time.

Downsides

The biggest downsides of this 3-pronged approach is it does mean that:

  • Only the top level crate gets tested
  • Lower level crates must be installed without testing in order to simply test the top level crate
  • Lots of work must be done fussing with keywords to make it install

But there's currently literally no alternative. Please pursue bug #697914