4646
4747extern crate cc;
4848
49+ use std:: collections:: HashMap ;
4950use std:: env;
5051use std:: ffi:: { OsStr , OsString } ;
5152use std:: fs:: { self , File } ;
@@ -80,6 +81,7 @@ pub struct Config {
8081 pic : Option < bool > ,
8182 c_cfg : Option < cc:: Build > ,
8283 cxx_cfg : Option < cc:: Build > ,
84+ env_cache : HashMap < String , Option < OsString > > ,
8385}
8486
8587/// Builds the native library rooted at `path` with the default cmake options.
@@ -202,6 +204,7 @@ impl Config {
202204 pic : None ,
203205 c_cfg : None ,
204206 cxx_cfg : None ,
207+ env_cache : HashMap :: new ( ) ,
205208 }
206209 }
207210
@@ -422,13 +425,13 @@ impl Config {
422425 t
423426 }
424427 } ;
428+ let host = self . host . clone ( ) . unwrap_or_else ( || getenv_unwrap ( "HOST" ) ) ;
425429
426- let mut generator = self
430+ let generator = self
427431 . generator
428432 . clone ( )
429- . or_else ( || std :: env :: var_os ( "CMAKE_GENERATOR" ) ) ;
433+ . or_else ( || self . getenv_target_os ( "CMAKE_GENERATOR" ) ) ;
430434
431- let host = self . host . clone ( ) . unwrap_or_else ( || getenv_unwrap ( "HOST" ) ) ;
432435 let msvc = target. contains ( "msvc" ) ;
433436 let ndk = self . uses_android_ndk ( ) ;
434437 let mut c_cfg = self . c_cfg . clone ( ) . unwrap_or_default ( ) ;
@@ -483,12 +486,16 @@ impl Config {
483486 cmake_prefix_path. push ( PathBuf :: from ( root) ) ;
484487 }
485488 }
486- let system_prefix = env:: var_os ( "CMAKE_PREFIX_PATH" ) . unwrap_or ( OsString :: new ( ) ) ;
489+ let system_prefix = self
490+ . getenv_target_os ( "CMAKE_PREFIX_PATH" )
491+ . unwrap_or ( OsString :: new ( ) ) ;
487492 cmake_prefix_path. extend ( env:: split_paths ( & system_prefix) . map ( |s| s. to_owned ( ) ) ) ;
488493 let cmake_prefix_path = env:: join_paths ( & cmake_prefix_path) . unwrap ( ) ;
489494
490495 // Build up the first cmake command to build the build system.
491- let executable = env:: var ( "CMAKE" ) . unwrap_or ( "cmake" . to_owned ( ) ) ;
496+ let executable = self
497+ . getenv_target_os ( "CMAKE" )
498+ . unwrap_or ( OsString :: from ( "cmake" ) ) ;
492499 let mut cmd = Command :: new ( & executable) ;
493500
494501 if self . verbose_cmake {
@@ -607,7 +614,7 @@ impl Config {
607614 if let Some ( ref generator) = generator {
608615 cmd. arg ( "-G" ) . arg ( generator) ;
609616 }
610- let profile = self . get_profile ( ) ;
617+ let profile = self . get_profile ( ) . to_string ( ) ;
611618 for & ( ref k, ref v) in & self . defines {
612619 let mut os = OsString :: from ( "-D" ) ;
613620 os. push ( k) ;
@@ -735,8 +742,10 @@ impl Config {
735742 }
736743
737744 if !self . defined ( "CMAKE_TOOLCHAIN_FILE" ) {
738- if let Ok ( s) = env:: var ( "CMAKE_TOOLCHAIN_FILE" ) {
739- cmd. arg ( & format ! ( "-DCMAKE_TOOLCHAIN_FILE={}" , s) ) ;
745+ if let Some ( s) = self . getenv_target_os ( "CMAKE_TOOLCHAIN_FILE" ) {
746+ let mut cmake_toolchain_file = OsString :: from ( "-DCMAKE_TOOLCHAIN_FILE=" ) ;
747+ cmake_toolchain_file. push ( & s) ;
748+ cmd. arg ( cmake_toolchain_file) ;
740749 }
741750 }
742751
@@ -823,6 +832,32 @@ impl Config {
823832 return dst;
824833 }
825834
835+ fn getenv_os ( & mut self , v : & str ) -> Option < OsString > {
836+ if let Some ( val) = self . env_cache . get ( v) {
837+ return val. clone ( ) ;
838+ }
839+ let r = env:: var_os ( v) ;
840+ println ! ( "{} = {:?}" , v, r) ;
841+ self . env_cache . insert ( v. to_string ( ) , r. clone ( ) ) ;
842+ r
843+ }
844+
845+ /// Gets a target-specific environment variable.
846+ fn getenv_target_os ( & mut self , var_base : & str ) -> Option < OsString > {
847+ let host = self . host . clone ( ) . unwrap_or_else ( || getenv_unwrap ( "HOST" ) ) ;
848+ let target = self
849+ . target
850+ . clone ( )
851+ . unwrap_or_else ( || getenv_unwrap ( "TARGET" ) ) ;
852+
853+ let kind = if host == target { "HOST" } else { "TARGET" } ;
854+ let target_u = target. replace ( "-" , "_" ) ;
855+ self . getenv_os ( & format ! ( "{}_{}" , var_base, target) )
856+ . or_else ( || self . getenv_os ( & format ! ( "{}_{}" , var_base, target_u) ) )
857+ . or_else ( || self . getenv_os ( & format ! ( "{}_{}" , kind, var_base) ) )
858+ . or_else ( || self . getenv_os ( var_base) )
859+ }
860+
826861 fn visual_studio_generator ( & self , target : & str ) -> String {
827862 use cc:: windows_registry:: { find_vs_version, VsVers } ;
828863
@@ -836,7 +871,7 @@ impl Config {
836871 doesn't know how to generate cmake files for it, \
837872 can the `cmake` crate be updated?"
838873 ) ,
839- Err ( msg) => panic ! ( msg) ,
874+ Err ( msg) => panic ! ( "{}" , msg) ,
840875 } ;
841876 if [ "i686" , "x86_64" , "thumbv7a" , "aarch64" ]
842877 . iter ( )
0 commit comments