authorbors <bors@rust-lang.org> 2026-01-14 09:57:06 UTC
committerbors <bors@rust-lang.org> 2026-01-14 09:57:06 UTC
log2fd6efc32704647e64d3d646d21c4c68eae100e4
tree64c8d234e9eaad96a2a9d26b39767e4d9230470e
parent4931e09e3ac3182d2a00f38cccfdf68e8e385e1c
parentb0aa77a0267040b6155d75487e8ecc7be7790bf9

Auto merge of #150541 - Kobzol:dist-gcc-component, r=jieyouxu

Add a dist component for libgccjit Companion to https://github.com/rust-lang/rust/pull/150538. try-job: dist-x86_64-linux

5 files changed, 117 insertions(+), 13 deletions(-)

src/bootstrap/src/core/build_steps/compile.rs+19-10
......@@ -1630,26 +1630,35 @@ impl GccDylibSet {
16301630 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
16311631 compiler.host
16321632 );
1633 let libgccjit = libgccjit.libgccjit();
1634 let target_filename = libgccjit.file_name().unwrap().to_str().unwrap();
1633 let libgccjit_path = libgccjit.libgccjit();
16351634
16361635 // If we build libgccjit ourselves, then `libgccjit` can actually be a symlink.
16371636 // In that case, we have to resolve it first, otherwise we'd create a symlink to a
16381637 // symlink, which wouldn't work.
1639 let actual_libgccjit_path = t!(
1640 libgccjit.canonicalize(),
1641 format!("Cannot find libgccjit at {}", libgccjit.display())
1638 let libgccjit_path = t!(
1639 libgccjit_path.canonicalize(),
1640 format!("Cannot find libgccjit at {}", libgccjit_path.display())
16421641 );
16431642
1644 // <cg-sysroot>/lib/<target>/libgccjit.so
1645 let dest_dir = cg_sysroot.join("lib").join(target_pair.target());
1646 t!(fs::create_dir_all(&dest_dir));
1647 let dst = dest_dir.join(target_filename);
1648 builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
1643 let dst = cg_sysroot.join(libgccjit_path_relative_to_cg_dir(target_pair, libgccjit));
1644 t!(std::fs::create_dir_all(dst.parent().unwrap()));
1645 builder.copy_link(&libgccjit_path, &dst, FileType::NativeLibrary);
16491646 }
16501647 }
16511648}
16521649
1650/// Returns a path where libgccjit.so should be stored, **relative** to the
1651/// **codegen backend directory**.
1652pub fn libgccjit_path_relative_to_cg_dir(
1653 target_pair: &GccTargetPair,
1654 libgccjit: &GccOutput,
1655) -> PathBuf {
1656 let target_filename = libgccjit.libgccjit().file_name().unwrap().to_str().unwrap();
1657
1658 // <cg-dir>/lib/<target>/libgccjit.so
1659 Path::new("lib").join(target_pair.target()).join(target_filename)
1660}
1661
16531662/// Output of the `compile::GccCodegenBackend` step.
16541663///
16551664/// It contains a build stamp with the path to the built cg_gcc dylib.
src/bootstrap/src/core/build_steps/dist.rs+83-1
......@@ -19,7 +19,9 @@ use object::read::archive::ArchiveFile;
1919#[cfg(feature = "tracing")]
2020use tracing::instrument;
2121
22use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
22use crate::core::build_steps::compile::{
23 get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name,
24};
2325use crate::core::build_steps::doc::DocumentationFormat;
2426use crate::core::build_steps::gcc::GccTargetPair;
2527use crate::core::build_steps::tool::{
......@@ -2992,3 +2994,83 @@ impl Step for GccDev {
29922994 Some(StepMetadata::dist("gcc-dev", self.target))
29932995 }
29942996}
2997
2998/// Tarball containing a libgccjit dylib,
2999/// needed as a dependency for the GCC codegen backend (similarly to the LLVM
3000/// backend needing a prebuilt libLLVM).
3001///
3002/// This component is used for distribution through rustup.
3003#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3004pub struct Gcc {
3005 host: TargetSelection,
3006 target: TargetSelection,
3007}
3008
3009impl Step for Gcc {
3010 type Output = Option<GeneratedTarball>;
3011
3012 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3013 run.alias("gcc")
3014 }
3015
3016 fn make_run(run: RunConfig<'_>) {
3017 // GCC is always built for a target pair, (host, target).
3018 // We do not yet support cross-compilation here, so the host target is always inferred to
3019 // be the bootstrap host target.
3020 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3021 }
3022
3023 fn run(self, builder: &Builder<'_>) -> Self::Output {
3024 // This prevents gcc from being built for "dist"
3025 // or "install" on the stable/beta channels. It is not yet stable and
3026 // should not be included.
3027 if !builder.build.unstable_features() {
3028 return None;
3029 }
3030
3031 let host = self.host;
3032 let target = self.target;
3033 if host != "x86_64-unknown-linux-gnu" {
3034 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3035 return None;
3036 }
3037
3038 // We need the GCC sources to build GCC and also to add its license and README
3039 // files to the tarball
3040 builder.require_submodule(
3041 "src/gcc",
3042 Some("The src/gcc submodule is required for disting libgccjit"),
3043 );
3044
3045 let target_pair = GccTargetPair::for_target_pair(host, target);
3046 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3047
3048 // We have to include the target name in the component name, so that rustup can somehow
3049 // distinguish that there are multiple gcc components on a given host target.
3050 // So the tarball includes the target name.
3051 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3052 tarball.set_overlay(OverlayKind::Gcc);
3053 tarball.is_preview(true);
3054 tarball.add_legal_and_readme_to("share/doc/gcc");
3055
3056 // The path where to put libgccjit is determined by GccDylibSet.
3057 // However, it requires a Compiler to figure out the path to the codegen backend sysroot.
3058 // We don't really have any compiler here, because we just build libgccjit.
3059 // So we duplicate the logic for determining the CG sysroot here.
3060 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3061
3062 // This returns the path to the actual file, but here we need its parent
3063 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3064 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3065
3066 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3067 Some(tarball.generate())
3068 }
3069
3070 fn metadata(&self) -> Option<StepMetadata> {
3071 Some(StepMetadata::dist(
3072 "gcc",
3073 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3074 ))
3075 }
3076}
src/bootstrap/src/core/builder/mod.rs+2-1
......@@ -990,7 +990,8 @@ impl<'a> Builder<'a> {
990990 dist::PlainSourceTarballGpl,
991991 dist::BuildManifest,
992992 dist::ReproducibleArtifacts,
993 dist::GccDev
993 dist::GccDev,
994 dist::Gcc
994995 ),
995996 Kind::Install => describe!(
996997 install::Docs,
src/bootstrap/src/utils/tarball.rs+10
......@@ -26,6 +26,7 @@ pub(crate) enum OverlayKind {
2626 RustAnalyzer,
2727 RustcCodegenCranelift,
2828 RustcCodegenGcc,
29 Gcc,
2930 LlvmBitcodeLinker,
3031}
3132
......@@ -78,6 +79,14 @@ impl OverlayKind {
7879 "LICENSE-MIT",
7980 "src/tools/llvm-bitcode-linker/README.md",
8081 ],
82 OverlayKind::Gcc => &[
83 "src/gcc/README",
84 "src/gcc/COPYING",
85 "src/gcc/COPYING.LIB",
86 "src/gcc/COPYING.RUNTIME",
87 "src/gcc/COPYING3",
88 "src/gcc/COPYING3.LIB",
89 ],
8190 }
8291 }
8392
......@@ -101,6 +110,7 @@ impl OverlayKind {
101110 OverlayKind::RustcCodegenCranelift => builder.rust_version(),
102111 OverlayKind::RustcCodegenGcc => builder.rust_version(),
103112 OverlayKind::LlvmBitcodeLinker => builder.rust_version(),
113 OverlayKind::Gcc => builder.rust_version(),
104114 }
105115 }
106116}
src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh+3-1
......@@ -14,5 +14,7 @@ python3 ../x.py build --set rust.debug=true opt-dist
1414# Use GCC for building GCC components, as it seems to behave badly when built with Clang
1515# Only build GCC on full builds, not try builds
1616if [ "${DIST_TRY_BUILD:-0}" == "0" ]; then
17 CC=/rustroot/bin/cc CXX=/rustroot/bin/c++ python3 ../x.py dist gcc-dev
17 CC=/rustroot/bin/cc CXX=/rustroot/bin/c++ python3 ../x.py dist \
18 gcc-dev \
19 gcc
1820fi