obi1kenobi / cargo-semver-checks

Scan your Rust crate for semver violations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to enable dependency's features needed to build the crate

nwalfield opened this issue · comments

Steps to reproduce the bug with the above code

See the "Actual Behavior" section.

Actual Behaviour

$ git clone https://gitlab.com/sequoia-pgp/sequoia-cert-store.git
$ cd sequoia-cert-store
$ git checkout cee6bfd8
$ cargo set-version 0.5.1
   Upgrading sequoia-cert-store from 0.5.0 to 0.5.1
$ cargo semver-checks
     Parsing sequoia-cert-store v0.5.1 (current)
error: running cargo-doc on crate sequoia-cert-store failed with output:
-----
...
error: failed to run custom build command for `sequoia-openpgp v1.19.0`

Caused by:
  process didn't exit successfully: `/tmp/sequoia-cert-store/target/semver-checks/local-sequoia_cert_store-0_5_1/target/semver-checks/target/debug/build/sequoia-openpgp-a7260106954c3cab/build-script-build` (exit status: 1)
  --- stderr
  No cryptographic backend selected.

  Sequoia requires a cryptographic backend.  This backend is selected at compile
  time using feature flags.

  See https://crates.io/crates/sequoia-openpgp#crypto-backends
warning: build failed, waiting for other jobs to finish...

-----

error: failed to build rustdoc for crate sequoia-cert-store v0.5.1
note: this is usually due to a compilation error in the crate,
      and is unlikely to be a bug in cargo-semver-checks
note: the following command can be used to reproduce the compilation error:
      cargo new --lib example &&
          cd example &&
          echo '[workspace]' >> Cargo.toml &&
          cargo add --path /tmp/sequoia-cert-store --no-default-features --features  &&
          cargo check

error: aborting due to failure to build rustdoc for crate sequoia-cert-store v0.5.1

The error is because we didn't select a cryptographic backend.

Trying again:

$ cargo semver-checks --features sequoia-openpgp/crypto-nettle
     Parsing sequoia-cert-store v0.5.1 (current)
error: `cargo metadata` exited with an error: error: failed to parse manifest at `/tmp/sequoia-cert-store/target/semver-checks/local-sequoia_cert_store-0_5_1-aaa4629efb3c60e8/Cargo.toml`

Caused by:
  feature `sequoia-openpgp/crypto-nettle` in dependency `sequoia-cert-store` is not allowed to contain slashes
  If you want to enable features of a transitive dependency, the direct dependency needs to re-export those features from the `[features]` table.

Tools like cargo build don't impose this restriction. Although I could manually edit our Cargo.toml to select a backend:

$ git diff  Cargo.toml
diff --git a/Cargo.toml b/Cargo.toml
index 90ea46f..2b05ba1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "sequoia-cert-store"
 description = "A certificate database interface."
-version = "0.5.0"
+version = "0.5.1"
 authors = ["Neal H. Walfield <neal@sequoia-pgp.org>",
         "Justus Winter <justus@sequoia-pgp.org>"]
 homepage = "https://sequoia-pgp.org/"
@@ -26,7 +26,7 @@ num_cpus = "1"
 openpgp-cert-d = "0.3.1"
 parking_lot = "0.12"
 rayon = "1"
-sequoia-openpgp = { version = "1.19.0", default-features = false }
+sequoia-openpgp = { version = "1.19.0", features = ["crypto-nettle"] }
 sequoia-net = { version = "0.28", default-features = false }
 smallvec = "1.1"
 thiserror = "1.0.2"

Now, cargo semver-checks can build the current version, but it fails on the last version:

$ cargo semver-checks
     Parsing sequoia-cert-store v0.5.1 (current)
      Parsed [   9.515s] (current)
     Parsing sequoia-cert-store v0.5.0 (baseline)
error: running cargo-doc on crate sequoia-cert-store failed with output:
-----
...
error: failed to run custom build command for `sequoia-openpgp v1.19.0`

Caused by:
  process didn't exit successfully: `/tmp/sequoia-cert-store/target/semver-checks/registry-sequoia_cert_store-0_5_0/target/semver-checks/target/debug/build/sequoia-openpgp-a7260106954c3cab/build-script-build` (exit status: 1)
  --- stderr
  No cryptographic backend selected.

  Sequoia requires a cryptographic backend.  This backend is selected at compile
  time using feature flags.

  See https://crates.io/crates/sequoia-openpgp#crypto-backends
warning: build failed, waiting for other jobs to finish...

-----

error: failed to build rustdoc for crate sequoia-cert-store v0.5.0
note: this is usually due to a compilation error in the crate,
      and is unlikely to be a bug in cargo-semver-checks
note: the following command can be used to reproduce the compilation error:
      cargo new --lib example &&
          cd example &&
          echo '[workspace]' >> Cargo.toml &&
          cargo add sequoia-cert-store@=0.5.0 --no-default-features --features  &&
          cargo check

Expected Behaviour

I think cargo semver-checks should allow selecting the same features as cargo build.

Generated System Information

$ cargo semver-checks --bugreport
#### Software version

cargo-semver-checks 0.30.0

#### Operating system

Linux 6.1.0-17-amd64

#### Command-line

```bash
/home/us/.cargo/bin/cargo-semver-checks semver-checks --bugreport 

cargo version

> cargo -V 
cargo 1.75.0 (1d8b05cdd 2023-11-20)

Compile time information

  • Profile: release
  • Target triple: x86_64-unknown-linux-gnu
  • Family: unix
  • OS: linux
  • Architecture: x86_64
  • Pointer width: 64
  • Endian: little
  • CPU features: fxsr,sse,sse2
  • Host: x86_64-unknown-linux-gnu

### Build Configuration

_No response_

### Additional Context

Thanks for working on this!

This is very interesting — I didn't realize cargo supported this way of specifying features! Since I'm not familiar with this, I'd love to get your thoughts on a few questions.

How do users of sequoia-cert-store select a backend today?

Say I created a new Rust project and ran cargo add sequoia-cert-store, what happens next? Would a plain cargo check work immediately, or do I need to configure something else first?

sequoia-openpgp supports several different cryptographic backends (specifically: nettle, openssl, botan v2, botan v3, rust-crypto, and Windows CNG). To use sequoia-openpgp, exactly one crypto backend needs to be selected. Unfortunately, there is no easy way to express this using cargo, because features in cargo are additive. As such, we add a check in build.rs to enforce this restriction.

Regarding sequoia-cert-store, end users do not use it: it's a library. If someone were to add sequoia-cert-store to their project, there are two approaches. If their crate is also a library, they should not select a crypto backend (just like sequoia-cert-store doesn't). If they are an end user application, they may select a default crypto backend, but should allow the user to override it.

The reason libraries should not select a backend is, again, because features are additive. If a different library uses sequoia-openpgp and selects a different backend, then the two libraries couldn't be used by the same crate!

sequoia-cert-store, a library, depends on sequoia-openpgp in the usual way, as seen in its Cargo.toml:

sequoia-openpgp = { version = "1.19.0", default-features = false }

You can see what sequoia-sq, an end user application, does in its Cargo.toml:

[features] default = [     "crypto-nettle",     "dot-writer", ]
crypto-nettle = ["sequoia-openpgp/crypto-nettle"]
crypto-openssl = ["sequoia-openpgp/crypto-openssl"]
crypto-botan = ["sequoia-openpgp/crypto-botan"]
crypto-botan2 = ["sequoia-openpgp/crypto-botan2"]
crypto-cng = ["sequoia-openpgp/crypto-cng"]
crypto-rust = ["sequoia-openpgp/crypto-rust"]

It selects a default crypto backend (Nettle) so that cargo install works, but allows the user to override it. This is what Fedora does when they package it (they prefer OpenSSL).

Say I created a new Rust project and ran cargo add sequoia-cert-store, what happens next? Would a plain cargo check work immediately, or do I need to configure something else first?

That's easy to test:

$ mkdir some-crate
$ cd some-crate/
$ cargo init
     Created binary (application) package
$ cargo add sequoia-cert-store
    Updating crates.io index
      Adding sequoia-cert-store v0.5.0 to dependencies.
    Updating crates.io index
$ cargo check
   Compiling sequoia-openpgp v1.19.0
error: failed to run custom build command for `sequoia-openpgp v1.19.0`

Caused by:
  process didn't exit successfully: `/tmp/some-crate/target/debug/build/sequoia-openpgp-3f9e96105f0e50d2/build-script-build` (exit status: 1)
  --- stderr
  No cryptographic backend selected.

  Sequoia requires a cryptographic backend.  This backend is selected at compile
  time using feature flags.

  See https://crates.io/crates/sequoia-openpgp#crypto-backends
warning: build failed, waiting for other jobs to finish...

That link explains what you need to do. It's divided into two sections: one for libraries (intermediate applications), and one for leaf crates (applications).

I hope that answers your questions! :)

Fascinating. I've never seen a workflow where using a library crate requires selecting a feature in one of its dependencies. Thanks for the very thorough answer, I appreciate it! (Perhaps obviously, my cargo check question was intended to get at the expected workflow users should have — which you answered as well.)

This is something cargo-semver-checks should support. I'm leaning toward tagging it as C-enhancement rather than C-bug since it'll require a bit of design work and some new implementation paths in the internals, which is more than most bugfixes.

Might you be open to contributing PRs for this?

I'd also love sponsorship from @sequoia-pgp and the pep foundation, if you are finding cargo-semver-checks useful and would like to help accelerate its development! ❤️

Thanks for following up. As is customary around where I live, I took the last few days off.

Might you be open to contributing PRs for this?

At this point, no. I don't have the bandwidth for that.

I'd also love sponsorship from @sequoia-pgp and the pep foundation, if you are finding cargo-semver-checks useful and would like to help accelerate its development! ❤️

Yeah, that would be great. The pep foundation is bankrupt since September 2023. Sequoia is only still around because the Sovereign Tech Fund decided to fund us. That money runs out at the end of 2024, and they've been managing expectations about future funding. I'd love to compare notes on how to acquire funding, however! Let me know if you are up for that.

Would love to compare notes! I'm applying for a NLNet grant, and thinking about applying to the OpenTech fund grant program.

I'm not eligible for Sovereign Tech Fund funding since I'm not based in Germany, and all their current grants I'm familiar with require that. But if there's a way to get Sovereign Tech Fund money to cargo-semver-checks, I'd love to know about it! I've already filled out their recent survey for their upcoming OSS fellowship, and I recommend all OSS maintainers do the same: https://survey.sovereigntechfund.de/968766

Another thing I've heard some projects do is work with unaffiliated contributors to help them apply for grants, and then ask for a split of the grant money between the project (for ongoing maintenance, code reviews, long-term work like architecture and test infra, etc.) and the contributor themselves. I've heard of 60%-40% splits between contributor and project, which I'd be very happy with from the project side.

If you or someone you know is able to find a grant like the above that would be okay with splitting the funding between the contributor and the project itself, I'd love to support them in putting together a grant proposal, identifying what to build, and helping them achieve their goals.

Would love to compare notes!

Let's continue the discussion via email: firstname@lastname dot org.

I'm not eligible for Sovereign Tech Fund funding since I'm not based in Germany, and all their current grants I'm familiar with require that.

Perhaps you are thinking of prototype fund. STF has no such restrictions. I've bet you've heard of curl, for instance. Daniel is in Sweden. The Ruby Gems people are in the US. etc.

I'd love to know about it! I've already filled out their recent survey for their upcoming OSS fellowship, and I recommend all OSS maintainers do the same: https://survey.sovereigntechfund.de/968766

I need to manage your expectations here: AIUI, that's still very much in the exploratory phase.

Another thing I've heard some projects do is work with unaffiliated contributors to help them apply for grants, and then ask for a split of the grant money between the project (for ongoing maintenance, code reviews, long-term work like architecture and test infra, etc.) and the contributor themselves. I've heard of 60%-40% splits between contributor and project, which I'd be very happy with from the project side.

Are you suggesting that you want to work on Sequoia? Or, what are you thinking?