Merge ~blkerby/ubuntu/+source/rustc:std-vendor into ~canonical-foundations/ubuntu/+source/rustc:merge-1.91

Proposed by Brent Kerby
Status: Merged
Approved by: Max Gilmour
Approved revision: 2f166d166f989a2c5c3b2d35e28ff855918671f7
Merge reported by: Max Gilmour
Merged at revision: 2f166d166f989a2c5c3b2d35e28ff855918671f7
Proposed branch: ~blkerby/ubuntu/+source/rustc:std-vendor
Merge into: ~canonical-foundations/ubuntu/+source/rustc:merge-1.91
Diff against target: 246 lines (+135/-9)
7 files modified
debian/bootstrap.toml.in (+1/-1)
debian/changelog (+8/-0)
debian/rules (+18/-6)
debian/rust-X.Y-src.install.in (+20/-0)
debian/scripts/update-rust-src-install (+46/-0)
debian/vendor-deps (+2/-2)
debian/vendor-std-deps (+40/-0)
Reviewer Review Type Date Requested Status
Max Gilmour Approve
Review via email: mp+497988@code.launchpad.net

Description of the change

This adds support for vendoring the standard library dependencies as part of the "rust-X.Y-src" package, enabling the "build-std" unstable Cargo feature to be used in offline environments. This includes:
- A new bash script "vendor-std-deps" to vendor the standard library dependencies into a temporary directory.
- A new Python script to scan the temporary output and autogenerate a section of "rust-X.Y-src.install.in", listing each vendored crate.
- A new target "vendor-std-deps" in "debian/rules" to invoke the new bash script and Python script.
- Addition of "vendor-std-deps" as a dependent to the "vendor-tarball" target; so going forward the vendoring of standard library dependencies should be handled automatically, without the maintainer needing to do any additional steps in the rustc upgrade process.

While working on this, I had some trouble reproducing the existing vendor tarball for rustc-1.91. One possible cause of differences would be a different toolchain version being used. To prevent this in the future, a check is added to ensure that the toolchain version used to create the vendor tarball matches the version of the toolchain being built.

I also had an issue where the vendored crate versions ended up not being the same versions as the ones actually required by the "build-std" option in the end. This appears to have been caused by the "dh_auto_configure" step removing (or rather renaming) the Cargo.lock files. I'm not aware of the context of why this was done, but leaving the original Cargo.lock files intact appears to work and resolves the issue. Leaving the Cargo.lock intact also seems ideal in order to match the upstream behavior as close as possible? While troubleshooting, I also set "locked-deps" to true in the "bootstrap.toml.in", to make sure the versions in the Cargo.lock files are exactly what are used; this isn't necessarily needed but may be worth keeping as a check, since if something were to cause the versions to change it would be unexpected and we may want to see an error.

To post a comment you must log in.
Revision history for this message
Brent Kerby (blkerby) wrote (last edit ):

PPA: https://launchpad.net/~blkerby/+archive/ubuntu/rustc-1.91-resolute-b

Steps to validate that this solution will work:
> add-apt-repository -y ppa:blkerby/rustc-1.91-resolute-b
> apt update
> apt install -y rustc-1.91 cargo-1.91 rust-1.91-src
> alias cargo=cargo-1.91
> cargo new hello
> cd hello
> cargo add serde # add dummy dependency so "cargo vendor" doesn't complain
> cargo vendor --versioned-dirs
> ln -s /usr/src/rustc-1.91.1/vendor/* vendor/
> mkdir .cargo
> cat >.cargo/config.toml
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"
> RUSTC_BOOTSTRAP=1 cargo run -Z build-std --offline

Revision history for this message
Max Gilmour (maxgmr) wrote :

The changes look good. I've also verified that this new toolchain is able to build itself successfully via autopkgtests. Merging.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/bootstrap.toml.in b/debian/bootstrap.toml.in
2index 11c7214..ff8d267 100644
3--- a/debian/bootstrap.toml.in
4+++ b/debian/bootstrap.toml.in
5@@ -3,7 +3,7 @@ change-id = 131075
6 [build]
7 submodules = false
8 vendor = true
9-locked-deps = false
10+locked-deps = true
11 verbose = VERBOSITY
12 profiler = true
13
14diff --git a/debian/changelog b/debian/changelog
15index d5182fa..1694aa6 100644
16--- a/debian/changelog
17+++ b/debian/changelog
18@@ -1,3 +1,11 @@
19+rustc-1.91 (1.91.1+dfsg-0ubuntu3) resolute; urgency=medium
20+
21+ * Add standard library vendored dependencies to rust-X.Y-src package
22+ * Restrict toolchain used to make vendor tarball, for reproducibility
23+ * Use frozen Cargo.lock dependencies
24+
25+ -- Brent Kerby <brent.kerby@canonical.com> Fri, 02 Jan 2026 12:59:35 -0700
26+
27 rustc-1.91 (1.91.1+dfsg-0ubuntu2) resolute; urgency=medium
28
29 * Set Architecture Level (ALS) to z15 on s390x (LP: #2126577)
30diff --git a/debian/rules b/debian/rules
31index 71a2bcc..a1c1f47 100755
32--- a/debian/rules
33+++ b/debian/rules
34@@ -30,6 +30,8 @@ VENDOR_TARBALL := $(PKG_NAME_CHANGELOG)_$(DEB_VERSION_UPSTREAM).orig-vendor.tar.
35 # This is a temporary directory used to store the filtered vendored dependencies.
36 # It is packed into the vendor tarball.
37 FILTERED_DEPS := $(CURDIR)/../vendor
38+# Another temporary directory used to store the standard library dependencies.
39+STD_DEPS := $(CURDIR)/../std-vendor
40
41 include /usr/share/dpkg/buildflags.mk
42 # needed for cross-compilation to avoid passing host CFLAGS to the BUILD
43@@ -106,19 +108,32 @@ ifneq (,$(RUST_TEST_SELFBUILD))
44 RUST_BOOTSTRAP_DIR = /usr/lib/rust-$(RUST_VERSION)
45 endif
46
47+BOOTSTRAP_VERSION := $(shell $(RUST_BOOTSTRAP_DIR)/bin/rustc --version | awk '{print $$2}')
48+
49 .PHONY: vendor-tarball-quick-check
50 vendor-tarball-quick-check:
51 if [ -e $(CURDIR)/../$(VENDOR_TARBALL) ]; then \
52 echo "../$(VENDOR_TARBALL) already exists" >&2; \
53 exit 1; \
54 fi
55+ifneq ($(BOOTSTRAP_VERSION),$(DEFINED_SRC_VERSION))
56+ $(error The bootstrap rustc version does not match the upstream version: \
57+ Found "$(BOOTSTRAP_VERSION)", expected "$(DEFINED_SRC_VERSION)". \
58+ Please set RUST_BOOTSTRAP_DIR to point to a toolchain matching the upstream version.)
59+endif
60
61 .PHONY: vendor-deps
62 vendor-deps:
63 debian/vendor-deps $(FILTERED_DEPS)
64
65+.PHONY: vendor-std-deps
66+vendor-std-deps:
67+ debian/vendor-std-deps $(STD_DEPS)
68+ python3 debian/scripts/update-rust-src-install $(STD_DEPS)
69+ rm -rf $(STD_DEPS)
70+
71 .PHONY: vendor-tarball
72-vendor-tarball: vendor-tarball-quick-check vendor-deps
73+vendor-tarball: vendor-tarball-quick-check vendor-std-deps vendor-deps
74 tar --sort=name --mtime=@0 --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -caf $(CURDIR)/../$(VENDOR_TARBALL) $(FILTERED_DEPS)
75 mk-origtargz --rename -c vendor $(CURDIR)/../$(VENDOR_TARBALL)
76 rm -rf $(FILTERED_DEPS)
77@@ -339,11 +354,6 @@ debian/dh_auto_configure.stamp: debian/bootstrap.toml check-no-old-llvm
78 # v="$(DEB_VERSION)"; test "$$v" = "$${v%~exp*}" -o "$(DEB_DISTRIBUTION)" = "experimental" -o "$(DEB_DISTRIBUTION)" = "UNRELEASED"
79 $(PRECONFIGURE_CHECK)
80 if [ -d stage0 ]; then mkdir -p build && ln -sfT ../stage0 build/cache; fi
81- # don't care about lock changes
82- # keep in sync with d/vendor-deps
83- for ws in . src/bootstrap library src/tools/clippy/clippy_test_deps src/tools/rust-analyzer src/tools/cargo src/tools/rustbook; do \
84- if [ -f "$$ws/Cargo.lock" ]; then mv "$$ws/Cargo.lock" "$$ws/Cargo.lock.orig"; fi \
85- done
86 # We patched some crates so have to rm the checksums
87 find vendor -name .cargo-checksum.json -execdir "$(CURDIR)/debian/prune-checksums" "{}" +
88 # Link against system liblzma, see https://github.com/alexcrichton/xz2-rs/issues/16
89@@ -575,6 +585,8 @@ endif
90
91
92 override_dh_install-indep:
93+ # Touch vendored crates to avoid upload failing with "time stamp too far in the past"
94+ find vendor -exec touch {} +
95 dh_install
96 $(RM) -rf $(SRC_CLEAN:%=debian/rust-$(RUST_VERSION)-src/src/usr/src/rustc-$(RUST_LONG_VERSION)/%)
97 # Get rid of lintian warnings
98diff --git a/debian/rust-X.Y-src.install.in b/debian/rust-X.Y-src.install.in
99index 0dc17f4..1740a7f 100644
100--- a/debian/rust-X.Y-src.install.in
101+++ b/debian/rust-X.Y-src.install.in
102@@ -13,3 +13,23 @@ Cargo.toml usr/src/rustc-${env:RUST_LONG_VERSION}
103 src usr/src/rustc-${env:RUST_LONG_VERSION}
104 library usr/src/rustc-${env:RUST_LONG_VERSION}
105 compiler usr/src/rustc-${env:RUST_LONG_VERSION}
106+# Do not edit: AUTOGENERATED
107+vendor/libc-0.2.175 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
108+vendor/object-0.37.3 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
109+vendor/memchr-2.7.5 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
110+vendor/hashbrown-0.15.5 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
111+vendor/rand_core-0.9.3 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
112+vendor/cc-1.2.0 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
113+vendor/rand-0.9.2 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
114+vendor/cfg-if-1.0.1 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
115+vendor/miniz_oxide-0.8.9 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
116+vendor/adler2-2.0.1 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
117+vendor/unwinding-0.2.8 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
118+vendor/getopts-0.2.24 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
119+vendor/rustc-literal-escaper-0.0.5 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
120+vendor/rustc-demangle-0.1.26 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
121+vendor/addr2line-0.25.0 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
122+vendor/rand_xorshift-0.4.0 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
123+vendor/shlex-1.3.0 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
124+vendor/gimli-0.32.0 usr/src/rustc-${env:RUST_LONG_VERSION}/vendor
125+# AUTOGENERATED END
126diff --git a/debian/scripts/update-rust-src-install b/debian/scripts/update-rust-src-install
127new file mode 100644
128index 0000000..92f997b
129--- /dev/null
130+++ b/debian/scripts/update-rust-src-install
131@@ -0,0 +1,46 @@
132+#!/usr/bin/python3
133+# Update the autogenerated part of rust-X.Y-src.install.in, by including the vendored
134+# dependencies of the standard library.
135+
136+import argparse
137+import os
138+
139+parser = argparse.ArgumentParser()
140+parser.add_argument("vendor", help="path to vendor directory of standard library dependencies")
141+args = parser.parse_args()
142+
143+install_path = "debian/rust-X.Y-src.install.in"
144+install_list = []
145+
146+for x in os.listdir(args.vendor):
147+ install_list.append(f"vendor/{x}" + " usr/src/rustc-${env:RUST_LONG_VERSION}" + f"/vendor")
148+
149+# Read the existing file
150+with open(install_path, "r") as f:
151+ lines = f.readlines()
152+
153+start_marker = "# Do not edit: AUTOGENERATED"
154+end_marker = "# AUTOGENERATED END"
155+
156+start_idx = None
157+end_idx = None
158+
159+for i, line in enumerate(lines):
160+ if start_marker in line:
161+ start_idx = i
162+ if end_marker in line:
163+ end_idx = i
164+ break
165+
166+if start_idx is not None and end_idx is not None and start_idx < end_idx:
167+ new_lines = (
168+ lines[:start_idx + 1]
169+ + [line + "\n" for line in install_list]
170+ + lines[end_idx:]
171+ )
172+ with open(install_path, "w") as f:
173+ f.writelines(new_lines)
174+else:
175+ raise RuntimeError(f"Could not find AUTOGENERATED markers in {install_path}")
176+
177+# print(args.vendor)
178\ No newline at end of file
179diff --git a/debian/vendor-deps b/debian/vendor-deps
180index 1f91338..89118a0 100755
181--- a/debian/vendor-deps
182+++ b/debian/vendor-deps
183@@ -7,7 +7,7 @@
184 # It is typically invoked by d/rules vendor-deps.
185 #
186 # Manual invocation example for 1.89:
187-# RUST_BOOTSTRAP_DIR=~/.rustup/toolchains/1.89.0-x86_64-unknown-linux-gnu/bin/rustc debian/vendor-deps ./filtered-vendor
188+# RUST_BOOTSTRAP_DIR=~/.rustup/toolchains/1.89.0-x86_64-unknown-linux-gnu/ debian/vendor-deps ./filtered-vendor
189
190 set -e
191
192@@ -127,7 +127,7 @@ for forced_std_dep in "${forced_std_deps[@]}"; do
193 std_dep_make_non_optional "$forced_std_dep"
194 done
195
196-cargo +nightly vendor-filterer "$vendored_deps" \
197+RUSTC_BOOTSTRAP=1 ${RUST_BOOTSTRAP_DIR}/bin/cargo vendor-filterer "$vendored_deps" \
198 --versioned-dirs \
199 "${vendor_filterer_args[@]}"
200
201diff --git a/debian/vendor-std-deps b/debian/vendor-std-deps
202new file mode 100755
203index 0000000..0375443
204--- /dev/null
205+++ b/debian/vendor-std-deps
206@@ -0,0 +1,40 @@
207+#!/bin/bash
208+# Vendor the standard library dependencies. Currently this is needed
209+# in order to support use of the unstable "-Z build-std" rustc feature in offline
210+# environments. Once the feature is stabilized it should become no longer necessary
211+# (pending resolution of https://github.com/rust-lang/wg-cargo-std-aware/issues/23
212+# and related issues).
213+
214+std_vendored_deps="$1"
215+if [ -d "$std_vendored_deps" ]; then
216+ echo "directory $std_vendored_deps already exists" >&2
217+ exit 1
218+fi
219+
220+# List of supported platforms; edit as needed
221+supported_platforms=(
222+ "x86_64-unknown-linux-gnu"
223+ "aarch64-unknown-linux-gnu"
224+ "i686-unknown-linux-gnu"
225+ "armv7-unknown-linux-gnueabihf"
226+ "powerpc64le-unknown-linux-gnu"
227+ "powerpc-unknown-linux-gnu"
228+ "s390x-unknown-linux-gnu"
229+ "riscv64a23-unknown-linux-gnu"
230+)
231+
232+vendor_filterer_args=()
233+for platform in "${supported_platforms[@]}"; do
234+ vendor_filterer_args+=("--platform=$platform")
235+done
236+
237+quilt push -a
238+
239+echo "Vendoring standard library dependencies to ${std_vendored_deps}..."
240+RUSTC_BOOTSTRAP=1 ${RUST_BOOTSTRAP_DIR}/bin/cargo vendor-filterer \
241+ --manifest-path library/Cargo.toml \
242+ --versioned-dirs \
243+ "${vendor_filterer_args[@]}" \
244+ ${std_vendored_deps}
245+
246+quilt pop -a

Subscribers

People subscribed via source and target branches