@@ -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.
@@ -1604,61 +1612,65 @@ impl GccDylibSet {
16041612 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})" ,
16051613 compiler. host
16061614 ) ;
1607- let libgccjit = libgccjit. libgccjit ( ) ;
1608- let target_filename = libgccjit. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
1615+ let libgccjit_path = libgccjit. libgccjit ( ) ;
16091616
16101617 // If we build libgccjit ourselves, then `libgccjit` can actually be a symlink.
16111618 // In that case, we have to resolve it first, otherwise we'd create a symlink to a
16121619 // symlink, which wouldn't work.
1613- let actual_libgccjit_path = t ! (
1614- libgccjit . canonicalize( ) ,
1615- 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( ) )
16161623 ) ;
16171624
1618- // <cg-sysroot>/lib/<target>/libgccjit.so
1619- let dest_dir = cg_sysroot. join ( "lib" ) . join ( target_pair. target ( ) ) ;
1620- t ! ( fs:: create_dir_all( & dest_dir) ) ;
1621- let dst = dest_dir. join ( target_filename) ;
1622- 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 ) ;
16231628 }
16241629 }
16251630}
16261631
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+
16271644/// Output of the `compile::GccCodegenBackend` step.
16281645///
1629- /// It contains paths to all built libgccjit libraries on which this backend depends here .
1646+ /// It contains a build stamp with the path to the built cg_gcc dylib .
16301647#[ derive( Clone ) ]
16311648pub struct GccCodegenBackendOutput {
16321649 stamp : BuildStamp ,
1633- dylib_set : GccDylibSet ,
1650+ }
1651+
1652+ impl GccCodegenBackendOutput {
1653+ pub fn stamp ( & self ) -> & BuildStamp {
1654+ & self . stamp
1655+ }
16341656}
16351657
16361658/// 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`.
1659+ /// Note that this **does not** build libgccjit, which is a dependency of cg_gcc.
1660+ /// That has to be built separately, because a separate copy of libgccjit is required
1661+ /// for each (host, target) compilation pair.
1662+ /// cg_gcc goes to great lengths to ensure that it does not *directly* link to libgccjit,
1663+ /// so we respect that here and allow building cg_gcc without building libgccjit itself.
16461664#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
16471665pub struct GccCodegenBackend {
16481666 compilers : RustcPrivateCompilers ,
1649- targets : Vec < TargetSelection > ,
1667+ target : TargetSelection ,
16501668}
16511669
16521670impl 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 }
1671+ /// Build `cg_gcc` that will run on the given host target.
1672+ pub fn for_target ( compilers : RustcPrivateCompilers , target : TargetSelection ) -> Self {
1673+ Self { compilers, target }
16621674 }
16631675}
16641676
@@ -1672,10 +1684,8 @@ impl Step for GccCodegenBackend {
16721684 }
16731685
16741686 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.
16771687 let compilers = RustcPrivateCompilers :: new ( run. builder , run. builder . top_stage , run. target ) ;
1678- run. builder . ensure ( GccCodegenBackend { compilers, targets : vec ! [ run. target] } ) ;
1688+ run. builder . ensure ( GccCodegenBackend :: for_target ( compilers, run. target ) ) ;
16791689 }
16801690
16811691 fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
@@ -1689,18 +1699,6 @@ impl Step for GccCodegenBackend {
16891699 & CodegenBackendKind :: Gcc ,
16901700 ) ;
16911701
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-
17041702 if builder. config . keep_stage . contains ( & build_compiler. stage ) {
17051703 trace ! ( "`keep-stage` requested" ) ;
17061704 builder. info (
@@ -1709,7 +1707,7 @@ impl Step for GccCodegenBackend {
17091707 ) ;
17101708 // Codegen backends are linked separately from this step today, so we don't do
17111709 // anything here.
1712- return GccCodegenBackendOutput { stamp, dylib_set } ;
1710+ return GccCodegenBackendOutput { stamp } ;
17131711 }
17141712
17151713 let mut cargo = builder:: Cargo :: new (
@@ -1723,15 +1721,12 @@ impl Step for GccCodegenBackend {
17231721 cargo. arg ( "--manifest-path" ) . arg ( builder. src . join ( "compiler/rustc_codegen_gcc/Cargo.toml" ) ) ;
17241722 rustc_cargo_env ( builder, & mut cargo, host) ;
17251723
1726- add_cg_gcc_cargo_flags ( & mut cargo, dylib_set. host_dylib ( ) ) ;
1727-
17281724 let _guard =
17291725 builder. msg ( Kind :: Build , "codegen backend gcc" , Mode :: Codegen , build_compiler, host) ;
17301726 let files = run_cargo ( builder, cargo, vec ! [ ] , & stamp, vec ! [ ] , false , false ) ;
17311727
17321728 GccCodegenBackendOutput {
17331729 stamp : write_codegen_backend_stamp ( stamp, files, builder. config . dry_run ( ) ) ,
1734- dylib_set,
17351730 }
17361731 }
17371732
@@ -2457,12 +2452,18 @@ impl Step for Assemble {
24572452 // GCC dylibs built below by taking a look at the current stage and whether
24582453 // cg_gcc is used as the default codegen backend.
24592454
2455+ // First, the easy part: build cg_gcc
24602456 let compilers = prepare_compilers ( ) ;
2457+ let cg_gcc = builder
2458+ . ensure ( GccCodegenBackend :: for_target ( compilers, target_compiler. host ) ) ;
2459+ copy_codegen_backends_to_sysroot ( builder, cg_gcc. stamp , target_compiler) ;
2460+
2461+ // Then, the hard part: prepare all required libgccjit dylibs.
24612462
24622463 // 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
2464+ // host target on which libgccjit will be used , which is the host target of
24642465 // `target_compiler`. We only pass the right side of the target pairs to
2465- // the `GccCodegenBackend ` constructor.
2466+ // the `GccDylibSet ` constructor.
24662467 let mut targets = HashSet :: new ( ) ;
24672468 // Add all host targets, so that we are able to build host code in this
24682469 // bootstrap invocation using cg_gcc.
@@ -2477,14 +2478,16 @@ impl Step for Assemble {
24772478 // host code (e.g. proc macros) using cg_gcc.
24782479 targets. insert ( compilers. target_compiler ( ) . host ) ;
24792480
2480- let output = builder. ensure ( GccCodegenBackend :: for_targets (
2481- compilers,
2481+ // Now build all the required libgccjit dylibs
2482+ let dylib_set = GccDylibSet :: build (
2483+ builder,
2484+ compilers. target_compiler ( ) . host ,
24822485 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) ;
2486+ ) ;
2487+
2488+ // And then copy all the dylibs to the corresponding
2489+ // library sysroots, so that they are available for cg_gcc .
2490+ dylib_set. install_to ( builder, target_compiler) ;
24882491 }
24892492 CodegenBackendKind :: Llvm | CodegenBackendKind :: Custom ( _) => continue ,
24902493 }
0 commit comments