1use crate::BuildScript;
5use crate::{
6 cargo_rustc_link_lib as cargo_rustc_link_lib_,
7 cargo_rustc_link_search as cargo_rustc_link_search_,
8};
9use once_cell::sync::Lazy;
10use std::path::PathBuf;
11use std::sync::{LockResult, Mutex, MutexGuard};
12
13static BUILD_SCRIPT: Lazy<Mutex<BuildScript>> = Lazy::new(|| {
14 let mut build_script = BuildScript::default();
15 build_script.now();
16
17 Mutex::new(build_script)
18});
19
20fn lock_mutex<T>(lock: LockResult<MutexGuard<T>>) -> MutexGuard<T> {
22 lock.expect("mutex is poisoned")
23}
24
25fn build_script() -> MutexGuard<'static, BuildScript<'static>> {
28 lock_mutex(BUILD_SCRIPT.lock())
29}
30
31pub fn cargo_rerun_if_changed(path: impl Into<PathBuf>) {
33 build_script().cargo_rerun_if_changed(path.into());
34}
35
36pub fn cargo_rerun_if_env_changed(var: impl Into<String>) {
38 build_script().cargo_rerun_if_env_changed(&var.into());
39}
40
41pub fn cargo_rustc_link_lib(name: impl Into<String>) {
43 build_script().cargo_rustc_link_lib(None, &name.into());
44}
45
46pub fn cargo_rustc_link_lib_mapping(kind: cargo_rustc_link_lib_::Kind, name: impl Into<String>) {
48 build_script().cargo_rustc_link_lib(kind.into(), &name.into());
49}
50
51pub fn cargo_rustc_link_search(path: impl Into<PathBuf>) {
53 build_script().cargo_rustc_link_search(None, path.into());
54}
55
56pub fn cargo_rustc_link_search_mapping(
58 kind: cargo_rustc_link_search_::Kind,
59 path: impl Into<PathBuf>,
60) {
61 build_script().cargo_rustc_link_search(kind.into(), path.into());
62}
63
64pub fn cargo_rustc_flags(flags: impl Into<String>) {
66 build_script().cargo_rustc_flags(&flags.into());
67}
68
69pub fn cargo_rustc_cfg(key: impl Into<String>) {
71 build_script().cargo_rustc_cfg(&key.into(), None);
72}
73
74pub fn cargo_rustc_cfg_mapping(key: impl Into<String>, value: impl Into<String>) {
76 build_script().cargo_rustc_cfg(&key.into(), Some(&value.into()));
77}
78
79pub fn cargo_rustc_env(var: impl Into<String>, value: impl Into<String>) {
81 build_script().cargo_rustc_env(&var.into(), &value.into());
82}
83
84pub fn cargo_rustc_cdylib_link_arg(flag: impl Into<String>) {
87 build_script().cargo_rustc_cdylib_link_arg(&flag.into());
88}
89
90pub fn cargo_warning(message: impl Into<String>) {
92 build_script().cargo_warning(&message.into());
93}
94
95pub fn cargo_mapping(key: impl Into<String>, value: impl Into<String>) {
97 build_script().cargo_mapping(&key.into(), &value.into());
98}
99
100#[cfg(test)]
101mod tests {
102 use gag::BufferRedirect;
103 use serial_test::serial;
104 use std::io::Read;
105
106 fn test(func: impl Fn(), expected: &str) -> bool {
107 let mut output = String::new();
108 let mut buffer = BufferRedirect::stdout().unwrap();
109 func();
110 buffer.read_to_string(&mut output).unwrap();
111
112 output.contains(expected)
113 }
114
115 macro_rules! new_test {
116 ($name:ident, $func:expr, $expected:literal) => {
117 #[test]
118 #[serial]
119 fn $name() {
120 assert!(test($func, $expected))
121 }
122 };
123 }
124
125 new_test!(
126 test_cargo_rerun_if_changed,
127 || super::cargo_rerun_if_changed("path"),
128 "cargo:rerun-if-changed=path"
129 );
130 new_test!(
131 test_cargo_rerun_if_env_changed,
132 || super::cargo_rerun_if_env_changed("var"),
133 "cargo:rerun-if-env-changed=var"
134 );
135 new_test!(
136 test_cargo_rustc_link_lib,
137 || super::cargo_rustc_link_lib("name"),
138 "cargo:rustc-link-lib=name"
139 );
140
141 #[test]
142 #[serial]
143 fn test_cargo_rustc_link_lib_mapping() {
144 use crate::cargo_rustc_link_lib::Kind;
145
146 let kinds = [Kind::Framework, Kind::Static, Kind::DynamicLibrary];
147
148 for &kind in kinds.iter() {
149 assert!(test(
150 || super::cargo_rustc_link_lib_mapping(kind, "name"),
151 &format!("cargo:rustc-link-lib={}=name", {
152 let kind: String = kind.into();
153 kind
154 })
155 ))
156 }
157 }
158
159 new_test!(
160 test_cargo_rustc_link_search,
161 || super::cargo_rustc_link_search("path"),
162 "cargo:rustc-link-search=path"
163 );
164
165 #[test]
166 #[serial]
167 fn test_cargo_rustc_link_search_mapping() {
168 use crate::cargo_rustc_link_search::Kind;
169
170 let kinds = [
171 Kind::Framework,
172 Kind::All,
173 Kind::Crate,
174 Kind::Dependency,
175 Kind::Native,
176 ];
177
178 for &kind in kinds.iter() {
179 assert!(test(
180 || super::cargo_rustc_link_search_mapping(kind, "path"),
181 &format!("cargo:rustc-link-search={}=path", {
182 let kind: String = kind.into();
183 kind
184 })
185 ))
186 }
187 }
188
189 new_test!(
190 test_cargo_rustc_flags,
191 || super::cargo_rustc_flags("flags"),
192 "cargo:rustc-flags=flags"
193 );
194 new_test!(
195 test_cargo_rustc_cfg,
196 || super::cargo_rustc_cfg("key"),
197 "cargo:rustc-cfg=key"
198 );
199 new_test!(
200 test_cargo_rustc_cfg_mapping,
201 || super::cargo_rustc_cfg_mapping("key", "value"),
202 "cargo:rustc-cfg=key=\"value\""
203 );
204 new_test!(
205 test_cargo_rustc_env,
206 || super::cargo_rustc_env("var", "value"),
207 "cargo:rustc-env=var=value"
208 );
209 new_test!(
210 test_cargo_rustc_cdylib_link_arg,
211 || super::cargo_rustc_cdylib_link_arg("flag"),
212 "cargo:rustc-cdylib-link-arg=flag"
213 );
214 new_test!(
215 test_cargo_warning,
216 || super::cargo_warning("message"),
217 "cargo:warning=message"
218 );
219 new_test!(
220 test_cargo_mapping,
221 || super::cargo_mapping("key", "value"),
222 "cargo:key=value"
223 );
224}