Let's say we want to add jsonwebtoken 8.2.0 to our Cargo.toml. That crate is dependent on ring 0.16.20, which is dependent on the web-sys 0.3.60 crate and that dependency is declared like this:
[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", target_env = ""))'.dependencies]
web-sys = { version = "0.3.37", default-features = false, features = ["Crypto", "Window"] }
For my project I don't need any JS/Wasm-related stuff whatsoever. But I noticed in my Cargo.lock several such dependencies were added as a result of that web-sys crate (such as wasm-bindgen for example). Is there a way to avoid that "noise"?
The Cargo.lock decides versions to be used for compilation on all possible platforms and to my knowledge, there is no way to override that.
Consider: Not doing so would be a headache. If someone on a new platform cloned your repo and built your crate, they'd have to have their Cargo.lock modified (and send you a patch?). If you updated a crate dependency on your system it would only update the locked versions for your platform, other people might end up with an inconsistent lock. To avoid the headache, just let cargo do with the Cargo.lock as it wants and ignore the contents.
If you want to reduce the noise a bit and hide the lock file diffs from git output, you could mark Cargo.lock as a binary file like shown here:
echo >>.gitattributes Cargo.lock binary
(though I don't know whether that won't have weird effects on windows line endings.)
Related
When I'm developing a Rust project, I usually use foo-crate = "*" for dependency versions unless I have a reason to pick a particular version.
Before sharing a project, I want to update the "*" dependency version numbers in Cargo.toml to those found in Cargo.lock. i.e. I want the "*" version number to be replaced with what I'm successfully using in the project.
When I only have two or three dependencies, it's not a concern to do this manually.
Now, I'm regularly depending on a dozen or more crates.
Is there an automated way to move version numbers from Cargo.lock to Cargo.toml?
I have a crate that has several dependencies that use one common dependency, same as the root project. An intersecting range, though.
I.e.,:
[dependencies]
bitcoin="0.28"
hdpath="0.6" <- this one depends on `>=0.27`
hwkey="0.1" <- this one depends on `=0.28`
And the current latest version is bitcoin:0.29.2
The current Cargo.lock file contains bitcoin:0.28.1 so it all works for all of the deps and compiles fine.
But if I try to publish the crate there is no way to enforce it using the version from Cargo.lock and it tries to use two different version of bitcoin. The latest 0.29.2 for hdpath because it allows any version, and 0.28.1 for other parts because they are not compatible with the latest one.
That obviously doesn't work because it produces incompatible data types.
Is there any way to force Cargo to disable such an upgrade and use version from the lock file?
I am creating a library, that is nearly close to its first release, so I would like to upload it to crates.io. Library has a multi-crate design, so I ended with something like:
- CrateA
- CrateProcMacros
- CrateC
- CrateD
- CrateE
- CrateF
- Cargo.toml (handles the workspace)
- Cargo.lock
...
where CrateA is the parent of the other crates, and has dependencies on another of those local crates, and some of those crates also depends on another ones. I mean, it's the primary crate of the library, the one responsible for exposing the public API of the project, and the unique one that I would like to be published in crates.io.
Reading the cargo docs I am seeing that I won't be able to publish a unique crate to the registry. All will be uploaded and published.
So, what alternatives I have to only publish my CrateA to the registry? Should I change my project's structure, and move to CrateA all the other packages and then try to publish it? Or there's some way to achieve this?
EDIT
CrateA have direct dependencies on another crates. An those others also depends on another one inside my workspace.
The way Cargo packaging works is that you are publishing your source code nearly unchanged. There is no pre-compilation step. There is no step where multiple library crates are gathered into one package. The only way to publish your CrateA is to publish all of its dependencies too.
There is interest in making a multi-crate project easier to publish, but for now, you've got to do it all explicitly.
Make sure each package in your project declares a [package] name that makes sense in public. (The name of the directory you keep it in doesn't matter.) It's common to have names like myproject-partoftheproject, where the package people actually use normally would be named myproject.
Make sure that each dependency declaration has a version number (not just a path) matching what you're going to publish. (You don't have to remove the path; that will be done for you within publication.)
Publish each package. You must do this in reverse dependency order — that is, CrateA last.
No one will mind that you've published extra packages that aren't meant for direct use — for example, lots of libraries necessarily have separate proc-macro packages. Though, if you have any crates that are really just for code organization and don't have any particular benefit, you could consider making them into modules inside fewer crates.
master Cargo.toml should be like this
[workspace]
members = [
"CrateA",
"CrateB",
...
]
And CrateA/Cargo.toml should be like this
[package]
name = "Foo"
version = "0.0.0"
edition = "2021"
authors = ["Foo <Foo#gmail.com>"]
license = "Bar"
description = "Baz"
[dependencies]
CrateB = { path = "../CrateB", version = "0.0.0" }
CrateC = "0.0.0"
A few days ago, cross-compiling to JavaScript via Emscripten has finally hit nightly. I wanted to compile a project using glium in that manner. However, there are still many Emscripten-related bugs in many crates. While maintainers usually fix those bugs quickly, they don't necessarily release those bug fixes to crates.io immediately.
In my case, glium depends on glutin. glutin had a bug which is fixed now, but only in the git repository, not on crates.io. Note: glutin is not a direct dependency of my project; only an indirect one through glium!
How do I tell Cargo to use the glutin repository as source for glutin instead of crates.io?
You can use the [replace] section in your project's Cargo.toml. You can find the documentation about that feature here in the Cargo documentation.
In your case, glium depends on glutin 0.6.1. The version 0.6.1 on crates.io still contains the bug. So just add this to your Cargo.toml:
[replace]
"glutin:0.6.1" = { git = 'https://github.com/tomaka/glutin' }
Note however,
[...] that the replaced crate must not only have the same name but also the same version.
But even in the case of a version-mismatch (the repository already contains a newer version), you could still be in luck if the crate's maintainer creates git tags for every version (many in the Rust community do). In that case you can just specify the tag:
[replace]
"glutin:0.6.1" = {
git = 'https://github.com/tomaka/glutin'
tag = 'v0.6.1'
}
Sadly, this won't work with glutin, because the maintainer did not create tags for every version. In that case you can simply find the last commit before the version was bumped and specify it with rev = 'b4a3d0...' or specify a specific branch with the branch = '...' key.
So I am trying to serialize a struct using bincode following these instructions, and I was able to get that to work.
But then I wanted to serialize a struct with an IpAddr enum. Since IpAddr doesn't implement the Encodable trait needed, I downloaded the rustc_serialize crate from git and implemented encodable for IpAddr myself. I then changed my Cargo.toml file to:
[dependencies]
# rustc-serialize = "0.3"
byteorder = "0.3"
bincode = "0.4"
[dependencies.rustc-serialize]
path = "src/rustc-serialize-master"
But now, the same code from the struct I was using doesn't compile saying that
rustc_serialize::serialize::Encodable is not implemented for my struct even though i have #[derive(RustcEncodable)] above the struct.
Even when I get rid of the code I added to the local version of rustc_serialize, I still get that error.
I think it might be due to something being screwed up with the way bincode and a local rustc_serialize interact, but I'm not sure.
Please review the Cargo documentation on overriding dependencies:
To specify overrides, create a .cargo/config file in some ancestor of your project's directory (common places to put it is in the root of your code directory or in your home directory).
Inside that file, put this:
paths = ["/path/to/project/rand"]
Going deeper, you are likely running into issue 22750 - two different versions of a crate interacting leads to unhelpful error messages. When you add rustc-serialize to your dependencies, you aren't replacing the old version, you are adding a new one.
In general, this is a good feature. If my project relies on crates A and B and they both rely on crate Z but with different versions, Rust can handle that just fine. The problem arises when they re-export items from those crates.