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

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

I hope generative AI does away with SEO

Have you ever searched for something on Google and found the first one, two, or three blog posts to be utter nonsense? That's because these blog posts have been optimized not for human consumption, but rather to entertain the search engine ranking algorith…

via pcloadletterDecember 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

ColdFusion++ Christmas Campaign: Catching a Coordinated Callback Calamity

UPDATE: Further analysis revealed the ColdFusion campaign represents a small fraction of a much larger operation. The two primary IPs (134.122.136.119, 134.122.136.96) generated over 2.5 million requests targeting 767 distinct CVEs across 47+ technology st…

via GreyNoise LabsDecember 26, 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

The Revolution Will Not Make the Hacker News Front Page

(with apologies to Gil Scott-Heron) If you get all of your important technology news from “content aggregators” like Hacker News, Lobste.rs, and most subreddits, you might be totally unaware of the important but boring infrastructure work happening largely…

via Dhole MomentsDecember 18, 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

context—Odin's Most Misunderstood Feature

Even with the documentation on the topic, many people completely misunderstand what the context system is for, and what problem it actually solves. For those not familiar with Odin, in each scope, there is an implicit value named context. This context vari…

via Articles on gingerBillDecember 15, 2025

Announcing ic-dbms 0.1.0

What if I told you that this code: use candid::CandidType; use ic_dbms_api::prelude::{Text, Uint32}; use ic_dbms_canister::prelude::{DbmsCanister, Table}; use serde::Deserialize; #[derive(Debug, Table, CandidType, Deserialize, Clone, PartialEq, Eq…

via Christian Visintin BlogDecember 13, 2025

Theme selector

Two weeks ago I added dark mode to this website. It was late one night and I was revisiting an article and my eyes were tired, so that was that. It was based solely on system dark mode settings, and I started using some more nice, modern CSS features like …

via macwright.comDecember 09, 2025

OpenAI employees… are you okay?

You might have seen an article making the rounds this week, about a young man who ended his life after ChatGPT encouraged him to do so. The chat logs are really upsetting. Someone two degrees removed from me took their life a few weeks ago. A close friend …

via Drew DeVault's blogNovember 08, 2025

Comfort of Wabi Sabi

Comfort of accepting used things

via Ishan WritesOctober 25, 2025

i'm bored, so here's a useless 0day

i either want my US$2.5k professional-grade device backdoored or not at all

via maia blogAugust 20, 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

Generated by openring-rs

favicon here hometagsblogmicrobio cvtech cvgpg keys