use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/raw/prefs.c");
println!("cargo:rerun-if-changed=src/raw/prefs.h");
let out_dir = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR is not set"));
let prefs_object_path = out_dir.join("prefs.o");
let library_path = out_dir.join("libprefs_shim.a");
run(Command::new("xcrun")
.arg("clang")
.arg("-c")
.arg("src/raw/prefs.c")
.arg("-o")
.arg(&prefs_object_path)
.arg("-I")
.arg("shim")
.arg("-Wall")
.arg("-Wextra"));
run(Command::new("xcrun")
.arg("libtool")
.arg("-static")
.arg("-o")
.arg(&library_path)
.arg(&prefs_object_path));
println!("cargo:rustc-link-search=native={}", out_dir.display());
println!("cargo:rustc-link-lib=static=prefs_shim");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
}
fn run(command: &mut Command) {
let rendered = render_command(command);
let status = command
.status()
.unwrap_or_else(|error| panic!("failed to run `{rendered}`: {error}"));
assert!(
status.success(),
"command `{rendered}` exited with status {status}"
);
}
fn render_command(command: &Command) -> String {
let mut rendered = command.get_program().to_string_lossy().into_owned();
for argument in command.get_args() {
rendered.push(' ');
rendered.push_str(&shell_escape(argument.as_ref()));
}
rendered
}
fn shell_escape(argument: &Path) -> String {
let rendered = argument.to_string_lossy();
if rendered
.chars()
.all(|character| character.is_ascii_alphanumeric() || "/._-".contains(character))
{
rendered.into_owned()
} else {
format!("{rendered:?}")
}
}