Skip to content

Commit 5f89f90

Browse files
authored
Allow per-target cmake toolchain (#120)
* Allow per-target cmake toolchain * Make CMAKE, CMAKE_PREFIX_PATH and CMAKE_GENERATOR per-target env vars * Fix warnings in 1.51.0 * Print when accessing per-target env vars * Avoid mutex around env_cache
1 parent 66e9978 commit 5f89f90

File tree

1 file changed

+44
-9
lines changed

1 file changed

+44
-9
lines changed

src/lib.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
extern crate cc;
4848

49+
use std::collections::HashMap;
4950
use std::env;
5051
use std::ffi::{OsStr, OsString};
5152
use 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

Comments
 (0)