@@ -19,7 +19,9 @@ use object::read::archive::ArchiveFile;
1919#[ cfg( feature = "tracing" ) ]
2020use 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+ } ;
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 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+ }
0 commit comments