@@ -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 , add_cg_gcc_cargo_flags} ;
22+ use crate :: core:: build_steps:: gcc:: { Gcc , GccOutput , GccTargetPair , add_cg_gcc_cargo_flags} ;
2323use crate :: core:: build_steps:: tool:: { RustcPrivateCompilers , SourceType , copy_lld_artifacts} ;
2424use crate :: core:: build_steps:: { dist, llvm} ;
2525use crate :: core:: builder;
@@ -1579,16 +1579,16 @@ impl Step for RustcLink {
15791579/// Set of `libgccjit` dylibs that can be used by `cg_gcc` to compile code for a set of targets.
15801580#[ derive( Clone ) ]
15811581pub struct GccDylibSet {
1582- dylibs : BTreeMap < TargetSelection , GccOutput > ,
1583- host_target : TargetSelection ,
1582+ dylibs : BTreeMap < GccTargetPair , GccOutput > ,
1583+ host_pair : GccTargetPair ,
15841584}
15851585
15861586impl GccDylibSet {
15871587 /// Returns the libgccjit.so dylib that corresponds to a host target on which `cg_gcc` will be
15881588 /// executed.
15891589 fn host_dylib ( & self ) -> & GccOutput {
1590- self . dylibs . get ( & self . host_target ) . unwrap_or_else ( || {
1591- panic ! ( "libgccjit.so was not build for host target {}" , self . host_target )
1590+ self . dylibs . get ( & self . host_pair ) . unwrap_or_else ( || {
1591+ panic ! ( "libgccjit.so was not build for host target {}" , self . host_pair )
15921592 } )
15931593 }
15941594
@@ -1601,7 +1601,13 @@ impl GccDylibSet {
16011601 // <rustc>/lib/<host-target>/codegen-backends
16021602 let cg_sysroot = builder. sysroot_codegen_backends ( compiler) ;
16031603
1604- for ( target, libgccjit) in & self . dylibs {
1604+ for ( target_pair, libgccjit) in & self . dylibs {
1605+ assert_eq ! (
1606+ target_pair. host( ) ,
1607+ compiler. host,
1608+ "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})" ,
1609+ compiler. host
1610+ ) ;
16051611 let libgccjit = libgccjit. libgccjit ( ) ;
16061612 let target_filename = libgccjit. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
16071613
@@ -1614,7 +1620,7 @@ impl GccDylibSet {
16141620 ) ;
16151621
16161622 // <cg-sysroot>/lib/<target>/libgccjit.so
1617- let dest_dir = cg_sysroot. join ( "lib" ) . join ( target) ;
1623+ let dest_dir = cg_sysroot. join ( "lib" ) . join ( target_pair . target ( ) ) ;
16181624 t ! ( fs:: create_dir_all( & dest_dir) ) ;
16191625 let dst = dest_dir. join ( target_filename) ;
16201626 builder. copy_link ( & actual_libgccjit_path, & dst, FileType :: NativeLibrary ) ;
@@ -1648,15 +1654,12 @@ pub struct GccCodegenBackend {
16481654}
16491655
16501656impl GccCodegenBackend {
1651- /// Create a cg_gcc backend that can compile code for all targets for which we build the
1652- /// standard library, plus the host target on which `cg_gcc` will run, so that it can compile
1653- /// host code (e.g. proc macros).
1654- pub fn for_all_std_targets ( builder : & Builder < ' _ > , compilers : RustcPrivateCompilers ) -> Self {
1655- // All std targets + the cg_gcc host target
1656- let target_set: HashSet < TargetSelection > =
1657- builder. targets . iter ( ) . copied ( ) . chain ( std:: iter:: once ( compilers. target ( ) ) ) . collect ( ) ;
1658-
1659- let mut targets: Vec < TargetSelection > = target_set. into_iter ( ) . collect ( ) ;
1657+ /// Build `cg_gcc` that will run on host `H` (`compilers.target_compiler.host`) and will be
1658+ /// able to produce code target pairs (`H`, `T`) for all `T` from `targets`.
1659+ pub fn for_targets (
1660+ compilers : RustcPrivateCompilers ,
1661+ mut targets : Vec < TargetSelection > ,
1662+ ) -> Self {
16601663 // Sort targets to improve step cache hits
16611664 targets. sort ( ) ;
16621665 Self { compilers, targets }
@@ -1673,30 +1676,33 @@ impl Step for GccCodegenBackend {
16731676 }
16741677
16751678 fn make_run ( run : RunConfig < ' _ > ) {
1676- run . builder . ensure ( GccCodegenBackend :: for_all_std_targets (
1677- run . builder ,
1678- RustcPrivateCompilers :: new ( run. builder , run. builder . top_stage , run. target ) ,
1679- ) ) ;
1679+ // By default, build cg_gcc that will only be able to compile native code for the given
1680+ // host target.
1681+ let compilers = RustcPrivateCompilers :: new ( run. builder , run. builder . top_stage , run. target ) ;
1682+ run . builder . ensure ( GccCodegenBackend { compilers , targets : vec ! [ run . target ] } ) ;
16801683 }
16811684
16821685 fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
1683- let target = self . compilers . target ( ) ;
1686+ let host = self . compilers . target ( ) ;
16841687 let build_compiler = self . compilers . build_compiler ( ) ;
16851688
16861689 let stamp = build_stamp:: codegen_backend_stamp (
16871690 builder,
16881691 build_compiler,
1689- target ,
1692+ host ,
16901693 & CodegenBackendKind :: Gcc ,
16911694 ) ;
16921695
16931696 let dylib_set = GccDylibSet {
16941697 dylibs : self
16951698 . targets
16961699 . iter ( )
1697- . map ( |& target| ( target, builder. ensure ( Gcc { target } ) ) )
1700+ . map ( |& target| {
1701+ let target_pair = GccTargetPair :: for_cross_build ( host, target) ;
1702+ ( target_pair, builder. ensure ( Gcc { target_pair } ) )
1703+ } )
16981704 . collect ( ) ,
1699- host_target : target ,
1705+ host_pair : GccTargetPair :: for_native_build ( host ) ,
17001706 } ;
17011707
17021708 if builder. config . keep_stage . contains ( & build_compiler. stage ) {
@@ -1715,16 +1721,16 @@ impl Step for GccCodegenBackend {
17151721 build_compiler,
17161722 Mode :: Codegen ,
17171723 SourceType :: InTree ,
1718- target ,
1724+ host ,
17191725 Kind :: Build ,
17201726 ) ;
17211727 cargo. arg ( "--manifest-path" ) . arg ( builder. src . join ( "compiler/rustc_codegen_gcc/Cargo.toml" ) ) ;
1722- rustc_cargo_env ( builder, & mut cargo, target ) ;
1728+ rustc_cargo_env ( builder, & mut cargo, host ) ;
17231729
17241730 add_cg_gcc_cargo_flags ( & mut cargo, dylib_set. host_dylib ( ) ) ;
17251731
17261732 let _guard =
1727- builder. msg ( Kind :: Build , "codegen backend gcc" , Mode :: Codegen , build_compiler, target ) ;
1733+ builder. msg ( Kind :: Build , "codegen backend gcc" , Mode :: Codegen , build_compiler, host ) ;
17281734 let files = run_cargo ( builder, cargo, vec ! [ ] , & stamp, vec ! [ ] , false , false ) ;
17291735
17301736 GccCodegenBackendOutput {
@@ -2406,9 +2412,59 @@ impl Step for Assemble {
24062412 copy_codegen_backends_to_sysroot ( builder, stamp, target_compiler) ;
24072413 }
24082414 CodegenBackendKind :: Gcc => {
2409- let output = builder. ensure ( GccCodegenBackend :: for_all_std_targets (
2410- builder,
2411- prepare_compilers ( ) ,
2415+ // We need to build cg_gcc for the host target of the compiler which we
2416+ // build here, which is `target_compiler`.
2417+ // But we also need to build libgccjit for some additional targets, in
2418+ // the most general case.
2419+ // 1. We need to build (target_compiler.host, stdlib target) libgccjit
2420+ // for all stdlibs that we build, so that cg_gcc can be used to build code
2421+ // for all those targets.
2422+ // 2. We need to build (target_compiler.host, target_compiler.host)
2423+ // libgccjit, so that the target compiler can compile host code (e.g. proc
2424+ // macros).
2425+ // 3. We need to build (target_compiler.host, host target) libgccjit
2426+ // for all *host targets* that we build, so that cg_gcc can be used to
2427+ // build a (possibly cross-compiled) stage 2+ rustc.
2428+ //
2429+ // Assume that we are on host T1 and we do a stage2 build of rustc for T2.
2430+ // We want the T2 rustc compiler to be able to use cg_gcc and build code
2431+ // for T2 (host) and T3 (target). We also want to build the stage2 compiler
2432+ // itself using cg_gcc.
2433+ // This could correspond to the following bootstrap invocation:
2434+ // `x build rustc --build T1 --host T2 --target T3 --set codegen-backends=['gcc', 'llvm']`
2435+ //
2436+ // For that, we will need the following GCC target pairs:
2437+ // 1. T1 -> T2 (to cross-compile a T2 rustc using cg_gcc running on T1)
2438+ // 2. T2 -> T2 (to build host code with the stage 2 rustc running on T2)
2439+ // 3. T2 -> T3 (to cross-compile code with the stage 2 rustc running on T2)
2440+ //
2441+ // Note that this set of targets is *maximal*, in reality we might need
2442+ // less libgccjits at this current build stage. So below we try to determine
2443+ // which target pairs we actually need at this stage.
2444+
2445+ let compilers = prepare_compilers ( ) ;
2446+
2447+ // The left side of the target pairs below is implied. It has to match the
2448+ // host target on which cg_gcc will run, which is the host target of
2449+ // `target_compiler`. We only pass the right side of the target pairs to
2450+ // the `GccCodegenBackend` constructor.
2451+ let mut targets = HashSet :: new ( ) ;
2452+ // Add all host targets, so that we are able to build host code in this
2453+ // bootstrap invocation using cg_gcc.
2454+ for target in & builder. hosts {
2455+ targets. insert ( * target) ;
2456+ }
2457+ // Add all stdlib targets, so that the built rustc can produce code for them
2458+ for target in & builder. targets {
2459+ targets. insert ( * target) ;
2460+ }
2461+ // Add the host target of the built rustc itself, so that it can build
2462+ // host code (e.g. proc macros) using cg_gcc.
2463+ targets. insert ( compilers. target_compiler ( ) . host ) ;
2464+
2465+ let output = builder. ensure ( GccCodegenBackend :: for_targets (
2466+ compilers,
2467+ targets. into_iter ( ) . collect ( ) ,
24122468 ) ) ;
24132469 copy_codegen_backends_to_sysroot ( builder, output. stamp , target_compiler) ;
24142470 // Also copy all requires libgccjit dylibs to the corresponding
0 commit comments