favicon here hometagsblogmicrobio cvtech cvgpg keys

Exploring Efficient Ways To Package Rust Software in openSUSE

#packaging #rust #opensuse

Soc Virnyl Estela | 2024-08-22 | updated: 2024-11-10 |reading time: ~7min

Update I am moving over some logic as another package called roast. This is to prepare this vendoring alternative called obs-service-cargo-vendor-home-registry. The project is still worked on during my free time.

I have re-investigated possible solutions for confusing packaging in Rust. Currently, we are using cargo vendor to vendor package dependencies. This comes at a cost.

  • Back and forth copying of .cargo/config.toml for possible projects that use monorepo configurations i.e. workspace and real monorepos.
    • Examples of these are: zellij, wezterm and python-tokenizers
  • We always want to ensure Cargo.lock and I doubt the solution will not avoid this since lockfiles are always essential when building software with Rust.
  • Existing .cargo/config.toml from projects will be overridden with our generated .cargo/config.toml.

The first solution I thought of is a global .cargo/config.toml for projects. This has been done with python-tokenizers in openSUSE because it is possible to use --manifest-path to specify a manifest Cargo.toml file in the specfile for cargo invocations.

Seeing this, I realised, why not just use the $CARGO_HOME since we are pointing at a global cache anyway? This blog is about tracking my future project https://github.com/uncomfyhalomacro/obs-service-cargo-vendor-home-registry of which I plan to integrate into https://github.com/Firstyear/obs-service-cargo as an alternative vendor generating utility for Open Build Service or OBS.

Storage size eaten by CARGO_HOME vs cargo vendor comparison§

NOTE cargo fetch, cargo vendor, cargo build, and cargo generate-lockfile all update the CARGO_HOME or what we call the cargo home registry or just cargo home. We use cargo fetch here because it's designed to update the registry cache instead of other commands.

WARNING Behaviours between cargo fetch and cargo generate-lockfile cargo fetch updates the registry to latest version of crates and also regenerates Cargo.lock to reflect the versions unless --locked flag is passed where it tries to respect the versions of the crates from the existing Cargo.lock despite this contradicting description in the manpage that If a Cargo.lock file is available, this command will ensure that all of the git dependencies and/or registry dependencies are downloaded and locally available. Subsequent Cargo commands will be able to run offline after a cargo fetch unless the lock file changes.

However, cargo generate-lockfile updates the registry + updates the Cargo.lock which in my opinion is just a duplication of the other cargo sub-command cargo update. Why? Both do the same behaviour. Even the part where you pass --locked will give you the same error "error: the lock file /run/host/tmp/jay-1.4.0/Cargo.lock needs to be updated but --locked".

Here are the zstd compressed tarballs for the following after running the cargo commands

wezterm

  • cargo-vendor: 1.1GB
  • cargo-fetch: 1.3GB

jay

  • cargo-vendor: 24MB
  • cargo-fetch: 76MB

zellij

  • cargo-vendor: 66MB
  • cargo-fetch: 133MB

Why does it seem like cargo-fetch duplicates the contents in the tarball? Because it really does. The registry contains the following directory structure

.
└── registry
    ├── cache
    │   └── index.crates.io-6f17d22bba15001f
    ├── index
    │   └── index.crates.io-6f17d22bba15001f
    └── src
        └── index.crates.io-6f17d22bba15001f

8 directories, 0 files

One can remove the .cargo/registry/src directory as that contains the extracted crates and then create a tar.zst file using the following commands

# Assuming $CARGO_HOME is set to $PWD/.cargo
pushd .cargo
rm -rfv registry/src
popd
tar --zstd -cvf vendor.tar.zst .cargo/

How to get cache from $CARGO_HOME§

Any of these commands will generate the cargo home registry cache

  • build
  • generate-lockfile
  • vendor
  • fetch
  • update

Some commands are duplication of the other commands i.e. update and generate-lockfile. It's just that the former prefetches the latest crate versions while the latter doesn't.

To update the registry cache, one must either go with cargo fetch or even cargo vendor to avoid building or updating (unless update is set).

All commands try to regenerate the Cargo.lock with the latest compatible MSRV. If --locked is passed, it will try to attempt to respect the versions in the Cargo.lock. However, if the version of a dependency in Cargo.lock got yanked and there is a newer version, then an operation with --locked will fail. Also, passing --locked to cargo-update is ambiguous as it will always almost fail since it tries to update the Cargo.lock.

Why not go with cargo vendor --sync§

Reason? Uncertainty of how that command respect Cargo.lock for each crate. I would rather have do

cargo fetch --locked --manifest-path=path/to/Cargo.toml

for each manifest found since one can flexibly turn --locked on and off.

Building now with $CARGO_HOME§

It's always has been possible to use $CARGO_HOME, specifically, $CARGO_HOME/registry.

There was an attempt in this repository, https://github.com/openSUSE-Rust/obs-service-cargo-vendor-home-registry.

Now, that project has been merged into https://github.com/openSUSE-Rust/obs-service-cargo.

You can see this working in https://build.opensuse.org/package/show/editors/kak-lsp. But we lied a bit here. We will explain that in the later sections.

Path dependencies in Cargo.toml needs to be revisited§

Membered crates (in workspace configurations) and local crates (both are local and in path actually) should also be taken consideration when vendoring dependencies.

For example, https://build.opensuse.org/package/show/science:machinelearning/python-tokenizers have two different dependencies that are actually related to each other.

The solution to this is to eagerly check their manifest and lockfiles. Hence, either with multiple vendor tarballs or a vendored $CARGO_HOME.

Lockfiles are always inconsistent§

See https://github.com/rust-lang/cargo/issues/7169. This is a glaring issue and not just for cargo install but almost all cargo commands such as cargo fetch. That's why in openSUSE, we try to include the lockfile as much as possible even if passing --locked. I think I would agree to this comment https://github.com/rust-lang/cargo/issues/7169#issuecomment-539226733.

Observation

  • cargo fetch --locked does not work because it tries to keep the registry cache updated
  • cargo vendor --locked works because I don't know why???

Now is the use of --sync idea thrown out the window?

For crates that don't ship with a lockfile, we will run eithercargo generate-lockfile or cargo update, former is more semantically correct to do as opposed to cargo update. But update makes sense the most because we are going to add update options on the new project anyway.

cargo-fetch vs cargo-update§

Two days ago as of writing, I filed a bug report regarding inconsistencies between cargo-fetch and cargo-vendor. Link to bug report https://github.com/rust-lang/cargo/issues/14795.

The inconsistency specifically is the way the two handle dependencies differently especially when it comes to cargo-fetch's --target flag.

I had high hopes that by default1, it gets all target architectures. But I was met with failed builds on not so commonly used architectures whereas vendored dependencies from cargo-vendor compiles. They fail because they cannot find their dependencies fetched from cargo-fetch.

I will just have to wait for a feedback regarding how cargo-fetch behaves as compared to cargo-vendor. I believe though that both should be at least similar in almost all aspects.

  1. This is still not a loss yet for me since most of the software I used in openSUSE are used by people who either use x86_64 and aarch64. I don't believe that the other architectures are used commonly so I have removed support.

Articles from blogs I follow around the net

The Only Two Markup Languages

There are only two families of proper arbitrary markup languages: TeX and SGML I would normally link to official thing as reference but it's behind the "wonderful" ISO paywall: ISO 8879:1986.. By arbitrary, I mean the grammar specifically, and how it can …

via gingerBill - ArticlesJanuary 19, 2026

Creepy Crawlers: Hunting Those Who Hunt For WordPress Plugins

We were engaging in some routine clustering on untagged or only-generically-tagged HTTP traffic when a fun pattern jumped out: thousands of requests hitting /wp-content/plugins/*/readme.txt. It doesn’t take a cybersecurity wonk to come to the conclusion th…

via GreyNoise LabsJanuary 19, 2026

Pre-agent nostalgia

Everything seems to move fast these days and apparently nostalgia is no exception. I'm not an agentic coding evangelist but I'm also a realist—coding agents are really impressive and have changed the way most of us write software. Agents can help you plan,…

via pcloadletterJanuary 18, 2026

Software Assurance & That Warm and Fuzzy Feeling

If I were to recommend you use a piece of cryptography-relevant software that I created, how would you actually know if it was any good? Trust is, first and foremost, a social problem. If I told you a furry designed a core piece of Internet infrastructure,…

via Dhole MomentsJanuary 15, 2026

Redesigning my microkernel from the ground up

As you may recall, circa 2022-2023 I was working on a microkernel written in Hare named Helios. Helios was largely inspired by and modelled after the design of seL4 and was my first major foray into modern OS development that was serious enough to get to a…

via Drew DeVault's blogJanuary 12, 2026

I transformed my LEGO Gameboy into a working Gameboy!

Since I saw the Lego Gameboy set, I wanted to make it functional since I have good knowledge of programming and little knowledge of electronics. Also I've been a big fan of Gameboys since I was a kid, so I thought it would be a fun project to combine my…

via Christian Visintin BlogJanuary 06, 2026

Gbyte leaks gigabytes of data - #FuckStalkerware pt. 8

plus an MMO boosting service, fully remote Android spying and patented ToS violations

via maia blogJanuary 06, 2026

Whiplash and the ideas of success

Some ideas about success and analysis of some of the concepts of the film Whiplash

via Ishan WritesJanuary 04, 2026

reqwest v0.13 - rustls by default

To end out the year, here comes a new major release of reqwest, the opinionated higher-level HTTP client for Rust. We don’t really need major breaking versions to keep providing value. Improvements keep coming all the time. But we did need one to make one…

via seanmonstarDecember 30, 2025

Merry Christmas, Ya Filthy Animals (2025)

It’s my last day of writing for the year, so I’m going to try keep this one quick – it was knocked out over three hours, so I hope you can forgive me if it’s a bit clumsier than my usual writing. For some strange reason, one of the few clear memories I hav…

via LudicityDecember 27, 2025

Are people migrating away from GitHub?

I noticed some people migrating away from GitHub recently. I was curious to understand the rationale. Is it a blip or is it a sign of prolonged exodus?

via Rob O'Leary | BlogDecember 22, 2025

Status update, December 2025

Hi all! This month the new KMS plane color pipeline API has finally been merged! It took multiple years and continued work and review by engineers from multiple organizations, but at last we managed to push it over the finish line. This new API exposes to …

via emersionDecember 21, 2025

Yep, Passkeys Still Have Problems

It's now late into 2025, and just over a year since I wrote my last post on Passkeys. The prevailing dialogue that I see from thought leaders is "addressing common misconceptions" around Passkeys, the implication being that "you just don't understand it co…

via Firstyear's blog-a-logDecember 17, 2025

Testing multiple versions of Python in parallel

Daniel Roy Greenfeld wrote about how to test your code for multiple versions of Python using `uv`. I follow up with a small improvement to the Makefile.

via Technically PersonalJuly 21, 2025

LLDB's TypeSystems Part 2: PDB

In my previous post, I described implementing PDB parsing as a can of worms. That might have been a bit of an understatement. PDB has been one "oh, it's gonna be twice as much work as I thought" after another. Implementing it has revealed many of the same …

via Cracking the ShellJuly 07, 2025

#Rx Writing Challenge 2025

This is a short reflection on my experience of the recent writing challenge I took part in. Over the past two weeks, I have participated in the #RxWritingChallenge 1—a daily, 30-minute writing group starting at 9 AM every morning. Surrounded by fellow doct…

via Ul-lingaApril 05, 2025

My coffee workflow

My coffee workflow by Clement Delafargue on April 1, 2025 Tagged as: coffee, espresso, flair58, v60. It is my first April cools’ and I guess I could start by talking about coffee. If you’ve seen me in person, it won’t be a surprise, I guess. This po…

via Clément Delafargue - RSS feedApril 01, 2025

Physics Simulations in Bevy

Bevy is the most popular and powerful game engine in Rust. Because of its flexibility, it can be used not only for games but also for (scientific) physics simulations. In this blog post, I will share my experience using Bevy for physics simulations from sc…

via mo8it.comJuly 19, 2024

Generated by openring-rs

favicon here hometagsblogmicrobio cvtech cvgpg keys