@@ -26,7 +26,7 @@ use std::path::{Path, PathBuf};
2626use  std:: process:: Command ; 
2727use  std:: { env,  iter} ; 
2828
29- use  crate :: core:: config:: { Target ,   TargetSelection } ; 
29+ use  crate :: core:: config:: TargetSelection ; 
3030use  crate :: utils:: helpers:: output; 
3131use  crate :: { Build ,  CLang ,  GitRepo } ; 
3232
@@ -107,10 +107,11 @@ pub fn find(build: &Build) {
107107pub  fn  find_target ( build :  & Build ,  target :  TargetSelection )  { 
108108    let  mut  cfg = new_cc_build ( build,  target) ; 
109109    let  config = build. config . target_config . get ( & target) ; 
110-     if  let  Some ( cc)  = config. and_then ( |c| c. cc . as_ref ( ) )  { 
110+     if  let  Some ( cc)  = config
111+         . and_then ( |c| c. cc . clone ( ) ) 
112+         . or_else ( || default_compiler ( & mut  cfg,  Language :: C ,  target,  build) ) 
113+     { 
111114        cfg. compiler ( cc) ; 
112-     }  else  { 
113-         set_compiler ( & mut  cfg,  Language :: C ,  target,  config,  build) ; 
114115    } 
115116
116117    let  compiler = cfg. get_compiler ( ) ; 
@@ -127,12 +128,12 @@ pub fn find_target(build: &Build, target: TargetSelection) {
127128    // We'll need one anyways if the target triple is also a host triple 
128129    let  mut  cfg = new_cc_build ( build,  target) ; 
129130    cfg. cpp ( true ) ; 
130-     let  cxx_configured = if  let  Some ( cxx)  = config. and_then ( |c| c. cxx . as_ref ( ) )  { 
131+     let  cxx_configured = if  let  Some ( cxx)  = config
132+         . and_then ( |c| c. cxx . clone ( ) ) 
133+         . or_else ( || default_compiler ( & mut  cfg,  Language :: CPlusPlus ,  target,  build) ) 
134+     { 
131135        cfg. compiler ( cxx) ; 
132136        true 
133-     }  else  if  build. hosts . contains ( & target)  || build. build  == target { 
134-         set_compiler ( & mut  cfg,  Language :: CPlusPlus ,  target,  config,  build) ; 
135-         true 
136137    }  else  { 
137138        // Use an auto-detected compiler (or one configured via `CXX_target_triple` env vars). 
138139        cfg. try_get_compiler ( ) . is_ok ( ) 
@@ -161,68 +162,70 @@ pub fn find_target(build: &Build, target: TargetSelection) {
161162    } 
162163} 
163164
164- fn  set_compiler ( 
165+ fn  default_compiler ( 
165166    cfg :  & mut  cc:: Build , 
166167    compiler :  Language , 
167168    target :  TargetSelection , 
168-     config :  Option < & Target > , 
169169    build :  & Build , 
170- )  { 
170+ )  ->  Option < PathBuf >   { 
171171    match  & * target. triple  { 
172172        // When compiling for android we may have the NDK configured in the 
173173        // config.toml in which case we look there. Otherwise the default 
174174        // compiler already takes into account the triple in question. 
175-         t if  t. contains ( "android" )  => { 
176-             if   let   Some ( ndk )  = config . and_then ( |c| c . ndk . as_ref ( ) )   { 
177-                 cfg . compiler ( ndk_compiler ( compiler ,   & * target . triple ,  ndk ) ) ; 
178-             } 
179-         } 
175+         t if  t. contains ( "android" )  => build 
176+             . config 
177+             . android_ndk 
178+             . as_ref ( ) 
179+              . map ( |ndk|  ndk_compiler ( compiler ,   & * target . triple ,  ndk ) ) , 
180180
181181        // The default gcc version from OpenBSD may be too old, try using egcc, 
182182        // which is a gcc version from ports, if this is the case. 
183183        t if  t. contains ( "openbsd" )  => { 
184184            let  c = cfg. get_compiler ( ) ; 
185185            let  gnu_compiler = compiler. gcc ( ) ; 
186186            if  !c. path ( ) . ends_with ( gnu_compiler)  { 
187-                 return ; 
187+                 return   None ; 
188188            } 
189189
190190            let  output = output ( c. to_command ( ) . arg ( "--version" ) ) ; 
191-             let  i = match  output. find ( " 4." )  { 
192-                 Some ( i)  => i, 
193-                 None  => return , 
194-             } ; 
191+             let  i = output. find ( " 4." ) ?; 
195192            match  output[ i + 3 ..] . chars ( ) . next ( ) . unwrap ( )  { 
196193                '0' ..='6'  => { } 
197-                 _ => return , 
194+                 _ => return   None , 
198195            } 
199196            let  alternative = format ! ( "e{gnu_compiler}" ) ; 
200197            if  Command :: new ( & alternative) . output ( ) . is_ok ( )  { 
201-                 cfg. compiler ( alternative) ; 
198+                 Some ( PathBuf :: from ( alternative) ) 
199+             }  else  { 
200+                 None 
202201            } 
203202        } 
204203
205-         "mips-unknown-linux-musl"  => { 
204+         "mips-unknown-linux-musl"  if  compiler ==  Language :: C   => { 
206205            if  cfg. get_compiler ( ) . path ( ) . to_str ( )  == Some ( "gcc" )  { 
207-                 cfg. compiler ( "mips-linux-musl-gcc" ) ; 
206+                 Some ( PathBuf :: from ( "mips-linux-musl-gcc" ) ) 
207+             }  else  { 
208+                 None 
208209            } 
209210        } 
210-         "mipsel-unknown-linux-musl"  => { 
211+         "mipsel-unknown-linux-musl"  if  compiler ==  Language :: C   => { 
211212            if  cfg. get_compiler ( ) . path ( ) . to_str ( )  == Some ( "gcc" )  { 
212-                 cfg. compiler ( "mipsel-linux-musl-gcc" ) ; 
213+                 Some ( PathBuf :: from ( "mipsel-linux-musl-gcc" ) ) 
214+             }  else  { 
215+                 None 
213216            } 
214217        } 
215218
216-         t if  t. contains ( "musl" )  => { 
219+         t if  t. contains ( "musl" )  && compiler ==  Language :: C   => { 
217220            if  let  Some ( root)  = build. musl_root ( target)  { 
218221                let  guess = root. join ( "bin/musl-gcc" ) ; 
219-                 if  guess. exists ( )  { 
220-                     cfg . compiler ( guess ) ; 
221-                 } 
222+                 if  guess. exists ( )  {   Some ( guess )   }   else   {   None   } 
223+             }   else   { 
224+                 None 
222225            } 
223226        } 
224227
225-         _ => { } 
228+         _ => None , 
226229    } 
227230} 
228231
@@ -243,10 +246,22 @@ pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> Path
243246    let  api_level =
244247        if  triple. contains ( "aarch64" )  || triple. contains ( "x86_64" )  {  "21"  }  else  {  "19"  } ; 
245248    let  compiler = format ! ( "{}{}-{}" ,  triple_translated,  api_level,  compiler. clang( ) ) ; 
246-     ndk. join ( "bin" ) . join ( compiler) 
249+     let  host_tag = if  cfg ! ( target_os = "macos" )  { 
250+         // The NDK uses universal binaries, so this is correct even on ARM. 
251+         "darwin-x86_64" 
252+     }  else  if  cfg ! ( target_os = "windows" )  { 
253+         "windows-x86_64" 
254+     }  else  { 
255+         // NDK r25b only has official releases for macOS, Windows and Linux. 
256+         // Try the Linux directory everywhere else, on the assumption that the OS has an 
257+         // emulation layer that can cope (e.g. BSDs). 
258+         "linux-x86_64" 
259+     } ; 
260+     ndk. join ( "toolchains" ) . join ( "llvm" ) . join ( "prebuilt" ) . join ( host_tag) . join ( "bin" ) . join ( compiler) 
247261} 
248262
249263/// The target programming language for a native compiler. 
264+ #[ derive( PartialEq ) ]  
250265pub ( crate )  enum  Language  { 
251266    /// The compiler is targeting C. 
252267     C , 
0 commit comments