Skip to content

Commit 0f9ed18

Browse files
committed
xtask: Add musl-sysroot-url subcommand
Add a submcommand that prints the full URL of a musl sysroot tarball from Gentoo[0][1] for the given architecture. These tarballs are convenient to use for building bpf-linker for the `*-unknown-linux-musl` targets in GitHub actions. They contain static libstdc++ that's linked to musl. We need to link libstdc++ becuase libLLVM provided by Rust CI are linked dynamically to it. Producing a static binary requires a static libstdc++ to provide missing symbols. Building bpf-linker for `*-unknown-linux-musl` targets using Ubuntu's libstdc++ does not work because it's linked dynamically to glibc, causing linking errors like: ``` (.text._ZNSt6locale13_S_initializeEv+0x0): undefined reference to `__libc_single_threaded' ``` Using Gentoo's tarball and referencing it in `CXXSTDLIB` variable solves the problem. After unpacking the tarball to `sysroot/`, one can build a static binary using the following command on any distro: ``` RUSTFLAGS="-C target-feature=+crt-static" \ CXXSTDLIB_PATH="$(dirname $(find sysroot/ -name libstdc++.a))" \ cargo +nightly test \ --features llvm-21,llvm-link-static --no-default-features \ --target x86_64-unknown-linux-musl ``` Why Gentoo? It's more convenient than the considered alternatives: - Alpine Linux minirootfs[2] does not contain libstdc++. Neither does Void Linux rootfs[3]. One would need to chroot into it the sysroot and install it, which requires more work. - musl.cc[4] did not provide any update update since 2021. - Chimera Linux[5] uses LLVM libc++. [0] https://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-musl/ [1] https://distfiles.gentoo.org/releases/arm64/autobuilds/current-stage3-arm64-musl/ [2] https://www.alpinelinux.org/downloads/ [3] https://voidlinux.org/download/#download-installable-base-live-images-and-rootfs-tarballs [4] https://musl.cc/ [5] https://chimera-linux.org/
1 parent 7862791 commit 0f9ed18

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ object = { version = "0.37", default-features = false, features = [
5252

5353
[dev-dependencies]
5454
compiletest_rs = { version = "0.11.0" }
55-
regex = { version = "1.11.1", default-features = false }
55+
regex = { workspace = true }
5656
rustc-build-sysroot = { workspace = true }
5757
which = { version = "8.0.0", default-features = false, features = ["real-sys", "regex"] }
5858

@@ -101,6 +101,7 @@ edition = "2024"
101101
anyhow = { version = "1.0.100", default-features = false }
102102
clap = { version = "4.5.53", features = ["derive", "env"] }
103103
# dev deps
104+
regex = { version = "1.11.1", default-features = false }
104105
reqwest = { version = "0.12.24", default-features = false }
105106
rustc-build-sysroot = { version = "0.5.11", default-features = false }
106107
serde = { version = "1.0.228", default-features = false }

xtask/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition.workspace = true
66
[dependencies]
77
anyhow = { workspace = true }
88
clap = { workspace = true }
9+
regex = { workspace = true }
910
reqwest = { workspace = true, features = ["blocking", "json", "rustls-tls"] }
1011
rustc-build-sysroot = { workspace = true }
1112
serde = { workspace = true, features = ["derive"] }

xtask/src/main.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ enum XtaskSubcommand {
7070
BuildStd(BuildStd),
7171
/// Manages and builds LLVM.
7272
BuildLlvm(BuildLlvm),
73+
/// Finds the full URL of a musl-based sysroot that contains necessary
74+
/// system libraries for static linking.
75+
MuslSysrootUrl,
7376
/// Finds the commit in github.com/rust-lang/rust that can be used for
7477
/// downloading LLVM for the current Rust toolchain.
7578
RustcLlvmCommit(RustcLlvmCommitOptions),
@@ -202,6 +205,53 @@ fn build_llvm(options: BuildLlvm) -> Result<()> {
202205
Ok(())
203206
}
204207

208+
fn musl_sysroot_url() -> Result<()> {
209+
let arch = if cfg!(target_arch = "aarch64") {
210+
"arm64"
211+
} else if cfg!(target_arch = "x86_64") {
212+
"amd64"
213+
} else {
214+
anyhow::bail!("unsupported architecture: {}", env::consts::ARCH);
215+
};
216+
let base_url = format!(
217+
"https://distfiles.gentoo.org/releases/{arch}/autobuilds/current-stage3-{arch}-musl"
218+
);
219+
let latest_file = format!("latest-stage3-{arch}-musl.txt");
220+
221+
// Parse the the `latest-*.txt` file that contains the full tarball name.
222+
let latest_url = format!("{base_url}/{latest_file}");
223+
let content = reqwest::blocking::get(&latest_url)
224+
.with_context(|| format!("failed to fetch latest version info from {latest_url}"))?
225+
.text()
226+
.with_context(|| format!("failed to read response text from {latest_url}"))?;
227+
let re = regex::Regex::new(r"^(stage3-[a-z0-9]+-musl-[^.]+\.tar\.xz) +[0-9]+$")
228+
.expect("could not compile the regular expression");
229+
let tarballs: Vec<_> = content
230+
.lines()
231+
.filter_map(|line| {
232+
re.captures(line).map(|cap| {
233+
let (_, [tarball]) = cap.extract();
234+
tarball
235+
})
236+
})
237+
.collect();
238+
let tarball = match tarballs.as_slice() {
239+
[] => {
240+
anyhow::bail!("could not find stage3 tarball filename in {latest_url}: {content}");
241+
}
242+
[tarball] => tarball,
243+
tarballs => {
244+
anyhow::bail!(
245+
"found multiple stage3 tarball filenames in {latest_url}: {tarballs:?}: {content}"
246+
);
247+
}
248+
};
249+
250+
println!("{base_url}/{tarball}");
251+
252+
Ok(())
253+
}
254+
205255
#[derive(Deserialize)]
206256
struct SearchIssuesResponse {
207257
items: Vec<IssueItem>,
@@ -329,6 +379,7 @@ fn main() -> Result<()> {
329379
match subcommand {
330380
XtaskSubcommand::BuildStd(options) => build_std(options),
331381
XtaskSubcommand::BuildLlvm(options) => build_llvm(options),
382+
XtaskSubcommand::MuslSysrootUrl => musl_sysroot_url(),
332383
XtaskSubcommand::RustcLlvmCommit(options) => rustc_llvm_commit(options),
333384
}
334385
}

0 commit comments

Comments
 (0)