Status report on optional Rust in FreeBSD support
Shawn Webb has published a status report on work to provide basic support in FreeBSD for userland components written in Rust.
We introduced a new BSD makefile, located at share/mk/bsd.rust.mk, that enables building a Rust application during buildworld. As of this writing, we only support building and installing Rust applications. Supporting library crates is planned (we would like to be able to build/install library crates that expose an FFI, like for C/C++ compatibility). Normal library crates build and install just fine. Support for cdylib Rust library crates specifically is what's missing, but is desired and planned.We do NOT currently support Rust in the kernel. Kernel support requires more work that we deemed out-of-scope for this initial proof-of-concept/work-in-progress patchset. We also do NOT support building multiple programs in the same BSD Makefile (like with bsd.progs.mk), though that is also a desired feature.
LWN covered a discussion about including Rust in the FreeBSD base system in August 2024.
Posted May 22, 2025 8:14 UTC (Thu)
by rsidd (subscriber, #2582)
[Link] (16 responses)
It wasn't clear to me how the FreeBSD folks are planning to resolve this issue. PHK's suggestion was moving to a package-based base system, but I am not sure it will solve this problem -- can you mix and match cargo and FreeBSD packages? And how are Linux systems doing this? I am not a Rust or FreeBSD user. On Python on Linux (Ubuntu) this is a real problem. I also use Julia where I install everything from upstream, which is ok since it's not a part of the base install.
Posted May 22, 2025 9:22 UTC (Thu)
by tux3 (subscriber, #101245)
[Link] (4 responses)
I would recommend the same. The base system should probably bite the bullet and rebuild everything it needs for its own use, in a way that works well with the system. But we can't let the system install interact with a language package manager. I'm not aware of any example where this has worked well. You don't want your car's left and right wheels steering independently: at some point they stop being perfectly aligned and everyone suffers for it.
The default pip behavior has improved, and now most users receive warnings when they try to break the barrier.
Posted May 22, 2025 15:33 UTC (Thu)
by geofft (subscriber, #59789)
[Link] (3 responses)
Treat the versions of rustc and cargo as implementation details of building code in Rust for FreeBSD. bsd.rust.mk already sets variables with paths, but it defaults them to /usr/local/bin - put them somewhere else, like /usr/local/libexec/rust-toolchain. Then a user is free to install rustc and cargo in whatever way they want (into /usr/local/bin, if they desire, but also more likely via rustup into their home directory) and you can be confident that neither of the two use cases, end-user use of Rust as an actual tool vs. build system use of Rust in order to build end-user-facing tools, will not conflict with each other.
In the spec that improved the situation in Python (and effectively canonized the advice to use virtualenvs), we called out this general problem of toolchains having a dual purpose and two masters: https://peps.python.org/pep-0668/#motivation
Unfortunately the migration away from having an OS-provided python3 command in those OSes that currently provide it is very difficult (and some people had gotten used to influencing the behavior of OS packages by doing sudo pip install, e.g., plugins for Ansible), so if you can do it from day one, you'll be in a much better spot.
On a personal note, many years ago my way of dealing with Python was only ever using dependencies packaged in the OS and never touching pip. By the time of that document my way was using virtualenvs. Now my way is to use uv, which brings its own build of Python that is wholly separate from the OS, and for bonus points is much newer (and I've ended up as one of the maintainers of those Python builds). In some sense this is a huge change in approach, but in another sense it isn't: it's about rigorously picking one world and staying entirely in it. (And now there are increasingly active discussions about how you package C dependencies for Python apps in a way that is independent of the OS, too, which feels like the right approach for the same reasons.)
Posted May 24, 2025 19:25 UTC (Sat)
by rsidd (subscriber, #2582)
[Link] (2 responses)
For python, venvs make sense if you're the only user. If it's a multi-user system and if the admin needs to make a package available to users, it's a real pain.
Posted May 24, 2025 19:45 UTC (Sat)
by geofft (subscriber, #59789)
[Link] (1 responses)
If the goal is to make a managed environment available to users to run their own Python code, they can do the same thing and tell users where the venv is and/or make a wrapper command e.g. /usr/local/bin/python-for-xyz-purpose -> /usr/local/share/venv-for-xyz-purpose/bin/python.
I've done both of these professionally. At a past job we used dh-virtualenv (packaged in upstream Debian for ~15 years), which is a nice tool for creating a venv and installing packages (which can come from PyPI) and distributing it as a Debian package. More recently I made a command "python3-with-stuff" on the user default PATH that ran a non-OS Python install with a venv providing of useful libraries for our environment (requests and requests-kerberos, elasticsearch, a few wrappers around those for doing the right thing for internal auth, some internally-written libraries, etc.), and that approach seemed to be pretty popular.
If the thing you want to make available to users is specifically a package (i.e. a library, which users who are Python developers can use with any environment), I think you want to approach this in the form of setting up an internal package repository that users can install things from, because without
Posted May 25, 2025 18:59 UTC (Sun)
by rsidd (subscriber, #2582)
[Link]
Posted May 22, 2025 12:09 UTC (Thu)
by tialaramex (subscriber, #21167)
[Link] (9 responses)
If you'd tried to sell all this stuff as "necessary" for Rust, or Perl, or whatever, PHK would be screaming about how it's unsustainable, but in C++ they have no choice.
Posted May 23, 2025 14:30 UTC (Fri)
by nix (subscriber, #2304)
[Link] (8 responses)
(And, honestly, while the standard C++ library is getting fairly hefty, its external dependencies aren't too onerous, and that's what matters here -- and its ABI is stable, even though this incurs endless pain for the standard C++ library maintainers. And a hefty standard library is *useful*.)
Posted May 26, 2025 5:22 UTC (Mon)
by jrtc27 (subscriber, #107748)
[Link] (7 responses)
Posted May 26, 2025 18:28 UTC (Mon)
by comex (subscriber, #71521)
[Link] (1 responses)
But I suppose it still demonstrates that the added overhead isn't too high.
Posted May 28, 2025 21:59 UTC (Wed)
by jrtc27 (subscriber, #107748)
[Link]
Posted May 27, 2025 7:24 UTC (Tue)
by tialaramex (subscriber, #21167)
[Link] (4 responses)
That would have been true for the Perl too and of course it would be true for most languages so long as you decide you're "not paying" for code you didn't use.
Posted May 27, 2025 19:48 UTC (Tue)
by nix (subscriber, #2304)
[Link] (2 responses)
Posted May 28, 2025 16:14 UTC (Wed)
by tialaramex (subscriber, #21167)
[Link]
I guess we'll see how much bigger this gets before (if ever) FreeBSD decides maybe their policy makes no actual sense.
Posted May 28, 2025 21:57 UTC (Wed)
by jrtc27 (subscriber, #107748)
[Link]
Posted May 28, 2025 22:16 UTC (Wed)
by jrtc27 (subscriber, #107748)
[Link]
For reference, /usr/lib/x86_64-linux-gnu/perl-base on an Ubuntu 22.04 system is 5.5M on its own, and the parts of /usr/share/perl/5.34.0 from perl-modules-5.34 is a whole 16.3M, which doesn't even include all the pre-compiled native modules. /lib/libc++.so.1 on an amd64 FreeBSD 14.2-RELEASE-p3 system is 970K, and /usr/include/c++ on that same system is 7.3M, so in total under half the size of Ubuntu's perl-modules-5.34 alone.
Posted May 25, 2025 22:49 UTC (Sun)
by Vorpal (guest, #136011)
[Link]
Unlike Python, rust only need dependencies when compiling. This is because Rust doesn't have a stable ABI (other than the C ABI for interacting with C code), so everything must be linked statically.
Also, unlike Python, Rust uses a declarative build configuration and a lock file with hashes of all dependencies (recursively). This eliminates the risk of incompatible dependencies, especially as the Rust ecosystem is strictly semver and you can have separate semver versions of a dependency at once (so lib a and lib b depending on different incompatible versions of lib c just works, as long as you don't try to move data between the two versions of the same library, which will be a compile time error).
Rust compiler versions for developers are generally handled with the "rustup " tool, which handles multiplexing separate versions of the compiler. Unlike venv in python, this would just be a config file in your project directory, and no actual venv needs to be built. It is just about selecting the right version.
Or rather it is about selecting a sufficiently new version. Unlike Python, Rust does not break backwards compatibility (except if necessary for security or soundness fixes). So almost every project uses "most recent stable version" for building with a "minimum supported version" as well (that is generally tested by CI). The compiler is smart enough to warn if you try to use an API older than your minimum supported version, but that doesn't (yet?) apply to dependencies (so you could start depending on a version of a dependency that doesn't work on your minimum rust version).
That said, not everything is unicorns and rainbows. If you want to vendor all dependencies as separate packages (like Debian does) you are in for a painful time. Also, debian for some reason don't want to package multiple major versions of a Rust dependency side by side. For whatever reason.
Overall though, it should be much less painful than this would be for Perl or Python.
I would actually (for general purpose coding) recommend using the most recent stable version of Rust, rather than some LTS version Debian or other packages. Becuse Rust tends to be very stable, and the regressions that do happen are very niche. How is this done? The rust project has a tool called crater that builds and test every public piece of rust code, and they use this to check that they don't introduce breaking changes or regressions.
The previous discussion included a post by Poul-Henning Kamp describing the problems including perl in base previously caused, basically by making it difficult to tap into the larger Perl ecosystem or even to keep Perl up-to-date, and he worried that the same could happen for rust. In fact even though Linux doesn't have the same "base system" concept, the same is true of python on linux systems -- you have two packaging systems, Ubuntu's (say) and PIP, and they don't play nicely together. Often packages I need are not on Ubuntu's repos or are out of date, and the only sane way to run them is in a virtual environment (python's venv, or something like coda).
Mixing base rust and upstream cargo...
Packaging homochirality: don't mix the mirror worlds
The default Rust cargo behavior only uses the system when it needs C dependencies, it otherwise ignores the system Rust install.
Packaging homochirality: don't mix the mirror worlds
Packaging homochirality: don't mix the mirror worlds
If the goal is to make a command (a piece of software) that happens to be written in Python accessible to users, the admin can make a venv in a world-readable location like /opt or /usr/local/, and symlink the command in the bin/ directory from a directory on all users' PATH.
Packaging homochirality: don't mix the mirror worlds
--system-site-packages
you don't have a way to get that into users' environments (and with --system-site-packages
they get too much). Also, users might want to use another version of Python than the one you built it for, etc. You don't have to make an actual repository served over HTTP (though that might be easier for a large site); if all your users have access to the same filesystem, you can make a directory with packages and tell users to use pip --find-links
, or even configure that by default in /etc/pip.conf.
Packaging homochirality: don't mix the mirror worlds
Base
Base
Base
Base
Base
Base
Base
Base
Base
Base
Mixing base rust and upstream cargo...