@@ -14,14 +14,72 @@ use std::sync::OnceLock;
1414
1515use build_helper:: ci:: CiEnv ;
1616
17- use crate :: Kind ;
18- use crate :: core:: builder:: { Builder , RunConfig , ShouldRun , Step } ;
1917use crate :: core:: builder:: { Builder , Cargo , Kind , RunConfig , ShouldRun , Step } ;
2018use crate :: core:: config:: TargetSelection ;
2119use crate :: utils:: build_stamp:: { BuildStamp , generate_smart_stamp_hash} ;
2220use crate :: utils:: exec:: command;
2321use crate :: utils:: helpers:: { self , t} ;
2422
23+ #[ derive( Debug , Clone , Hash , PartialEq , Eq ) ]
24+ pub struct Gcc {
25+ pub target : TargetSelection ,
26+ }
27+
28+ #[ derive( Clone ) ]
29+ pub struct GccOutput {
30+ pub libgccjit : PathBuf ,
31+ }
32+
33+ impl Step for Gcc {
34+ type Output = GccOutput ;
35+
36+ const ONLY_HOSTS : bool = true ;
37+
38+ fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
39+ run. path ( "src/gcc" ) . alias ( "gcc" )
40+ }
41+
42+ fn make_run ( run : RunConfig < ' _ > ) {
43+ run. builder . ensure ( Gcc { target : run. target } ) ;
44+ }
45+
46+ /// Compile GCC (specifically `libgccjit`) for `target`.
47+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
48+ let target = self . target ;
49+
50+ // If GCC has already been built, we avoid building it again.
51+ let metadata = match get_gcc_build_status ( builder, target) {
52+ GccBuildStatus :: AlreadyBuilt ( path) => return GccOutput { libgccjit : path } ,
53+ GccBuildStatus :: ShouldBuild ( m) => m,
54+ } ;
55+
56+ let _guard = builder. msg_unstaged ( Kind :: Build , "GCC" , target) ;
57+ t ! ( metadata. stamp. remove( ) ) ;
58+ let _time = helpers:: timeit ( builder) ;
59+
60+ let libgccjit_path = libgccjit_built_path ( & metadata. install_dir ) ;
61+ if builder. config . dry_run ( ) {
62+ return GccOutput { libgccjit : libgccjit_path } ;
63+ }
64+
65+ build_gcc ( & metadata, builder, target) ;
66+ create_lib_alias ( builder, & libgccjit_path) ;
67+
68+ t ! ( metadata. stamp. write( ) ) ;
69+
70+ GccOutput { libgccjit : libgccjit_path }
71+ }
72+ }
73+
74+ /// Creates a libgccjit.so.0 alias next to libgccjit.so if it does not
75+ /// already exist
76+ fn create_lib_alias ( builder : & Builder < ' _ > , libgccjit : & PathBuf ) {
77+ let lib_alias = libgccjit. parent ( ) . unwrap ( ) . join ( "libgccjit.so.0" ) ;
78+ if !lib_alias. exists ( ) {
79+ t ! ( builder. symlink_file( libgccjit, lib_alias) ) ;
80+ }
81+ }
82+
2583pub struct Meta {
2684 stamp : BuildStamp ,
2785 out_dir : PathBuf ,
@@ -39,6 +97,8 @@ pub enum GccBuildStatus {
3997/// Returns a path to the libgccjit.so file.
4098#[ cfg( not( test) ) ]
4199fn try_download_gcc ( builder : & Builder < ' _ > , target : TargetSelection ) -> Option < PathBuf > {
100+ use build_helper:: git:: PathFreshness ;
101+
42102 // Try to download GCC from CI if configured and available
43103 if !matches ! ( builder. config. gcc_ci_mode, crate :: core:: config:: GccCiMode :: DownloadFromCi ) {
44104 return None ;
0 commit comments