@@ -16,6 +16,7 @@ use build_helper::ci::CiEnv;
16
16
17
17
use crate :: Kind ;
18
18
use crate :: core:: builder:: { Builder , RunConfig , ShouldRun , Step } ;
19
+ use crate :: core:: builder:: { Builder , Cargo , Kind , RunConfig , ShouldRun , Step } ;
19
20
use crate :: core:: config:: TargetSelection ;
20
21
use crate :: utils:: build_stamp:: { BuildStamp , generate_smart_stamp_hash} ;
21
22
use crate :: utils:: exec:: command;
@@ -33,7 +34,52 @@ pub enum GccBuildStatus {
33
34
ShouldBuild ( Meta ) ,
34
35
}
35
36
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.
37
83
///
38
84
/// It's used to avoid busting caches during x.py check -- if we've already built
39
85
/// GCC, it's fine for us to not try to avoid doing so.
@@ -178,6 +224,34 @@ impl Step for Gcc {
178
224
179
225
t ! ( stamp. write( ) ) ;
180
226
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
183
257
}
0 commit comments