rustrust-cargo

How to override the optimization levels of some dependencies, transitively?


In the following not-so-simple situation:

  1. A root workspace, with a few crates including root-crypto.
    • Where the root-crypto crate depends on various crypto crates: k256, sha2, sha3, ...
  2. An application workspace, with a few binaries including app-foo.
    • Where the app-foo crate depends on root-crypto amongst other root-* crates.

For debugging purposes, it is desirable to compile app-foo and its other app-* and root-* dependencies in debug mode (opt-level at 0 or 1).

However, compiling the cryptographic crates -- especially k256 -- in debug mode is truly terrible for performance: calculating one signature takes 20x longer in debug, compared to release!

The key answer appears to be to override the opt-level of k256 (see Profiles), but how?

If in the root workspace, one uses:

[profile.dev.package."*"]
opt-level = 3

This will likely work when compiling within the root workspace, but not within the app workspace.

If in the app workspace, one uses:

[profile.dev.package."*"]
opt-level = 3

Then the root-* dependencies will also get optimized, which is undesirable.

Is specifying the overrides in the root-crypto's Cargo.toml sufficient, so it applies to all its users?

Is specifying the top-level crates (k256, sha2, and sha3) sufficient, or does one need to specify all their transitive dependencies too? There's 28 in total for now, already, and as versions are upgraded this list may change...

base16ct
base64ct
cfg-if
const-oid
cpufeatures
crypto-bigint
der
digest
ecdsa
elliptic-curve
ff
generic-array
group
hmac
k256
keccak
once_cell
pem-rfc7468
pkcs8
rand_core
rfc6979
sec1
sha2
sha3
signature
spki
subtle
zeroize

Solution

  • Unfortunately, there doesn't appear to be any good way to override the opt-level of specific dependencies and their transitive dependencies, for all crate users.

    Is specifying the overrides in the root-crypto's Cargo.toml sufficient, so it applies to all its users?

    Cargo does not allow it, requiring that such an override be done in the workspace's Cargo.toml instead.

    Experimentation confirms that a dependency from another workspace will then NOT apply the overrides.

    Is specifying the top-level crates (k256, sha2, and sha3) sufficient, or does one need to specify all their transitive dependencies too?

    Experimentation confirms that specifying only the top-level crates means that only the top-level crates are compiled with the override, their dependencies are not.

    There does not appear to be an syntax in the documentation that hints at being able to specify an override for a crate and its transitive dependencies.