22 comments

[ 2.6 ms ] story [ 52.6 ms ] thread
This is big, because Rust and Debian have a philosophical disagreement how software should be updated, and so far this has left Debian users with a Rust package that is not supported by a significant portion of the Rust ecosystem.

Rust has an "evergreen" approach to updates, like Chrome, focusing on making updates so easy and backwards-compatible that there's nothing stopping users from always using the latest version. Debian prefers quite the opposite, and they'd rather keep outdated software with known bugs than to risk updating and bringing new bugs.

Having rustup-init is a compromise, allowing Debian users to have an up-to-date non-Debian Rust version, without `curl | sh`.

Rusts extremely heavy bias towards statically compiled binaries is also a notable major major major cross-roads here. The rust/ tree in Debian is big and heavy, tons of stuff. But unlike the entire rest of Debian it's entirely & purely -dev packages. Because Rust truly has zero interest in participating in conventional well managed shared library systems. I-caches & broad system updating be dammed: recompile & reduplicate the world, I guess, if you believe rust.

Very very very interested to see what happens with this fanaticism as it faces it's new challenge, WASI. I can think of no language less competent & less disposed to WASI librarification than Rust.

The shared vs static libs divide has been ongoing since libraries were a thing. Not an OS maintainer/packager, but from the outside, it really seems most of Debian's headaches are because they want to maximize compatibility owing to shared libraries.

Which is an entirely valid approach, but it seems like things would be a lot easier if programs were all statically compiled.

Rust is not the single language implementation that wants to avoid the "conventional" shared library systems. Python did so, Node did so and probably many other did or plan to do so. The conventional systems are most suitable for end-user applications, while they are annoying at the best for many other use cases.
> Python did so

Nah, python is one of the few languages with an ecosystem that can still be properly packaged, even after pep517. All libraries are scripts that are installed (and bytecode-compiled) globally.

Node is a pain in the ass due to the granularity of libraries, how frequently they update and how developers expect a specific pinned version (and vendors are flaky about backwards-compat), but nothing stopping it from having the same treatment as python.

Dynamic linking isn't really an end-user feature, but rather a system integrator's. It makes it easier to make sure everything behaves the same, and can share the same resources, which is why Apple particularly wanted an ABI for Swift[1]

[1]: https://faultlore.com/blah/swift-abi/ - How Swift Achieved Dynamic Linking Where Rust Couldn't

> Nah, python is one of the few languages with an ecosystem that can still be properly packaged, even after pep517. All libraries are scripts that are installed (and bytecode-compiled) globally.

Virtually every Python programmer now uses some sort of virtual environments, because a single Python environment cannot have multiple versions of the same package installed, and those "proper" packages are pain in the ass for that reason. If I install a `python3-pil` package in Ubuntu jammy today, it will be 9.0.1 instead of 10.2.0 and I cannot install 10.2.0 into the global environment without risking some breakage. Yes, there would be some backport packages and then PPAs, but they will again be non-cooperative in the same way and I just want to use `pip`.

What if each leaf package making use of `python3-pil` had their own virtual environment instead? That would solve most problems, but doesn't that sound like rustup? In fact, `dist-packages` was born exactly due to the stubbornness of those distro packages...

> Dynamic linking isn't really an end-user feature, but rather a system integrator's.

Any system integrator that strictly insists on dynamic linking is missing the whole point of building systems in the first place.

My point was that it does both. It didn't ditch dynamic system libraries, and it's better off for it than the rest of 'em.

The fun thing about the python ecosystem, is that even if you write an application for the latest version of Pillow, its API is stable, and you're unlikely to actually use anything introduced only in the newest version, so switching between versions is largely free (though you should definitely specify a minimum version reflecting the functionalities you actually use). In the worst case, the distro will eventually catch up with the library version your software needs, and then it can be packaged. Unlike with the node ecosystem, in python land code can easily survive years without upstream maintenance!

> Any system integrator that strictly insists on dynamic linking is missing the whole point of building systems in the first place.

You can't really say things like this without elaborating.

A couple of weeks ago I was curious how many binaries on my system did not link glibc. On my pretty standard Unbuntu it were exactly ten and they were 100% Go binaries.
I don't think rust is 'fanatic' about it, there's no cultural or organisational push of 'thou shalt static link'. It's simply not a big priority to stabilise an ABI, in large part because it's quite hard to do right, especially with the other things rust does prioritise. And the rest of the world doesn't seem to think it's a huge deal either. Distro maintainers are more or less the only people I've seen who really care about it.
This, pretty much. You can code a shared object/dynamically linked library in Rust, and it will work as a drop-in replacement for one that's coded in C. Rust also has extensive support for interfacing with C shared objects.
> I don't think rust is 'fanatic' about it, there's no cultural or organisational push of 'thou shalt static link'.

Rust users have a "fanatic" ideology about static linking is a stretch. But rust is indeed now firmly wedded to recompiling everything. This is true despite the fact that ever growing compile times are a major complaint about the language.

What Rust users are fanatic about is monomorphisation. That boils down to the compiler implementing generic types using C++ style templates instead of C++ style vtables. Monomorphisation means the compiler produces a custom version of most libraries for your application or more precisely, the types your application uses. It probably contributes it's speed. But since they are customised to your application there is no point sharing them, so shared libraries are kinda pointless.

Like C++ Rust supports both the vtable a template style, but assumption the compiler knows the Size of every object is baked in pretty deep. Parameters have the Sized constraint by default for example, and a standard trick to get around the borrow checker is to copy everything, which you can only do if you know its size. I don't see it changing now - the language will life or die by the choice.

> "But unlike the entire rest of Debian it's entirely & purely -dev packages."

I've heard that before and wondered what it means, so maybe someone can explain. My primitive understanding is that the regular package has the binary (executable or library) plus any additional files like man pages. The -dev package is the header files and the source package is the Debian patched source that can build the regular package. How is it different for Rust?

BTW Debian has a nice list of what is available from the Rust world:

https://qa.debian.org/developer.php?email=pkg-rust-maintaine...

That's because shared libraries have an extremely heavy bias towards C. They're ill-suited for languages that have generics, and use monomorphisation or rely on inlining. The standard .so format and dynamic linker don't support features that can't be dumbed down to look like C.
You are making an assumption that shared libraries have to somehow be compatible with the C ones and use the C dynamic linker: you can 100% have your own dynamic linker and have your little ecosystem work the way you want it to work for your language, and you also (to be clear) absolutely can do this without having to be Apple and controlling the "system" dynamic linker (which again is itself just a convention really) to add features as they do with Swift/Objective-C. (Hell: even just having an alternative C standard library on your system demonstrates a separate linker ecosystem as the C dynamic linker is effectively shipped as part of the C standard library.) The only thing that matters here is not the disk format or the mechanism but how it would be packaged and the tradeoffs on when time has to be put into baking them.
I understand that rustup can be convenient, but I don't get why they insist on using this tool. It should be enough to distribute the toolchain and std as a zip file.
(comment deleted)
(comment deleted)
rustup makes it easy to have multiple Rust versions installed side by side, so you can test compatibility with older versions, or try beta or nightly builds (e.g. `cargo +1.77.0 test`). I think that functionality is rustup-specific and not easily replicable with tarballs or apt.

Apart from that rustup makes it easy to add and remove optional components, libraries for cross-compilation, and update Rust itself. These things could in theory be done with apt if Debian repackaged all of these components, but they didn't. Having one way to manage Rust installation that works the same on all platforms makes it easier to teach Rust and provide install instructions for software.

I wish rust supported openbsd. Not sure if I am blaming the right entity, but rust on openbsd is lame.
I don’t think “blame” is how I’d frame it personally, but the OpenBSD folks have seemed to mostly just hate on Rust, and platforms are generally added to Rust by the folks who are interested in the platform, so that’s why it is the way it is (and that goes for every platform really).
Well, that would be beyond me. Thanks for the info!