use std::env; use std::ffi::OsString; use std::path::PathBuf; pub const BUILD_DIR: &'static str = "build"; pub const ERRNO_GENERATOR_FILENAME: &'static str = "errno.c"; pub const ERRNO_GENERATOR_OUTPUT_FILENAME: &'static str = "errno.gen"; pub const GENERATED_ERRNO_FILENAME: &'static str = "errno_values.rs"; fn determine_base_dir() -> PathBuf { // Get the cargo manifest directory. match ::std::env::var_os("CARGO_MANIFEST_DIR") { Some(dir) => { PathBuf::from(dir) } None => { PathBuf::new() } } } fn determine_output_dir() -> PathBuf { let output_dir: PathBuf; // Get the output directory for the build. match ::std::env::var_os("OUT_DIR") { Some(dir) => { output_dir = PathBuf::from(dir); } None => { // Try to just get the current directory. match env::current_dir() { Ok(dir) => { output_dir = PathBuf::from(dir); } Err(error) => { // Then just default to "". println!("WARN: {}", error); output_dir = PathBuf::new(); } } } } output_dir } fn determine_build_dir() -> PathBuf { let mut build_dir: PathBuf; build_dir = determine_base_dir(); build_dir.push(BUILD_DIR); build_dir } fn determine_c_compiler() -> OsString { match ::std::env::var_os("CC") { Some(compiler) => { OsString::from(compiler) } None => { OsString::from("gcc") } } } fn build_output_file(filename: &str) -> PathBuf { let mut output_dir: PathBuf; output_dir = determine_output_dir(); output_dir.push(filename); output_dir } fn build_src_file(filename: &str) -> PathBuf { let mut build_dir: PathBuf; build_dir = determine_build_dir(); build_dir.push(filename); build_dir } fn compile(src_files: &[PathBuf], output_name: &str) -> PathBuf { let c_compiler: OsString; let output_file: PathBuf; let mut initial_command: ::std::process::Command; let command: &mut ::std::process::Command; let last_command: &mut ::std::process::Command; let final_command: &mut ::std::process::Command; c_compiler = determine_c_compiler(); output_file = build_output_file(output_name); initial_command = ::std::process::Command::new(c_compiler); command = initial_command.args(src_files); last_command = command.arg("-o"); final_command = last_command.arg(output_file.clone()); match final_command.output() { Ok(output) => { if output.status.success() == false { println!("ERROR: {:?}", output); panic!(); } } Err(error) => { println!("ERROR: {}", error); panic!(); } } output_file } fn run(executable: PathBuf, args: &[PathBuf]) { let mut initial_command: ::std::process::Command; let final_command: &mut ::std::process::Command; initial_command = ::std::process::Command::new(executable); final_command = initial_command.args(args); match final_command.output() { Ok(output) => { if output.status.success() == false { println!("ERROR: {:?}", output); panic!(); } } Err(error) => { println!("ERROR: {}", error); panic!(); } } } fn compile_and_run(output_name: &str, src_files: &[PathBuf], args: &[PathBuf]) { let executable: PathBuf; executable = compile(src_files, output_name); run(executable, args); } pub fn main() { let _gen_file: PathBuf; let errno_file: PathBuf; let gen_errno_file: PathBuf; errno_file = build_src_file(ERRNO_GENERATOR_FILENAME); _gen_file = build_output_file(ERRNO_GENERATOR_OUTPUT_FILENAME); gen_errno_file = build_output_file(GENERATED_ERRNO_FILENAME); compile_and_run(ERRNO_GENERATOR_OUTPUT_FILENAME, &[errno_file], &[gen_errno_file]); }