# Performance of \`cargo package\` / \`cargo publish\` and the purpose of the verify step

**URL:** <https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135>\
**Category:** cargo\
**Created:** [January 8, 2025, 6:06pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135 "2025-01-08T18:06:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 8, 2025, 6:06pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/1 "2025-01-08T18:06:09Z")

</div>

In short, I'm looking to feedback on the following questions:

- What packages or workflows are sensitive to `cargo package` or `cargo publish` times?
- Should `cargo publish`'s verify step focus on smoke testing the packaging process or be a last-ditch quality check in case there isn't a CI?

`cargo package` and `cargo publish` run a verify step by default. When testing `cargo publish --workspace` ([cargo publish multiple packages at once · Issue #1169 · rust-lang/cargo · GitHub](https://github.com/rust-lang/cargo/issues/1169)), I noticed how slow the verify step is and realized it is running `cargo build` instead of `cargo check`. Publishing packages is an infrequent task and the performance likely doesn't make much of a difference (well, except for [aws-sdk](https://github.com/rust-lang/cargo/issues/14955)). I did go all of these years without realizing thinking more about how slow it is.

Where `cargo publish` time can make a difference is in dry-run support. Previously, workspace release tools, like `cargo-release`, had to skip the verify step in dry-run modes because there wasn't a way to overlay the newly generated packages on top of the registry to build dependent workspace members. With `cargo publish --workspace --dry-run`, that is now possible. This makes what was a fast dry-run to be very slow. Dry-run can be run part of the development cycle while tweaking the release process. The full `build` isn't relevant to the that, especially when tweaking non-publishing steps like regex-based custom version updates. Users would hand-tweak the command to get the subset of functionality that is relevant but that requires extra work on the users behalf.

Switching the verify step from `cargo build` to `cargo check` would reduce the amount of time it takes and give the same amount of coverage for "is this packaged correctly". What it loses is any post-monopolization diagnostics (including linker errors). With [Cargo Check T-lang Policy by Lokathor · Pull Request #3477 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/3477), `cargo check` is officially not guaranteed to report all errors and code that passes only `cargo check` is not subject to Rust's compatibility guarantees.

Whether the differences between `cargo check` and `cargo build` are relevant depends on factors like:

- Our general assumption of what users do before publishing (`cargo test`? run all of CI?)
- The likelihood that a step from above is missed before release
- The likelihood of post-monopolization errors being introduced in that gap
- The number of affected users if a problem does slip through (are more popular crates likely to have more rigorous processes?)

This also gets into the larger question of what the role of the verify step, whether its

- Is this packaged correctly
  - Technically, there is a risk of files missing depending on the combination of features or `--target`
  - Examples aren't built and could be missing files or dependencies. However, some dependencies might intentionally be missing as Cargo removes some to break publish dependency cycles
  - _if_ you prioritize running tests on a `.crate`, then the only way to verify all files are packaged is to run tests. However, some dependencies may also be stripped here _and_ some community members have been policing the ecosystem for test data being packaged to reduce `.crate` size, e.g. [Released versions contain test data · Issue #200 · BurntSushi/bstr · GitHub](https://github.com/BurntSushi/bstr/issues/200), somewhat related to [`cargo vendor` should offer the ability to omit the `tests/` directory · Issue #13474 · rust-lang/cargo · GitHub](https://github.com/rust-lang/cargo/issues/13474)

- Last-ditch quality check
  - Currently only builds (no clippy, miri, etc) the default build-targets using the `dev` profile with one feature set on one target-platform
  - Doesn't run tests (see earlier for problems here)

We could potentially make the verify step configurable (see also [`cargo package` could run tests in the packaged tree · Issue #14685 · rust-lang/cargo · GitHub](https://github.com/rust-lang/cargo/issues/14685)) at which point this becomes a question of defaults before and after this is configurable.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [January 8, 2025, 7:18pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/2 "2025-01-08T19:18:03Z")

</div>

Without offering opinions on the larger issue, skipping `cargo build` skips _linking,_ which is a huge amount of the time, but also often a source of issues for a certain kind of project (executables that link against system libraries probably being the main set). Whether that’s desirable is separate, but it probably shouldn’t be glommed in with “post-monomorphization errors”, even though _technically_…

(I personally would expect `cargo publish --dry-run` to do a dry-run build as well. But again, I’m not a crate maintainer, so my opinion isn’t so important here.)

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [January 8, 2025, 7:29pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/3 "2025-01-08T19:29:15Z")

</div>

One type of post-monomorphization error is a constant evaluation error. Constant evaluation errors could result from packaging mistakes (e.g. if using a macro like `include_dir!()` and processing the found files in constant evaluation).

In general, I think that `cargo publish` is something that _should not be casual_ and it isn't a big deal if it takes longer than strictly necessary.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 8, 2025, 7:31pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/4 "2025-01-08T19:31:13Z")

</div>

I've updated it to call out that it includes linker errors.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 8, 2025, 7:48pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/5 "2025-01-08T19:48:46Z")

</div>

> [@kpreid](#):
>
> In general, I think that `cargo publish` is something that _should not be casual_ and it isn't a big deal if it takes longer than strictly necessary.

Keep in mind that this isn't just `cargo publish` but

- `cargo publish --dry-run` for the use cases I called out
  - I'd also love to see this integrated into more CIs once we have the `--workspace` flag which will be slower than a regular `cargo build` because (1) it will build serially, (2) it won't reuse intermediate build artifacts (we could look at loosening that limitation)

- `cargo package` which I've worked with people who were it an integral part of their workflow

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [January 8, 2025, 10:25pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/6 "2025-01-08T22:25:34Z")

</div>

> [@epage](#):
>
> noticed how slow the verify step is and realized it is running `cargo check` instead of `cargo build`.

Did you mean this the other way around?

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 8, 2025, 10:38pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/7 "2025-01-08T22:38:00Z")

</div>

Fixed

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [January 9, 2025, 5:24pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/8 "2025-01-09T17:24:35Z")

</div>

The pre-publish check has saved me on a couple of occasions when I was too hasty to publish.

I work with sys crates a lot, so linking check is useful to me.

If you're looking for a compromise, then cargo check may be ok for crates that don't have any -sys deps, or maybe even for crates that don't have build.rs themselves (under assumption that build.rs may be compiling extra stuff and checking it links is important).

But in general I don't mind the pre-publish check. When I'm in a hurry or scripting my own test+publish, `--no-verify` is there.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [July 3, 2026, 5:25pm UTC](https://internals.rust-lang.org/t/performance-of-cargo-package-cargo-publish-and-the-purpose-of-the-verify-step/22135/9 "2026-07-03T17:25:11Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
