@@ -19,6 +19,7 @@ use std::process::Command;
19
19
use std:: str:: FromStr ;
20
20
21
21
use crate :: core:: build_steps:: compile:: CODEGEN_BACKEND_PREFIX ;
22
+ use crate :: core:: build_steps:: llvm;
22
23
use crate :: core:: config:: flags:: { Color , Flags , Warnings } ;
23
24
use crate :: utils:: cache:: { Interned , INTERNER } ;
24
25
use crate :: utils:: cc_detect:: { ndk_compiler, Language } ;
@@ -1526,17 +1527,7 @@ impl Config {
1526
1527
config. llvm_build_config = llvm. build_config . clone ( ) . unwrap_or ( Default :: default ( ) ) ;
1527
1528
1528
1529
let asserts = llvm_assertions. unwrap_or ( false ) ;
1529
- config. llvm_from_ci = match llvm. download_ci_llvm {
1530
- Some ( StringOrBool :: String ( s) ) => {
1531
- assert_eq ! ( s, "if-available" , "unknown option `{s}` for download-ci-llvm" ) ;
1532
- crate :: core:: build_steps:: llvm:: is_ci_llvm_available ( & config, asserts)
1533
- }
1534
- Some ( StringOrBool :: Bool ( b) ) => b,
1535
- None => {
1536
- config. channel == "dev"
1537
- && crate :: core:: build_steps:: llvm:: is_ci_llvm_available ( & config, asserts)
1538
- }
1539
- } ;
1530
+ config. llvm_from_ci = config. parse_download_ci_llvm ( llvm. download_ci_llvm , asserts) ;
1540
1531
1541
1532
if config. llvm_from_ci {
1542
1533
// None of the LLVM options, except assertions, are supported
@@ -2107,6 +2098,90 @@ impl Config {
2107
2098
2108
2099
Some ( commit. to_string ( ) )
2109
2100
}
2101
+
2102
+ fn parse_download_ci_llvm (
2103
+ & self ,
2104
+ download_ci_llvm : Option < StringOrBool > ,
2105
+ asserts : bool ,
2106
+ ) -> bool {
2107
+ match download_ci_llvm {
2108
+ None => self . channel == "dev" && llvm:: is_ci_llvm_available ( & self , asserts) ,
2109
+ Some ( StringOrBool :: Bool ( b) ) => b,
2110
+ Some ( StringOrBool :: String ( s) ) if s == "if-available" => {
2111
+ llvm:: is_ci_llvm_available ( & self , asserts)
2112
+ }
2113
+ Some ( StringOrBool :: String ( s) ) if s == "if-unchanged" => {
2114
+ if self
2115
+ . last_modified_commit ( & [ "src/llvm-project" ] , "download-ci-llvm" , true )
2116
+ . is_none ( )
2117
+ {
2118
+ // there are some untracked changes in the the given paths.
2119
+ false
2120
+ } else {
2121
+ llvm:: is_ci_llvm_available ( & self , asserts)
2122
+ }
2123
+ }
2124
+ Some ( StringOrBool :: String ( other) ) => {
2125
+ panic ! ( "unrecognized option for download-ci-llvm: {:?}" , other)
2126
+ }
2127
+ }
2128
+ }
2129
+
2130
+ /// Returns the last commit in which any of `modified_paths` were changed,
2131
+ /// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
2132
+ pub fn last_modified_commit (
2133
+ & self ,
2134
+ modified_paths : & [ & str ] ,
2135
+ option_name : & str ,
2136
+ if_unchanged : bool ,
2137
+ ) -> Option < String > {
2138
+ // Handle running from a directory other than the top level
2139
+ let top_level = output ( self . git ( ) . args ( & [ "rev-parse" , "--show-toplevel" ] ) ) ;
2140
+ let top_level = top_level. trim_end ( ) ;
2141
+
2142
+ // Look for a version to compare to based on the current commit.
2143
+ // Only commits merged by bors will have CI artifacts.
2144
+ let merge_base = output (
2145
+ self . git ( )
2146
+ . arg ( "rev-list" )
2147
+ . arg ( format ! ( "--author={}" , self . stage0_metadata. config. git_merge_commit_email) )
2148
+ . args ( & [ "-n1" , "--first-parent" , "HEAD" ] ) ,
2149
+ ) ;
2150
+ let commit = merge_base. trim_end ( ) ;
2151
+ if commit. is_empty ( ) {
2152
+ println ! ( "error: could not find commit hash for downloading components from CI" ) ;
2153
+ println ! ( "help: maybe your repository history is too shallow?" ) ;
2154
+ println ! ( "help: consider disabling `{option_name}`" ) ;
2155
+ println ! ( "help: or fetch enough history to include one upstream commit" ) ;
2156
+ crate :: exit!( 1 ) ;
2157
+ }
2158
+
2159
+ // Warn if there were changes to the compiler or standard library since the ancestor commit.
2160
+ let mut git = self . git ( ) ;
2161
+ git. args ( & [ "diff-index" , "--quiet" , & commit, "--" ] ) ;
2162
+
2163
+ for path in modified_paths {
2164
+ git. arg ( format ! ( "{top_level}/{path}" ) ) ;
2165
+ }
2166
+
2167
+ let has_changes = !t ! ( git. status( ) ) . success ( ) ;
2168
+ if has_changes {
2169
+ if if_unchanged {
2170
+ if self . verbose > 0 {
2171
+ println ! (
2172
+ "warning: saw changes to one of {modified_paths:?} since {commit}; \
2173
+ ignoring `{option_name}`"
2174
+ ) ;
2175
+ }
2176
+ return None ;
2177
+ }
2178
+ println ! (
2179
+ "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
2180
+ ) ;
2181
+ }
2182
+
2183
+ Some ( commit. to_string ( ) )
2184
+ }
2110
2185
}
2111
2186
2112
2187
fn set < T > ( field : & mut T , val : Option < T > ) {
0 commit comments