@@ -26,7 +26,7 @@ use std::path::{Path, PathBuf};
26
26
use std:: process:: Command ;
27
27
use std:: { env, iter} ;
28
28
29
- use crate :: config:: { Target , TargetSelection } ;
29
+ use crate :: config:: TargetSelection ;
30
30
use crate :: util:: output;
31
31
use crate :: { Build , CLang , GitRepo } ;
32
32
@@ -100,10 +100,11 @@ pub fn find(build: &mut Build) {
100
100
for target in targets. into_iter ( ) {
101
101
let mut cfg = new_cc_build ( build, target) ;
102
102
let config = build. config . target_config . get ( & target) ;
103
- if let Some ( cc) = config. and_then ( |c| c. cc . as_ref ( ) ) {
103
+ if let Some ( cc) = config
104
+ . and_then ( |c| c. cc . clone ( ) )
105
+ . or_else ( || default_compiler ( & mut cfg, Language :: C , target, build) )
106
+ {
104
107
cfg. compiler ( cc) ;
105
- } else {
106
- set_compiler ( & mut cfg, Language :: C , target, config, build) ;
107
108
}
108
109
109
110
let compiler = cfg. get_compiler ( ) ;
@@ -120,12 +121,12 @@ pub fn find(build: &mut Build) {
120
121
// We'll need one anyways if the target triple is also a host triple
121
122
let mut cfg = new_cc_build ( build, target) ;
122
123
cfg. cpp ( true ) ;
123
- let cxx_configured = if let Some ( cxx) = config. and_then ( |c| c. cxx . as_ref ( ) ) {
124
+ let cxx_configured = if let Some ( cxx) = config
125
+ . and_then ( |c| c. cxx . clone ( ) )
126
+ . or_else ( || default_compiler ( & mut cfg, Language :: CPlusPlus , target, build) )
127
+ {
124
128
cfg. compiler ( cxx) ;
125
129
true
126
- } else if build. hosts . contains ( & target) || build. build == target {
127
- set_compiler ( & mut cfg, Language :: CPlusPlus , target, config, build) ;
128
- true
129
130
} else {
130
131
// Use an auto-detected compiler (or one configured via `CXX_target_triple` env vars).
131
132
cfg. try_get_compiler ( ) . is_ok ( )
@@ -155,68 +156,70 @@ pub fn find(build: &mut Build) {
155
156
}
156
157
}
157
158
158
- fn set_compiler (
159
+ fn default_compiler (
159
160
cfg : & mut cc:: Build ,
160
161
compiler : Language ,
161
162
target : TargetSelection ,
162
- config : Option < & Target > ,
163
163
build : & Build ,
164
- ) {
164
+ ) -> Option < PathBuf > {
165
165
match & * target. triple {
166
166
// When compiling for android we may have the NDK configured in the
167
167
// config.toml in which case we look there. Otherwise the default
168
168
// compiler already takes into account the triple in question.
169
- t if t. contains ( "android" ) => {
170
- if let Some ( ndk ) = config . and_then ( |c| c . ndk . as_ref ( ) ) {
171
- cfg . compiler ( ndk_compiler ( compiler , & * target . triple , ndk ) ) ;
172
- }
173
- }
169
+ t if t. contains ( "android" ) => build
170
+ . config
171
+ . android_ndk
172
+ . as_ref ( )
173
+ . map ( |ndk| ndk_compiler ( compiler , & * target . triple , ndk ) ) ,
174
174
175
175
// The default gcc version from OpenBSD may be too old, try using egcc,
176
176
// which is a gcc version from ports, if this is the case.
177
177
t if t. contains ( "openbsd" ) => {
178
178
let c = cfg. get_compiler ( ) ;
179
179
let gnu_compiler = compiler. gcc ( ) ;
180
180
if !c. path ( ) . ends_with ( gnu_compiler) {
181
- return ;
181
+ return None ;
182
182
}
183
183
184
184
let output = output ( c. to_command ( ) . arg ( "--version" ) ) ;
185
- let i = match output. find ( " 4." ) {
186
- Some ( i) => i,
187
- None => return ,
188
- } ;
185
+ let i = output. find ( " 4." ) ?;
189
186
match output[ i + 3 ..] . chars ( ) . next ( ) . unwrap ( ) {
190
187
'0' ..='6' => { }
191
- _ => return ,
188
+ _ => return None ,
192
189
}
193
190
let alternative = format ! ( "e{}" , gnu_compiler) ;
194
191
if Command :: new ( & alternative) . output ( ) . is_ok ( ) {
195
- cfg. compiler ( alternative) ;
192
+ Some ( PathBuf :: from ( alternative) )
193
+ } else {
194
+ None
196
195
}
197
196
}
198
197
199
198
"mips-unknown-linux-musl" => {
200
199
if cfg. get_compiler ( ) . path ( ) . to_str ( ) == Some ( "gcc" ) {
201
- cfg. compiler ( "mips-linux-musl-gcc" ) ;
200
+ Some ( PathBuf :: from ( "mips-linux-musl-gcc" ) )
201
+ } else {
202
+ None
202
203
}
203
204
}
204
205
"mipsel-unknown-linux-musl" => {
205
206
if cfg. get_compiler ( ) . path ( ) . to_str ( ) == Some ( "gcc" ) {
206
- cfg. compiler ( "mipsel-linux-musl-gcc" ) ;
207
+ Some ( PathBuf :: from ( "mipsel-linux-musl-gcc" ) )
208
+ } else {
209
+ None
207
210
}
208
211
}
209
212
210
213
t if t. contains ( "musl" ) => {
211
214
if let Some ( root) = build. musl_root ( target) {
212
215
let guess = root. join ( "bin/musl-gcc" ) ;
213
- if guess. exists ( ) {
214
- cfg . compiler ( guess ) ;
215
- }
216
+ if guess. exists ( ) { Some ( guess ) } else { None }
217
+ } else {
218
+ None
216
219
}
217
220
}
218
221
219
- _ => { }
222
+ _ => None ,
220
223
}
221
224
}
222
225
@@ -237,7 +240,18 @@ pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> Path
237
240
let api_level =
238
241
if triple. contains ( "aarch64" ) || triple. contains ( "x86_64" ) { "21" } else { "19" } ;
239
242
let compiler = format ! ( "{}{}-{}" , triple_translated, api_level, compiler. clang( ) ) ;
240
- ndk. join ( "bin" ) . join ( compiler)
243
+ let host_tag = if cfg ! ( target_os = "macos" ) {
244
+ // The NDK uses universal binaries, so this is correct even on ARM.
245
+ "darwin-x86_64"
246
+ } else if cfg ! ( target_os = "windows" ) {
247
+ "windows-x86_64"
248
+ } else {
249
+ // NDK r25b only has official releases for macOS, Windows and Linux.
250
+ // Try the Linux directory everywhere else, on the assumption that the OS has an
251
+ // emulation layer that can cope (e.g. BSDs).
252
+ "linux-x86_64"
253
+ } ;
254
+ ndk. join ( "toolchains" ) . join ( "llvm" ) . join ( "prebuilt" ) . join ( host_tag) . join ( "bin" ) . join ( compiler)
241
255
}
242
256
243
257
/// The target programming language for a native compiler.
0 commit comments