@@ -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