@@ -16,6 +16,7 @@ use build_helper::ci::CiEnv;
1616
1717use crate :: Kind ;
1818use crate :: core:: builder:: { Builder , RunConfig , ShouldRun , Step } ;
19+ use crate :: core:: builder:: { Builder , Cargo , Kind , RunConfig , ShouldRun , Step } ;
1920use crate :: core:: config:: TargetSelection ;
2021use crate :: utils:: build_stamp:: { BuildStamp , generate_smart_stamp_hash} ;
2122use crate :: utils:: exec:: command;
@@ -33,7 +34,52 @@ pub enum GccBuildStatus {
3334 ShouldBuild ( Meta ) ,
3435}
3536
36- /// This returns whether we've already previously built GCC.
37+ /// Tries to download GCC from CI if it is enabled and GCC artifacts
38+ /// are available for the given target.
39+ /// Returns a path to the libgccjit.so file.
40+ #[ cfg( not( test) ) ]
41+ fn try_download_gcc ( builder : & Builder < ' _ > , target : TargetSelection ) -> Option < PathBuf > {
42+ // Try to download GCC from CI if configured and available
43+ if !matches ! ( builder. config. gcc_ci_mode, crate :: core:: config:: GccCiMode :: DownloadFromCi ) {
44+ return None ;
45+ }
46+ if target != "x86_64-unknown-linux-gnu" {
47+ eprintln ! ( "GCC CI download is only available for the `x86_64-unknown-linux-gnu` target" ) ;
48+ return None ;
49+ }
50+ let source = detect_gcc_freshness (
51+ & builder. config ,
52+ builder. config . rust_info . is_managed_git_subrepository ( ) ,
53+ ) ;
54+ match source {
55+ PathFreshness :: LastModifiedUpstream { upstream } => {
56+ // Download from upstream CI
57+ let root = ci_gcc_root ( & builder. config ) ;
58+ let gcc_stamp = BuildStamp :: new ( & root) . with_prefix ( "gcc" ) . add_stamp ( & upstream) ;
59+ if !gcc_stamp. is_up_to_date ( ) && !builder. config . dry_run ( ) {
60+ builder. config . download_ci_gcc ( & upstream, & root) ;
61+ t ! ( gcc_stamp. write( ) ) ;
62+ }
63+
64+ let libgccjit = root. join ( "lib" ) . join ( "libgccjit.so" ) ;
65+ create_lib_alias ( builder, & libgccjit) ;
66+ Some ( libgccjit)
67+ }
68+ PathFreshness :: HasLocalModifications { .. } => {
69+ // We have local modifications, rebuild GCC.
70+ eprintln ! ( "Found local GCC modifications, GCC will *not* be downloaded" ) ;
71+ None
72+ }
73+ }
74+ }
75+
76+ #[ cfg( test) ]
77+ fn try_download_gcc ( _builder : & Builder < ' _ > , _target : TargetSelection ) -> Option < PathBuf > {
78+ None
79+ }
80+
81+ /// This returns information about whether GCC should be built or if it's already built.
82+ /// It transparently handles downloading GCC from CI if needed.
3783///
3884/// It's used to avoid busting caches during x.py check -- if we've already built
3985/// GCC, it's fine for us to not try to avoid doing so.
@@ -178,6 +224,34 @@ impl Step for Gcc {
178224
179225 t ! ( stamp. write( ) ) ;
180226
181- true
182- }
227+ /// Detect whether GCC sources have been modified locally or not.
228+ #[ cfg( not( test) ) ]
229+ fn detect_gcc_freshness ( config : & crate :: Config , is_git : bool ) -> build_helper:: git:: PathFreshness {
230+ use build_helper:: git:: { PathFreshness , check_path_modifications} ;
231+
232+ let freshness = if is_git {
233+ Some (
234+ check_path_modifications (
235+ Some ( & config. src ) ,
236+ & config. git_config ( ) ,
237+ & [ "src/gcc" , "src/bootstrap/download-ci-gcc-stamp" ] ,
238+ CiEnv :: current ( ) ,
239+ )
240+ . unwrap ( ) ,
241+ )
242+ } else if let Some ( info) = crate :: utils:: channel:: read_commit_info_file ( & config. src ) {
243+ Some ( PathFreshness :: LastModifiedUpstream { upstream : info. sha . trim ( ) . to_owned ( ) } )
244+ } else {
245+ None
246+ } ;
247+
248+ let Some ( freshness) = freshness else {
249+ eprintln ! ( "error: could not find commit hash for downloading GCC" ) ;
250+ eprintln ! ( "HELP: maybe your repository history is too shallow?" ) ;
251+ eprintln ! ( "HELP: consider disabling `download-ci-gcc`" ) ;
252+ eprintln ! ( "HELP: or fetch enough history to include one upstream commit" ) ;
253+ panic ! ( ) ;
254+ } ;
255+
256+ freshness
183257}
0 commit comments