use std::{ collections::HashMap, env::{var, var_os}, fs::{File, create_dir, exists, read_to_string}, io::{Read, Write}, os::unix::process::CommandExt, process::Command, }; fn parse(data: &str) -> HashMap { let mut out = HashMap::new(); let mut parse_one = |key: &str, value: String, fallback| match key { "metadata" => { let (left, right) = value .split_once('=') .expect("missing '=' for cargo::metadata"); out.insert(left.to_string(), right.to_string()); } _ if fallback => { out.insert(key.to_string(), value); } _ => {} }; for line in data.lines() { if let Some(data) = line.strip_prefix("cargo::") { let (key, value) = data.split_once('=').expect("missing '=' on cargo:: line"); parse_one(key, value.to_string(), false); } else if let Some(data) = line.strip_prefix("cargo:") { let (key, value) = data.split_once('=').expect("missing '=' on cargo: line"); parse_one(key, value.to_string(), true); } } out } fn main() { create_dir(var_os("OUT_DIR").unwrap()).unwrap(); create_dir(var_os("CARGO_TARGET_DIR").unwrap()).unwrap(); let mut f = File::create(var_os("out").unwrap()).unwrap(); writeln!(&mut f, "zilch: OUT_DIR={:?}", var("OUT_DIR").unwrap()).unwrap(); writeln!( &mut f, "zilch: CARGO_TARGET_DIR={:?}", var("CARGO_TARGET_DIR").unwrap() ) .unwrap(); let mut cmd = Command::new(var_os("script").unwrap()); cmd.stdout(f).current_dir(var_os("cwd").unwrap()); if let Ok(inherit) = var("_zilch_links") { if !inherit.is_empty() { for v in inherit.split('!') { let (path, name) = v.split_once(':').unwrap(); let mut file = File::open(path).unwrap(); let mut data = String::new(); file.read_to_string(&mut data).unwrap(); let data = parse(&data); for (k, v) in data { let mut name = format!("DEP_{}_{}", name, k); name.make_ascii_uppercase(); cmd.env(name.replace('-', "_"), v); } } } } let mut pkg_config_path = Vec::new(); if let Ok(paths) = var("_zilch_pkgconfig") { if !paths.is_empty() { let mut paths_to_check = Vec::new(); for path in paths.split(':') { paths_to_check.push(path.to_string()); } while let Some(path) = paths_to_check.pop() { let pkgconfig_path = format!("{}/lib/pkgconfig", path); if exists(&pkgconfig_path).ok() == Some(true) && !pkg_config_path.contains(&pkgconfig_path) { pkg_config_path.push(pkgconfig_path); } let pkgconfig_path = format!("{}/share/pkgconfig", path); if exists(&pkgconfig_path).ok() == Some(true) && !pkg_config_path.contains(&pkgconfig_path) { pkg_config_path.push(pkgconfig_path); } if let Ok(file) = read_to_string(format!("{}/nix-support/propagated-build-inputs", path)) { for path in file.split(' ') { if !path.is_empty() { paths_to_check.push(path.to_string()); } } } } } } cmd.env("PKG_CONFIG_PATH", pkg_config_path.join(":")); let status = cmd.status().unwrap(); if !status.success() { panic!( "Failed to execute.\nstdout: {}", std::fs::read_to_string(var_os("out").unwrap()).unwrap() ); } }