1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::{Defines, RubyVersion};
use std::{collections::HashMap, rc::Rc};
const ENV_PREFIX: &str = "DEP_RB_";
const RBCONFIG_PREFIX: &str = "RBCONFIG_";
const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_";
#[derive(Debug, Clone)]
pub struct RbEnv {
defines: Defines,
vars: Rc<HashMap<String, String>>,
}
impl RbEnv {
pub fn ruby_version(&self) -> RubyVersion {
RubyVersion::from_raw_environment(&self.vars)
}
pub fn ruby_major_minor(&self) -> (u8, u8) {
self.ruby_version().major_minor()
}
pub fn get_rbconfig_value(&self, key: &str) -> Option<&str> {
self.vars
.get(&format!("{}{}", RBCONFIG_PREFIX, key))
.map(|v| v.as_str())
}
pub fn cargo_features(&self) -> Vec<String> {
let keys = self.vars.keys();
let keys = keys.filter(|k| k.starts_with(CARGO_FEATURE_PREFIX));
let keys = keys.map(|k| k.trim_start_matches(CARGO_FEATURE_PREFIX));
keys.map(|k| k.replace('_', "-").to_lowercase()).collect()
}
pub fn force_link_ruby(self) -> Self {
let libdir = self.vars.get("LIBDIR").expect("DEP_RB_LIBDIR is not set");
let lib = self.vars.get("LIB").expect("DEP_RB_LIB is not set");
println!("cargo:rustc-link-search=native={}", libdir);
println!("cargo:rustc-link-lib={}", lib);
self
}
pub fn encoded_cargo_args(&self) -> Vec<String> {
if let Some(raw_args) = self.vars.get("ENCODED_CARGO_ARGS") {
let lines = raw_args.split('\x1E');
let unescaped = lines.map(|line| line.replace('\x1F', "\n"));
unescaped.collect()
} else {
vec![]
}
}
pub fn is_ruby_static(&self) -> bool {
self.vars
.get("RUBY_STATIC")
.map(|v| v == "true")
.unwrap_or(false)
}
pub fn print_cargo_rustc_cfg(&self) {
self.defines.print_cargo_rustc_cfg();
self.ruby_version().print_cargo_rustc_cfg();
}
pub fn print_encoded_cargo_args(&self) {
for line in self.encoded_cargo_args() {
println!("{}", line);
}
}
pub fn print_cargo_rerun_if_changed(&self) {
for key in self.vars.keys() {
println!("cargo:rerun-if-env-changed={}{}", ENV_PREFIX, key);
}
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=RB_SYS_ENV_DEBUG");
println!("cargo:rerun-if-env-changed=RUBY");
println!("cargo:rerun-if-env-changed=RUBY_VERSION");
}
}
impl Default for RbEnv {
fn default() -> Self {
let vars = std::env::vars();
let vars = vars.filter(|(key, _)| key.starts_with(ENV_PREFIX));
let vars = vars.map(|(key, value)| (key.trim_start_matches(ENV_PREFIX).to_string(), value));
let vars: HashMap<String, String> = vars.collect();
let vars = Rc::new(vars);
let defines = Defines::from_raw_environment(vars.clone());
Self { defines, vars }
}
}