When I do cargo publish of my library it fails to compile the project because for a some reason it uses different version of a dependency. But if I do cargo build it works fine.
I see that for cargo publish it uses two different version of one of the dependencies:
Compiling bitcoin v0.27.1
Compiling bitcoin v0.28.1
And it fails later because one of the dependencies uses 0.27.1 and another 0.28.1.
The dependency is specified as bitcoin = "=0.27.1" in Cargo.toml. If I look into Cargo.lock file I see only version 0.27.1. I.e. only one entry, no other versions in Cargo.lock. cargo tree shows only version 0.27.1 as well. And cargo build uses only 0.27.1 for compilation.
It's absolutely unclear where from the 0.28.1 comes from during the cargo publish
How I can tell cargo publish to not use 0.28.1 and stick to version in the Cargo.lock? I tried --locked and --frozen but I doesn't make any effect.
UPDATE
One of the dependencies has defined bitcoin = ">= 0.27" and it seems that Cargo tries to use the most up-to-date version 0.28.1 only because it fits that criteria for that lib. And 0.27.1 for others. That obviously would not work. How to enforce it to use one version?
UPDATE 2:
There is the whole tree of the conflicting versions cargo tree --all-features:
├── bitcoin v0.27.1
.
├── emerald-hwkey v0.2.0
│ ├── bitcoin v0.27.1 (*)
│ ├── hdpath v0.6.1
│ │ ├── bitcoin v0.28.1
Where hdpath:0.6.1's Crate.toml accepts any version via:
bitcoin = { version = ">= 0.27", optional = true }
So it's unclear why Cargo tries to upgrade this particular version and makes everything incompatible to each other.
UPDATE 3:
It seems that it works if I use a local version of hdpath with enforced ">= 0.27, < 0.28". But I don't want that because hdpath by itself doesn't have a reason for such restriction and works fine with any of the versions.
So I just need to make sure it uses the version compatible with the parent project. Is there any way?
Related
I was reading this at the guessing game tutorial inside the rust book
Ensuring Reproducible Builds with the Cargo.lock File
Cargo has a mechanism that ensures you can rebuild the same artifact every time you or anyone else builds your code: Cargo will use only the versions of the dependencies you specified until you indicate otherwise. For example, say that next week version 0.8.4 of the rand crate comes out, and that version contains an important bug fix, but it also contains a regression that will break your code. To handle this, Rust creates the Cargo.lock file the first time you run cargo build, so we now have this in the guessing_game directory.
When you build a project for the first time, Cargo figures out all the versions of the dependencies that fit the criteria and then writes them to the Cargo.lock file. When you build your project in the future, Cargo will see that the Cargo.lock file exists and use the versions specified there rather than doing all the work of figuring out versions again. This lets you have a reproducible build automatically. In other words, your project will remain at 0.8.3 until you explicitly upgrade, thanks to the Cargo.lock file.
but didn't quite understand how cargo garantees that we have/need the correct version of a dependency. For instance, if we put in the [dependecies] rand="0.8.3" it will not exactly download the crate at this version, but the crate the match the needs of our program but it's compatible with this version(?)
Please clarify this logic!
When specifying a crate in Cargo.toml, you can give an exact version (e.g. =0.8.3) or more general indications (e.g. 0.8.*).
If you specify rand = "=0.8.3" in Cargo.toml, then cargo will take version 0.8.3 (note the extra = inside the version requirement). But if you specify rand = "*", then the first time you build your crate it will take the latest version and write this version to Cargo.lock. That way if you rebuild your crate later cargo will reuse the same version even if a new version has been published on crates.io in the meantime.
Note btw that specifying rand = "0.8.3" does not mean "exactly version 0.8.3", but instead means "any version >=0.8.3 and <0.9": link.
I'm learning Rust from "Practical Rust Projects" by Shing Lyu. I'm now trying to build a game following the steps in Chapter 4. I'm working on Ubuntu 18.04 LTS.
After installing Rust and the Amethyst command line, I created a new project via amethyst new cat_volleyball. The next step is to run the engine using cargo run --features=vulkan
. When I do so, I get the error prompt below. Do you have suggestions on how to fix this?
error[E0433]: failed to resolve: could not find `__rt` in `quote`
--> /home/alberto/.cargo/registry/src/github.com-1ecc6299db9ec823/err-derive-0.1.6/src/lib.rs:145:63
|
145 | fn display_body(s: &synstructure::Structure) -> Option<quote::__rt::TokenStream> {
| ^^^^ could not find `__rt` in `quote`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
error: could not compile `err-derive`.
warning: build failed, waiting for other jobs to finish...
TL;DR Edit the Cargo.lock manually, please check the title below : How to force cargo to use yanked version of sub-dependency (for the proper steps)
Why this happens ?
This happened because in err-derive-0.1.6 is using quote-1.0.2 as dependency but in it's cargo.toml dependency declared like this:
[dependencies.quote]
version = "1.0.2"
This means cargo will use the latest minor update, so if quote-1.0.3 is out then cargo will use 1.0.3 instead 1.0.2. Please check caret-requirement. The problem in here is quote-1.0.3 breaks backward compatibility that comes from quote-1.0.2. In this case quote
How to force cargo to use specific version of sub-dependency
You can fix this issue by forcing the sub-dependency to use compatible version for your dependency.
This command will do it :
> cargo update -p quote --precise 1.0.2
How to force cargo to use yanked version of sub-dependency
Looks like quote-1.0.2 was yanked from crates.io, so command up above will not work because cargo will not be able to find the yanked version on crates.io . Since cargo update modifies the cargo.lock we can do it manually. To start clean :
Remove Cargo.lock
Run cargo update ( this will generate latest version Cargo.lock )
Edit Cargo.lock
Find the incompatible version of package in cargo.lock which is quote-1.0.3, It should look like this:
[[package]]
name = "quote"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
then simply change version to the compatible version in our case it is "1.0.2"
[[package]]
name = "quote"
version = "1.0.2"
After doing that do not run cargo update again, it will overwrite your changes and you'll not able to compile your project. Please remember this is a workaround for being able to continue the development, there is a reason to yank crates, do not use it in production it is best to wait dependent crates to update itself.
Note : In some cases you may get an error after editing cargo.lock:
error: Found argument 'Cargo.lock' which wasn't expected, or isn't valid in this context
#albus_c fixed this by doing :
A note for posterity: I fixed the issue removing rustc
(sudo apt remove rustc) and reinstalled as recommended on the Rust website,
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
After that everything worked fine.
The Cargo FAQ states that Cargo.lock is not used for libraries, instead using dependency version ranges found in Cargo.toml, to reduce lib duplication among shared dependencies.
However, I think there are instances where using a known successful build of a lib dependency is preferable. Namely, when a dependency no longer builds due to updates of its own dependencies.
Is it possible to configure Cargo to favour a library's Cargo.lock, over Cargo.toml, if it's available? Preferably on a by-package basis.
(Update: the issue below has been fixed in wither 0.5.1, where the dependency is now mongodb = "0.10.*". However, it seems that this issue would re-appear if mongodb updates its bson dependency - at least until wither's dependencies are updated once again to match. Or, as #Shepmaster mentions in his answer, until RFC 1977 is implemented.)
My particular situation is trying to use the package wither 0.5.0:
wither's Cargo.toml specifies dependencies mongodb = "<1.0" and bson = "<1.0"
mongodb's Cargo.toml specifies bson = "0.10.0"
bson's latest version is at 0.11.1
Without configuring dependencies further, bson 0.10.0 is used for mongodb, and bson 0.11.1 is used for wither. This causes compilation of wither to fail, as it uses some structures from bson to interact with mongodb.
My current workaround is a locally-cloned copy of wither, with an edited Cargo.toml to fix its version of bson. However, the git repository includes a committed Cargo.lock, which would allow me at least to use this repository as my dependency target, rather than cloning and modifying the package myself.
No, you cannot use a library's Cargo.lock.
as it uses some structures from bson to interact with mongodb.
This is the root problem. Currently, it's unknown to the dependency resolver that one crate has exposed another crate's types in a public interface. That will be addressed when RFC 1977 is implemented.
As described in Consolidating cargo dependencies, you can nudge the version of the dependency to be consolidated:
cargo update -p bson:0.11.1 --precise 0.10.0
See also:
Consolidating cargo dependencies
Set specific version of the dependency of a project's dependency in Cargo.toml or Cargo.lock
That being said, because of semver, your code works just fine:
[dependencies]
wither = "0.5.1"
mongodb = "0.3.7"
$ cargo tree --invert -p bson
bson v0.10.0
├── mongodb v0.3.7
│ ├── example v0.1.0 (file:///private/tmp/example)
│ └── wither v0.5.1
│ └── example v0.1.0 (file:///private/tmp/example) (*)
Seemingly unavoidably, bson 0.10.0 is used for mongodb, and bson 0.11.1 is used for wither.
This is not the case, as you can tell by (a) the example above and (b) your own statements about the acceptable version ranges.
I'm setting up a Rust server with Rocket and I'm trying to use it with a JWT library. They use different versions of the *ring* crate and I get an error during cargo build:
error: multiple packages link to native library `ring-asm`, but a native library can be linked only once
package `ring v0.12.1`
... which is depended on by `jsonwebtoken v4.0.1`
... which is depended on by `auther v0.1.0 (file:///home/drpytho/x/downloadble/auther)`
links to native library `ring-asm`
package `ring v0.11.0`
... which is depended on by `cookie v0.9.2`
... which is depended on by `rocket v0.3.6`
... which is depended on by `rocket_codegen v0.3.6`
... which is depended on by `auther v0.1.0 (file:///home/drpytho/x/downloadble/auther)`
also links to native library `ring-asm`
My Cargo.toml
[package]
name = "auther"
version = "0.1.0"
authors = ["Name <Email#mail.se>"]
[dependencies]
rocket = "0.3.6"
rocket_codegen = "0.3.6"
jsonwebtoken = "4"
serde_derive = "1"
serde = "1"
I read that you are supposed to fix the mismatching dependencies in your Cargo file, but I can't figure out how to do it.
You have to fix this by not transitively depending on different versions of crates that link to a native library.
There's no newer version of rocket available that depends on version 0.10 of cookie, which depends on ring 0.12, so you'll need to downgrade jsonwebtoken to 2.0.3.
You can work this out by checking the crates.io pages for the crates in question (like with jsonwebtoken), going back through older versions, and looking to see what dependencies it needs.
I'm trying to package a library using the cargo package manager for Rust. When I try to run cargo package per the documentation, I get the following output:
error: main function not found
error: aborting due to previous error
failed to verify package tarball
I'm confused. I'm trying to package a library (with useful external functions), so I expect that I don't need a main function. Here is my Cargo.toml:
[package]
name = "package-name"
version = "0.0.1"
authors = [ "Kevin Burke <kev#inburke.com>" ]
Here is my directory structure:
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── main.rs
What am I missing?
Ah! If you are packaging a library for other programs to use (as I am trying to do), you need to name your file lib.rs.
Alternatively, if you are packaging a binary, name your file main.rs (this was my mistake).