From ae8b7214a36c93b510514609f04bd576fcab9425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 30 Jul 2023 16:06:37 +0000 Subject: [PATCH 1/5] extract helper to find libLLVM's name --- src/bootstrap/llvm.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 2573c3ced36..aadfd34f506 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -491,19 +491,24 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult { cfg.build(); + // Helper to find the name of LLVM's shared library on darwin and linux. + let find_llvm_lib_name = |extension| { + let mut cmd = Command::new(&res.llvm_config); + let version = output(cmd.arg("--version")); + let major = version.split('.').next().unwrap(); + let lib_name = match &llvm_version_suffix { + Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.{extension}"), + None => format!("libLLVM-{major}.{extension}"), + }; + lib_name + }; + // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned // libLLVM.dylib will be built. However, llvm-config will still look // for a versioned path like libLLVM-14.dylib. Manually create a symbolic // link to make llvm-config happy. if builder.llvm_link_shared() && target.contains("apple-darwin") { - let mut cmd = Command::new(&res.llvm_config); - let version = output(cmd.arg("--version")); - let major = version.split('.').next().unwrap(); - let lib_name = match llvm_version_suffix { - Some(s) => format!("libLLVM-{major}{s}.dylib"), - None => format!("libLLVM-{major}.dylib"), - }; - + let lib_name = find_llvm_lib_name("dylib"); let lib_llvm = out_dir.join("build").join("lib").join(lib_name); if !lib_llvm.exists() { t!(builder.symlink_file("libLLVM.dylib", &lib_llvm)); From 62d084517ffd815fe0e37149967d15ee57f4c8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 30 Jul 2023 16:11:10 +0000 Subject: [PATCH 2/5] strip debuginfo from LLVM's .so when applicable, on x64 linux --- src/bootstrap/llvm.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index aadfd34f506..1cab3cbf092 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -515,6 +515,32 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult { } } + // When building LLVM as a shared library on linux, it can contain unexpected debuginfo: + // some can come from the C++ standard library. Unless we're explicitly requesting LLVM to + // be built with debuginfo, strip it away after the fact, to make dist artifacts smaller. + // FIXME: to make things simpler for now, limit this to the host and target where we know + // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not + // cross-compiling. Expand this to other appropriate targets in the future. + if builder.llvm_link_shared() + && builder.config.llvm_optimize + && !builder.config.llvm_release_debuginfo + && target == "x86_64-unknown-linux-gnu" + && target == builder.config.build + { + // Find the name of the LLVM shared library that we just built. + let lib_name = find_llvm_lib_name("so"); + + // If the shared library exists in LLVM's `/build/lib/` or `/lib/` folders, strip its + // debuginfo. Note: `output` will propagate any errors here. + let strip_if_possible = |path: PathBuf| { + if path.exists() { + output(Command::new("strip").arg("--strip-debug").arg(path)); + } + }; + strip_if_possible(out_dir.join("lib").join(&lib_name)); + strip_if_possible(out_dir.join("build").join("lib").join(&lib_name)); + } + t!(stamp.write()); res From 67263d022dfb2c5c4cc885ed1574d16a33dd0a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 31 Jul 2023 13:20:34 +0000 Subject: [PATCH 3/5] allow `DebuginfoLevel` to be compared --- src/bootstrap/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index f3078444563..15c95dc0c60 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -50,7 +50,7 @@ pub enum DryRun { UserSelected, } -#[derive(Copy, Clone, Default)] +#[derive(Copy, Clone, Default, PartialEq, Eq)] pub enum DebuginfoLevel { #[default] None, From 4d3d96a194a50ad58764f833939726b5163df67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 31 Jul 2023 13:21:21 +0000 Subject: [PATCH 4/5] strip debuginfo from librustc_driver.so when applicable, on x64 linux --- src/bootstrap/compile.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 841288c5118..c7c1f3be2e9 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -23,7 +23,7 @@ use crate::builder::Cargo; use crate::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; use crate::cache::{Interned, INTERNER}; -use crate::config::{LlvmLibunwind, RustcLto, TargetSelection}; +use crate::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; use crate::dist; use crate::llvm; use crate::tool::SourceType; @@ -883,16 +883,39 @@ fn run(self, builder: &Builder<'_>) { compiler.host, target, ); + let stamp = librustc_stamp(builder, compiler, target); run_cargo( builder, cargo, vec![], - &librustc_stamp(builder, compiler, target), + &stamp, vec![], false, true, // Only ship rustc_driver.so and .rmeta files, not all intermediate .rlib files. ); + // When building `librustc_driver.so` (like `libLLVM.so`) on linux, it can contain + // unexpected debuginfo from dependencies, for example from the C++ standard library used in + // our LLVM wrapper. Unless we're explicitly requesting `librustc_driver` to be built with + // debuginfo (via the debuginfo level of the executables using it): strip this debuginfo + // away after the fact. This is to make the distributed artifacts smaller, and therefore we + // only do this at stage >= 1. + // FIXME: to make things simpler for now, limit this to the host and target where we know + // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not + // cross-compiling. Expand this to other appropriate targets in the future. + if compiler.stage != 0 + && builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None + && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None + && target == "x86_64-unknown-linux-gnu" + && target == builder.config.build + { + let target_root_dir = stamp.parent().unwrap(); + let rustc_driver = target_root_dir.join("librustc_driver.so"); + if rustc_driver.exists() { + output(Command::new("strip").arg("--strip-debug").arg(rustc_driver)); + } + } + builder.ensure(RustcLink::from_rustc( self, builder.compiler(compiler.stage, builder.config.build), From c98c51236da467f877070df7c80dcb603249ce47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 3 Aug 2023 14:38:10 +0000 Subject: [PATCH 5/5] strip librustc_driver.so even at stage 1 --- src/bootstrap/compile.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c7c1f3be2e9..34f19803de0 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -898,13 +898,11 @@ fn run(self, builder: &Builder<'_>) { // unexpected debuginfo from dependencies, for example from the C++ standard library used in // our LLVM wrapper. Unless we're explicitly requesting `librustc_driver` to be built with // debuginfo (via the debuginfo level of the executables using it): strip this debuginfo - // away after the fact. This is to make the distributed artifacts smaller, and therefore we - // only do this at stage >= 1. + // away after the fact. // FIXME: to make things simpler for now, limit this to the host and target where we know // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not // cross-compiling. Expand this to other appropriate targets in the future. - if compiler.stage != 0 - && builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None + if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None && target == "x86_64-unknown-linux-gnu" && target == builder.config.build