Updating Rust
Update Rust & Cargo to use an up to date version
1395 Words, 11 Minutes
16 Jul 2024
Updating Rust
Compiling Rust
By default, OpenBSD has an old version of rustc available in the packages. It is because OpenBSD receives a tier 3 support from the Rust team, and they don't provide binaries nor installation via Rustup.
However, it's possible to use an up to date version of rustc, by compiling it.
Tested on OpenBSD 7.4.
Downloading build-rust
A member of the OpenBSD community maintains a script to compile Rust on OpenBSD. To download & use it, install git:
# pkg_add git
Then, the build-rust repository can be cloned:
$ git clone https://github.com/semarie/build-rust
$ cd build-rust
Configuring build-rust
The configuration file is stored at ~/.build_rust.conf. Example below:
# The command you use to become admin. doas, sudo, or nothing if you're
# already root
SUDO=doas
# The URL where to download the rustc source code packaged for building
# Note: there is no slash at the end
distfiles_rustc_base="https://static.rust-lang.org/dist/2023-10-21"
# The Rust compiler used to compile the other Rust version will be used
# from there. /usr/local is the path to use when using the default Rust
# installed using pkg_add(1).
# Once you built a Rust version (e.g. at /path/to/build-rust/install_dir/current),
# use the new path in rust_base_dir to use the new Rust version to compile another
# one.
rust_base_dir=/usr/local
Note: rustc can usually compile only its next version. So, it's required to compile the rustc versions one by one. To do so, the right URL, and especially the right date, has to be used in distfiles_rustc_base.
Identifying the date of the current version
It's required to have the version available in the packages to build the next version. It can be installed using pkg_add(1):
# pkg_add rust
To know the date of your current version, you can use the following command.
$ rustc --version
rustc 1.72.1 (d5c2e9c34 2023-09-13) (built from a source tarball)
The next date to use in distfiles_rustc_base will be later than this one.
Finding the right date
The following Fish script finds all dates in a month when there has been a package. Optionally, it downloads the packages and prints the Rust versions associated with them.
Examples:
- `fish find-archives.fish 03 2024` to list all URLs from March 2024 with an archive, without knowing their version.
- `fish find-archives.fish 03 2024 true` to download all the archives from March 2024, and print their version, URL and path.
- `fish find-archives.fish 03 2024 true nightly` to download all the nightly archives (instead of the beta ones) from March 2024, and print their version, URL and path.
Note: the second example could be useful to be sure to use the latest package of the targeted version. Using 1.76.beta.9 is beter than using 1.76.beta.1.
find-archives.sh
#!/bin/ksh -eu
#
# Copyright (c) 2024 Anthony Bocci <anthony.bocci+buildrust@protonmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
PATH=/bin:/usr/bin:/usr/sbin:/usr/local/bin
current_script=$(basename $0)
# Display usage information
usage() {
echo "Find beta or nightly rustc packages"
echo ""
echo "Usage: $current_script <month> [<year>] [<first-day>] [<target>]"
echo "<month> is the month to check. Example: 03 for March."
echo "<year> is the year to check. Example 2024. Default to the current year."
echo "<first-day> is the first day of the month to try. Default to 1."
echo "<target> is either beta or nightly. Default to beta."
}
if [ "$#" -lt 1 ]; then
usage
exit 0
fi
month="$(($1+0))"
year=$(date '+%Y')
first_day=1
target=beta
last_day=31
if [ "$#" -gt 1 ]; then
year="$(($2+0))"
fi
if [ "$#" -gt 2 ]; then
first_day="$(($3+0))"
fi
if [ "$#" -gt 3 ]; then
target="$4"
fi
# Ensure arguments are numbers
if [[ $month -eq 0 ]] || [[ $year -eq 0 ]] || [[ $first_day -eq 0 ]]; then
usage
exit 1
fi
tmp_dir="/tmp/build-rust-archives"
archive_name="rustc-$target-src.tar.gz"
extracted_dir="rustc-$target-src"
mkdir -p $tmp_dir
# Loop over each day of the given month / year and check if an archive exists
for day in $(seq $first_day 1 $last_day); do
day_str=$(printf "%02d" $day)
month_str=$(printf "%02d" $month)
url="https://static.rust-lang.org/dist/$year-$month_str-$day_str"
http_response=$(curl -s -I "$url/$archive_name")
status_code=$(echo $http_response | head -n 1 | cut -d' ' -f2)
# Get the remote file length. Grep behaves strangely with \r\n, so they
# are replaced with \n. One is added at the end of the input, otherwise
# grep doesn't capture the last line.
remote_file_length=$(echo "$http_response\n" | tr '\r\n' '\n' | grep -i 'content-length' | cut -d' ' -f2)
remote_file_length=$(($remote_file_length + 0))
# There is no archive at this URL, skip this day
if [ $status_code != '200' ]; then
continue
fi
out_dir="$tmp_dir/$year-$month_str-$day_str"
mkdir -p $out_dir
cd "$out_dir"
# If the archive file is there but incomplete, remove it
# It happens when the download is interrupted
if [ -f $archive_name ]; then
local_file_length=$(stat -f '%z' $archive_name)
local_file_length=$(($local_file_length + 0))
if [ $local_file_length -lt $remote_file_length ]; then
rm "$archive_name"
fi
fi
# Download the archive only if it's not already there
if [ ! -f $archive_name ]; then
echo "Downloading $url/$archive_name at $out_dir/$archive_name..."
curl -s -o "$archive_name" "$url/$archive_name"
fi
if [ ! -d $extracted_dir ]; then
echo "Extracting version file from $archive_name..."
tar -xzf "$archive_name" "$extracted_dir/version"
fi
if [ -f "$extracted_dir/version" ]; then
rustc_version=$(cat "$extracted_dir/version")
echo -e "$rustc_version, $url\n"
fi
done
As a reference:
- 2023-09-29 is version 1.73
- 2023-10-21 is version 1.74
- 2023-11-13 is version 1.75
- 2023-01-27 is version 1.76
- 2024-03-17 is version 1.77
- 2024-03-18 is version 1.78
- 2024-04-28 is version 1.79
- 2024-07-12 is version 1.80
The packages with the same versions, uploaded between these dates, can be ignored. Only the rustc version matters.
When you know the URL of the Rust version you're looking for, set the distfiles_rustc_base variable in configuration and you're ready to go.
Usage
To initialize the directory and install required packages to compile rustc, type the following command:
$ ./build.sh beta init
Once done, you can run the following commands to build rustc.
Note: the second one will probably take a long time, and the third one is optional, it's just convenient to use the new version to compile another Rust version.
$ cd /path/to/build-rust/
$ ./build.sh beta
$ mv ./install_dir/beta ./install_dir/current
If you get the following error when running ./build.sh beta, it means that your current version of Rust is lower or greater than the one needed to compile the new version.
Sun Mar 24 09:15:32 2024: error: build requires rustc 1.75. Sun Mar 24 09:15:32 2024: task not finished: see build.log for detail
Usually, it's either because you're not compiling the right Rust version (wrong URL in distfiles_rustc_base) or because you don't use the right version of the compiler (wrong path in rust_base_dir).
You might get other errors, an example is about a Rust feature stable but still allowed with an attribute as if it was unstable. Using a package of a different (usually newer) date should fix it.
If it worked properly, you can test the result with the following command:
$ /path/to/build-rust/install_dir/current/bin/rustc --version
Installing a pre-built Rust
It's recommended to build Rust yourself or to use the one installed using pkg_add(1).
However, if you don't want to build it manually, feel free to download one of the versions listed in the table. Do it at your own risks.
OpenBSD version | Rust version | File | File hash (SHA256) |
7.4 | 1.73 | v1.73.tar.gz | f68992f93c512a64df535e8b4f4c678225cc2a7f5a9799da23924a5b400ee43d |
7.4 | 1.74 | v1.74.tar.gz | 507d1f565eebe6118eeb4d1f5811ab614af73481ceea2218991fa4967e498070 |
7.4 | 1.75 | v1.75.tar.gz | bef7701c7fec9d66dabdbe1474140818ff69bedc91681d013dbbd19108b8cb4e |
7.4 | 1.76 | v1.76.tar.gz | a2404201b58e83d25e918f821dca18fe1f8e7cbfb2dfee9fa444d6d5d33fcef2 |
7.4 | 1.77 | v1.77.tar.gz | 66c4952e1e5ed91f0cb5e0714b4e379c61d3583f88968eeda32838df9d17a58b |
7.5 | 1.78 | v1.78.tar.gz | e6d1672bec6cff3f6a5612d7ed0ad70b0a97e75a20ca3cb1614ad1ca2f2d0796 |
7.5 | 1.79 | v1.79.tar.gz | a5de87b8fb402ab17726f0b6329fee5cefe345b1b67cec345c3a763811f5b41f |
7.5 | 1.80 | v1.80.tar.gz | 08d5510a5f470c50109762139fc170a324a71493cda9227e9e94e0882e6f5882 |
Using the new version as the default one
To use the new version as the default one, add the following lines in ~/.kshrc, to add the new version in the PATH.
export PATH="/path/to/build-rust/install_dir/current/bin:$PATH"
export LD_LIBRARY_PATH="/path/to/build-rust/install_dir/current/lib:$LD_LIBRARY_PATH"
OR
If you're using Fish, type the following commands (only once, the changes will persist):
set -Ux LD_LIBRARY_PATH /path/to/build-rust/install_dir/current/lib $LD_LIBRARY_PATH
set -U fish_user_paths /path/to/build-rust/install_dir/current/bin $fish_user_paths