Skip to content

Commit 4e3408a

Browse files
committed
Add a dist step for GCC
1 parent 6de834d commit 4e3408a

File tree

4 files changed

+114
-12
lines changed

4 files changed

+114
-12
lines changed

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,26 +1612,35 @@ impl GccDylibSet {
16121612
"Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
16131613
compiler.host
16141614
);
1615-
let libgccjit = libgccjit.libgccjit();
1616-
let target_filename = libgccjit.file_name().unwrap().to_str().unwrap();
1615+
let libgccjit_path = libgccjit.libgccjit();
16171616

16181617
// If we build libgccjit ourselves, then `libgccjit` can actually be a symlink.
16191618
// In that case, we have to resolve it first, otherwise we'd create a symlink to a
16201619
// symlink, which wouldn't work.
1621-
let actual_libgccjit_path = t!(
1622-
libgccjit.canonicalize(),
1623-
format!("Cannot find libgccjit at {}", libgccjit.display())
1620+
let libgccjit_path = t!(
1621+
libgccjit_path.canonicalize(),
1622+
format!("Cannot find libgccjit at {}", libgccjit_path.display())
16241623
);
16251624

1626-
// <cg-sysroot>/lib/<target>/libgccjit.so
1627-
let dest_dir = cg_sysroot.join("lib").join(target_pair.target());
1628-
t!(fs::create_dir_all(&dest_dir));
1629-
let dst = dest_dir.join(target_filename);
1630-
builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
1625+
let dst = cg_sysroot.join(libgccjit_path_relative_to_cg_dir(target_pair, libgccjit));
1626+
t!(std::fs::create_dir_all(dst.parent().unwrap()));
1627+
builder.copy_link(&libgccjit_path, &dst, FileType::NativeLibrary);
16311628
}
16321629
}
16331630
}
16341631

1632+
/// Returns a path where libgccjit.so should be stored, **relative** to the
1633+
/// **codegen backend directory**.
1634+
pub fn libgccjit_path_relative_to_cg_dir(
1635+
target_pair: &GccTargetPair,
1636+
libgccjit: &GccOutput,
1637+
) -> PathBuf {
1638+
let target_filename = libgccjit.libgccjit().file_name().unwrap().to_str().unwrap();
1639+
1640+
// <cg-dir>/lib/<target>/libgccjit.so
1641+
Path::new("lib").join(target_pair.target()).join(target_filename)
1642+
}
1643+
16351644
/// Output of the `compile::GccCodegenBackend` step.
16361645
///
16371646
/// It contains a build stamp with the path to the built cg_gcc dylib.

src/bootstrap/src/core/build_steps/dist.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use object::read::archive::ArchiveFile;
1919
#[cfg(feature = "tracing")]
2020
use tracing::instrument;
2121

22-
use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
22+
use crate::core::build_steps::compile::{
23+
get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name,
24+
};
2325
use crate::core::build_steps::doc::DocumentationFormat;
2426
use crate::core::build_steps::gcc::GccTargetPair;
2527
use crate::core::build_steps::tool::{
@@ -2992,3 +2994,83 @@ impl Step for CiGcc {
29922994
Some(StepMetadata::dist("ci-gcc", 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)]
3004+
pub struct Gcc {
3005+
host: TargetSelection,
3006+
target: TargetSelection,
3007+
}
3008+
3009+
impl 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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,8 @@ impl<'a> Builder<'a> {
990990
dist::PlainSourceTarballGpl,
991991
dist::BuildManifest,
992992
dist::ReproducibleArtifacts,
993-
dist::CiGcc
993+
dist::CiGcc,
994+
dist::Gcc
994995
),
995996
Kind::Install => describe!(
996997
install::Docs,

src/bootstrap/src/utils/tarball.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

0 commit comments

Comments
 (0)