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

Porteur bag 2

Back in May, I wrote about a custom porteur bag that I sewed for use on my bike. That bag served me well on two trips - a solo ride up to Brewster and back, and my semi-yearly ride on the Empire State Trail, from Poughkeepsie to Brooklyn in two days. But …

via macwright.comSeptember 27, 2025

Cloudflare bankrolls fascists

US politics has been pretty fascist lately. The state is filling up concentration camps, engaging in mass state violence against people on the basis of racialized traits, deporting them to random countries without any respect for habeas corpus, exerting st…

via Drew DeVault's blogSeptember 24, 2025

Baseline 2024 newly available - text-wrap: pretty

I was trying out text-wrap: pretty on my website. It didn’t appear to do anything. Is it a bug?

via Rob O'Leary | BlogSeptember 22, 2025

Are You Under the Influence? The Tail That Wags The Dog

It is tempting and forgivable to believe that we’re in control of our social media experiences. After all, we write what we want in our bio, select our avatars, and even come up with our own handles. We decide who we follow, what we post, and which recomme…

via Dhole MomentsSeptember 17, 2025

Package Managers are Evil

n.b. This is a written version of a dialogue from a YouTube video: 2 Language Creators vs 2 Idiots | The Standup Package managers (for programming languages) are evil1. To start, I need to make a few distinctions between concepts a lot of programmers mix u…

via Articles on gingerBillSeptember 08, 2025

Podcast: Netstack.fm, story of Rust's networking with hyper

Last week I was a guest on the Netstack podcast. We talked abit about how I got into Rust, how async Rust developed, and the story behind hyper and its surrounding ecoystem. We started (and ended) with my goal of better software: On your about page, y…

via seanmonstarSeptember 02, 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

Status update, August 2025

Hi! This month I’ve spent quite some time working on vali, a C library and code generator for the Varlink IPC protocol. It was formerly named “varlinkgen”, but the new name is shorter and more accurate (the library can be used without the code generator). …

via emersionAugust 16, 2025

PRs taking too long to be reviewed

Introduction I think there's something every developer working in an environment where PR must be reviewed has experienced: PRs taking too long to be reviewed. Every company has its own process for assigning reviews and setting the amount of minimum…

via Christian Visintin BlogAugust 14, 2025

The PoC Pollution Problem: How AI-Generated Exploits Are Poisoning Detection Engineering

As detection engineers, we live and breathe the cycle of vulnerability disclosure, proof-of-concept (PoC) analysis, and signature development. When CVE-2024-XXXXX drops on a Tuesday morning, we’re already pulling GitHub repositories, scanning blog posts, a…

via GreyNoise LabsJuly 30, 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

Contra Ptacek's Terrible Article On AI

A few days ago, I was presented with an article titled “My AI Skeptic Friends Are All Nuts” by Thomas Ptacek. I thought it was not very good, and didn't give it a second thought. To quote the formidable Baldur Bjarnason: “I don’t recommend reading it, but…

via LudicityJune 19, 2025

Generative AI will probably make blogs better

Generative AI will probably make blogs better. 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 …

via pcloadletterMay 30, 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

Simple Web Augmented Generation

A guide to building a simple web application using augmented generation.

via Ishan WritesMarch 10, 2025

Backup Yubikey Strategy

After a local security meetup where I presented about Webauthn, I had a really interesting chat with a member about a possible Yubikey management strategy. Normally when you purchase a yubikey it's recommended that you buy two of them - one primary and one…

via Firstyear's blog-a-logFebruary 28, 2025

Generated by openring-rs

favicon here hometagsblogmicrobio cvtech cvgpg keys