@@ -19,7 +19,7 @@ use serde_derive::Deserialize;
1919#[ cfg( feature = "tracing" ) ]
2020use tracing:: span;
2121
22- use crate :: core:: build_steps:: gcc:: { Gcc , GccOutput , GccTargetPair , add_cg_gcc_cargo_flags } ;
22+ use crate :: core:: build_steps:: gcc:: { Gcc , GccOutput , GccTargetPair } ;
2323use crate :: core:: build_steps:: tool:: { RustcPrivateCompilers , SourceType , copy_lld_artifacts} ;
2424use crate :: core:: build_steps:: { dist, llvm} ;
2525use crate :: core:: builder;
@@ -1569,21 +1569,29 @@ impl Step for RustcLink {
15691569}
15701570
15711571/// Set of `libgccjit` dylibs that can be used by `cg_gcc` to compile code for a set of targets.
1572+ /// `libgccjit` requires a separate build for each `(host, target)` pair.
1573+ /// So if you are on linux-x64 and build for linux-aarch64, you will need at least:
1574+ /// - linux-x64 -> linux-x64 libgccjit (for building host code like proc macros)
1575+ /// - linux-x64 -> linux-aarch64 libgccjit (for the aarch64 target code)
15721576#[ derive( Clone ) ]
15731577pub struct GccDylibSet {
15741578 dylibs : BTreeMap < GccTargetPair , GccOutput > ,
1575- host_pair : GccTargetPair ,
15761579}
15771580
15781581impl GccDylibSet {
1579- /// Returns the libgccjit.so dylib that corresponds to a host target on which `cg_gcc` will be
1580- /// executed, and which will target the host. So e.g. if `cg_gcc` will be executed on
1581- /// x86_64-unknown-linux-gnu, the host dylib will be for compilation pair
1582- /// `(x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu)`.
1583- fn host_dylib ( & self ) -> & GccOutput {
1584- self . dylibs . get ( & self . host_pair ) . unwrap_or_else ( || {
1585- panic ! ( "libgccjit.so was not built for host target {}" , self . host_pair)
1586- } )
1582+ /// Build a set of libgccjit dylibs that will be executed on `host` and will generate code for
1583+ /// each specified target.
1584+ pub fn build (
1585+ builder : & Builder < ' _ > ,
1586+ host : TargetSelection ,
1587+ targets : Vec < TargetSelection > ,
1588+ ) -> Self {
1589+ let dylibs = targets
1590+ . iter ( )
1591+ . map ( |t| GccTargetPair :: for_target_pair ( host, * t) )
1592+ . map ( |target_pair| ( target_pair, builder. ensure ( Gcc { target_pair } ) ) )
1593+ . collect ( ) ;
1594+ Self { dylibs }
15871595 }
15881596
15891597 /// Install the libgccjit dylibs to the corresponding target directories of the given compiler.
@@ -1626,39 +1634,34 @@ impl GccDylibSet {
16261634
16271635/// Output of the `compile::GccCodegenBackend` step.
16281636///
1629- /// It contains paths to all built libgccjit libraries on which this backend depends here .
1637+ /// It contains a build stamp with the path to the built cg_gcc dylib .
16301638#[ derive( Clone ) ]
16311639pub struct GccCodegenBackendOutput {
16321640 stamp : BuildStamp ,
1633- dylib_set : GccDylibSet ,
1641+ }
1642+
1643+ impl GccCodegenBackendOutput {
1644+ pub fn stamp ( & self ) -> & BuildStamp {
1645+ & self . stamp
1646+ }
16341647}
16351648
16361649/// Builds the GCC codegen backend (`cg_gcc`).
1637- /// The `cg_gcc` backend uses `libgccjit`, which requires a separate build for each
1638- /// `host -> target` pair. So if you are on linux-x64 and build for linux-aarch64,
1639- /// you will need at least:
1640- /// - linux-x64 -> linux-x64 libgccjit (for building host code like proc macros)
1641- /// - linux-x64 -> linux-aarch64 libgccjit (for the aarch64 target code)
1642- ///
1643- /// We model this by having a single cg_gcc for a given host target, which contains one
1644- /// libgccjit per (host, target) pair.
1645- /// Note that the host target is taken from `self.compilers.target_compiler.host`.
1650+ /// Note that this **does not** build libgccjit, which is a dependency of cg_gcc.
1651+ /// That has to be built separately, because a separate copy of libgccjit is required
1652+ /// for each (host, target) compilation pair.
1653+ /// cg_gcc goes to great lengths to ensure that it does not *directly* link to libgccjit,
1654+ /// so we respect that here and allow building cg_gcc without building libgccjit itself.
16461655#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
16471656pub struct GccCodegenBackend {
16481657 compilers : RustcPrivateCompilers ,
1649- targets : Vec < TargetSelection > ,
1658+ target : TargetSelection ,
16501659}
16511660
16521661impl GccCodegenBackend {
1653- /// Build `cg_gcc` that will run on host `H` (`compilers.target_compiler.host`) and will be
1654- /// able to produce code target pairs (`H`, `T`) for all `T` from `targets`.
1655- pub fn for_targets (
1656- compilers : RustcPrivateCompilers ,
1657- mut targets : Vec < TargetSelection > ,
1658- ) -> Self {
1659- // Sort targets to improve step cache hits
1660- targets. sort ( ) ;
1661- Self { compilers, targets }
1662+ /// Build `cg_gcc` that will run on the given host target.
1663+ pub fn for_target ( compilers : RustcPrivateCompilers , target : TargetSelection ) -> Self {
1664+ Self { compilers, target }
16621665 }
16631666}
16641667
@@ -1672,10 +1675,8 @@ impl Step for GccCodegenBackend {
16721675 }
16731676
16741677 fn make_run ( run : RunConfig < ' _ > ) {
1675- // By default, build cg_gcc that will only be able to compile native code for the given
1676- // host target.
16771678 let compilers = RustcPrivateCompilers :: new ( run. builder , run. builder . top_stage , run. target ) ;
1678- run. builder . ensure ( GccCodegenBackend { compilers, targets : vec ! [ run. target] } ) ;
1679+ run. builder . ensure ( GccCodegenBackend :: for_target ( compilers, run. target ) ) ;
16791680 }
16801681
16811682 fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
@@ -1689,27 +1690,15 @@ impl Step for GccCodegenBackend {
16891690 & CodegenBackendKind :: Gcc ,
16901691 ) ;
16911692
1692- let dylib_set = GccDylibSet {
1693- dylibs : self
1694- . targets
1695- . iter ( )
1696- . map ( |& target| {
1697- let target_pair = GccTargetPair :: for_target_pair ( host, target) ;
1698- ( target_pair, builder. ensure ( Gcc { target_pair } ) )
1699- } )
1700- . collect ( ) ,
1701- host_pair : GccTargetPair :: for_native_build ( host) ,
1702- } ;
1703-
1704- if builder. config . keep_stage . contains ( & build_compiler. stage ) {
1693+ if builder. config . keep_stage . contains ( & build_compiler. stage ) && stamp. path ( ) . exists ( ) {
17051694 trace ! ( "`keep-stage` requested" ) ;
17061695 builder. info (
17071696 "WARNING: Using a potentially old codegen backend. \
17081697 This may not behave well.",
17091698 ) ;
17101699 // Codegen backends are linked separately from this step today, so we don't do
17111700 // anything here.
1712- return GccCodegenBackendOutput { stamp, dylib_set } ;
1701+ return GccCodegenBackendOutput { stamp } ;
17131702 }
17141703
17151704 let mut cargo = builder:: Cargo :: new (
@@ -1723,15 +1712,12 @@ impl Step for GccCodegenBackend {
17231712 cargo. arg ( "--manifest-path" ) . arg ( builder. src . join ( "compiler/rustc_codegen_gcc/Cargo.toml" ) ) ;
17241713 rustc_cargo_env ( builder, & mut cargo, host) ;
17251714
1726- add_cg_gcc_cargo_flags ( & mut cargo, dylib_set. host_dylib ( ) ) ;
1727-
17281715 let _guard =
17291716 builder. msg ( Kind :: Build , "codegen backend gcc" , Mode :: Codegen , build_compiler, host) ;
17301717 let files = run_cargo ( builder, cargo, vec ! [ ] , & stamp, vec ! [ ] , false , false ) ;
17311718
17321719 GccCodegenBackendOutput {
17331720 stamp : write_codegen_backend_stamp ( stamp, files, builder. config . dry_run ( ) ) ,
1734- dylib_set,
17351721 }
17361722 }
17371723
@@ -2457,12 +2443,18 @@ impl Step for Assemble {
24572443 // GCC dylibs built below by taking a look at the current stage and whether
24582444 // cg_gcc is used as the default codegen backend.
24592445
2446+ // First, the easy part: build cg_gcc
24602447 let compilers = prepare_compilers ( ) ;
2448+ let cg_gcc = builder
2449+ . ensure ( GccCodegenBackend :: for_target ( compilers, target_compiler. host ) ) ;
2450+ copy_codegen_backends_to_sysroot ( builder, cg_gcc. stamp , target_compiler) ;
2451+
2452+ // Then, the hard part: prepare all required libgccjit dylibs.
24612453
24622454 // The left side of the target pairs below is implied. It has to match the
2463- // host target on which cg_gcc will run , which is the host target of
2455+ // host target on which libgccjit will be used , which is the host target of
24642456 // `target_compiler`. We only pass the right side of the target pairs to
2465- // the `GccCodegenBackend ` constructor.
2457+ // the `GccDylibSet ` constructor.
24662458 let mut targets = HashSet :: new ( ) ;
24672459 // Add all host targets, so that we are able to build host code in this
24682460 // bootstrap invocation using cg_gcc.
@@ -2477,14 +2469,16 @@ impl Step for Assemble {
24772469 // host code (e.g. proc macros) using cg_gcc.
24782470 targets. insert ( compilers. target_compiler ( ) . host ) ;
24792471
2480- let output = builder. ensure ( GccCodegenBackend :: for_targets (
2481- compilers,
2472+ // Now build all the required libgccjit dylibs
2473+ let dylib_set = GccDylibSet :: build (
2474+ builder,
2475+ compilers. target_compiler ( ) . host ,
24822476 targets. into_iter ( ) . collect ( ) ,
2483- ) ) ;
2484- copy_codegen_backends_to_sysroot ( builder , output . stamp , target_compiler ) ;
2485- // Also copy all requires libgccjit dylibs to the corresponding
2486- // library sysroots, so that they are available for the codegen backend .
2487- output . dylib_set . install_to ( builder, target_compiler) ;
2477+ ) ;
2478+
2479+ // And then copy all the dylibs to the corresponding
2480+ // library sysroots, so that they are available for cg_gcc .
2481+ dylib_set. install_to ( builder, target_compiler) ;
24882482 }
24892483 CodegenBackendKind :: Llvm | CodegenBackendKind :: Custom ( _) => continue ,
24902484 }
0 commit comments