Publishing crates from the same workspace


#1

Hello I have the following application structure

root
   \__ foo
   \__ foo_derive

foo_derive is using procedural macro (proc-macro = true) and its Cargo.toml has dev-dependencies to foo (to test whether the generated macros works)

foo_derive/Cargo.toml

[package]
name = "foo_derive"
version = "0.2.0"
authors = ["Boris <bgbahoue@gmail.com>"]

[lib]
name = "foo_derive"
proc-macro = true

[dev-dependencies]
foo = { path = "../foo", version = "0.2.0" }

The main foo package also has a dev-dependency to foo_derive to generate more easily the test code

foo/Cargo.toml

[package]
name = "foo"
version = "0.2.0"
authors = ["Boris <bgbahoue@gmail.com>"]

[dev-dependencies]
foo_derive = { path = "../foo_derive", version = "0.2.0" }

It all works fine until I try to package/publish any of these crates where I get the following error

error: failed to verify package tarball

Caused by:
  no matching version `^0.2` found for package `foo_derive` (required by `foo`)
location searched: registry https://github.com/rust-lang/crates.io-index
versions found: 0.1.1, 0.1.0

Previous versions exists because previously I published the 0.1.0 version commenting out one of the dev-dependency, publish both crates, uncommented the dev-dependency and re-published the crates. Lot of manual changes and unneeded versioning; now that I have to push the next version, I’m wondering what is the best way to do that properly

Thanks in advance for your help


#2

foo_derive is not depend of foo
Just remove that:

[dev-dependencies]
foo = { path = “…/foo”, version = “0.2.0” }


#3

@Gedweb Thanks for your reply. I tried to do that already but then my foo_derive tests don’t compile.

Indeed, as part of the code generated by the #[derive()] procedural macro I need to use a few objects from foo crate and have to call extern-crate foo
If I remove the dev-dependency my tests fail to compile because the crate can’t be found (rightfully so)

In the meantime I discovered the ‘–no-verify’ option for cargo package or cargo publish but I’m not sure it’s the way to do it properly


#4

If I remember correctly --no-verify only tells your cargo to not verify before pushing to the server, crates.io then also does the same check server-side and will send back an error because of the missing dependency.

I don’t know any easy workaround I’m completely happy with for this issue. One way to do it would be to add an unpublished foo_derive_test crate to your workspace that just contains the tests and depends on both crates via path links.

There’s an existing issue on crates.io to allow this, it has the exact solution I was thinking of, which is allowing batch publishing of a workspace (I would love this even for non-circular dependencies, it’s annoying having to list the correct order in which to publish, and not publish ones that haven’t changed).


#5

In my case it worked. I was able to package & publish my foo crate (https://crates.io/crates/he_di) then published my foo_derive crate (https://crates.io/crates/he_di_derive) without needing to use --no-verify since v0.2.0 was on crates.io.

I agree adding an unpublished test crate would indeed allow to remove the dev-dependency and break the dependency circle, but it beats the logic of packaging tests & source code together no?

Interestingly, it seems that Rocket found a way around this as per crates.io, rocket v0.2.8 doesn’t list a dev-dependency for rocket_codegen (https://crates.io/crates/rocket) while it’s Cargo.toml does have such a dependency (see https://github.com/SergioBenitez/Rocket/blob/v0.2.8/lib/Cargo.toml). I wonder how he did this…

But overall, yes I agree with you @Nemo157, having a smart batch publish for workspaces would be great!


#6

Manually changing it before publishing I guess. I happened to have rocket v0.2.7 in my cargo source folder (~/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.2.7) so took a look at its Cargo.toml (actually Cargo.toml.orig as cargo rewrites Cargo.toml during the upload):

→ diff <(curl -sL https://github.com/SergioBenitez/Rocket/raw/v0.2.7/lib/Cargo.toml) Cargo.toml.orig
35c35
< rocket_codegen = { version = "0.2.7", path = "../codegen" }
---
>

#7

Yes, a script actually but doing essentially that => https://github.com/SergioBenitez/Rocket/blob/master/scripts/publish.sh

Too bad almost :slight_smile: