2016-09-27 23:13:17 -07:00
|
|
|
macro_rules! warn {
|
|
|
|
($($arg:tt)*) => {{
|
|
|
|
extern crate std;
|
|
|
|
use std::io::prelude::*;
|
|
|
|
let _ = writeln!(&mut std::io::stderr(), $($arg)*);
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
macro_rules! die {
|
|
|
|
($($arg:tt)*) => {{
|
|
|
|
extern crate std;
|
|
|
|
warn!($($arg)*);
|
|
|
|
std::process::exit(-1)
|
|
|
|
}};
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
|
|
enum Make {
|
|
|
|
GNU, // GNU Make installed as `gmake`
|
|
|
|
GNUStealthy, // GNU Make installed as `make`
|
|
|
|
Other, // Another make installed as `make`
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
impl Make {
|
|
|
|
fn command(self) -> &'static str {
|
|
|
|
if self == Make::GNU {
|
|
|
|
"gmake"
|
|
|
|
} else {
|
|
|
|
"make"
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
fn gnu(self) -> bool {
|
|
|
|
self != Make::Other
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
fn status(command: &mut std::process::Command) -> std::io::Result<std::process::ExitStatus> {
|
|
|
|
command
|
|
|
|
.stdin(std::process::Stdio::null())
|
|
|
|
.stdout(std::process::Stdio::null())
|
|
|
|
.stderr(std::process::Stdio::null())
|
|
|
|
.status()
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
fn which_make() -> Option<Make> {
|
|
|
|
// check `gmake`
|
|
|
|
let result = status(std::process::Command::new("gmake").arg("-v"));
|
|
|
|
|
|
|
|
if let Ok(exit_status) = result {
|
|
|
|
if exit_status.success() {
|
|
|
|
return Some(Make::GNU);
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
2016-09-27 22:49:17 -07:00
|
|
|
|
|
|
|
// check `make`. pass gmake specific flags to see if it's actually gmake
|
|
|
|
let result = status(std::process::Command::new("make").arg("-v").arg("--always-make"));
|
|
|
|
|
|
|
|
if let Ok(exit_status) = result {
|
|
|
|
return if exit_status.success() {
|
|
|
|
Some(Make::GNUStealthy)
|
|
|
|
} else {
|
|
|
|
Some(Make::Other)
|
|
|
|
};
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
return None;
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2016-09-27 22:49:17 -07:00
|
|
|
let make = match which_make() {
|
|
|
|
None => die!("Could not execute `make` or `gmake`."),
|
|
|
|
Some(make) => make,
|
|
|
|
};
|
2016-06-16 17:13:43 -07:00
|
|
|
|
2016-09-27 23:25:06 -07:00
|
|
|
let mut justfile = "justfile";
|
|
|
|
|
2016-06-16 17:13:43 -07:00
|
|
|
loop {
|
2016-09-27 22:49:17 -07:00
|
|
|
match std::fs::metadata("justfile") {
|
|
|
|
Ok(metadata) => if metadata.is_file() { break; },
|
2016-09-28 00:02:18 -07:00
|
|
|
Err(error) => {
|
|
|
|
if error.kind() != std::io::ErrorKind::NotFound {
|
|
|
|
die!("Error fetching justfile metadata: {}", error)
|
|
|
|
}
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
2016-09-27 22:49:17 -07:00
|
|
|
|
2016-09-27 23:25:06 -07:00
|
|
|
match std::fs::metadata("Justfile") {
|
|
|
|
Ok(metadata) => if metadata.is_file() {
|
|
|
|
justfile = "Justfile";
|
|
|
|
break;
|
|
|
|
},
|
2016-09-28 00:02:18 -07:00
|
|
|
Err(error) => {
|
|
|
|
if error.kind() != std::io::ErrorKind::NotFound {
|
|
|
|
die!("Error fetching Justfile metadata: {}", error)
|
|
|
|
};
|
|
|
|
}
|
2016-09-27 23:25:06 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
match std::env::current_dir() {
|
2016-09-28 13:20:49 -07:00
|
|
|
Ok(pathbuf) => if pathbuf.as_os_str() == "/" { die!("No justfile found."); },
|
2016-09-27 22:49:17 -07:00
|
|
|
Err(error) => die!("Error getting current dir: {}", error),
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
if let Err(error) = std::env::set_current_dir("..") {
|
|
|
|
die!("Error changing directory: {}", error);
|
|
|
|
}
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
|
|
|
|
let recipes: Vec<String> = std::env::args().skip(1).take_while(|arg| arg != "--").collect();
|
|
|
|
let arguments: Vec<String> = std::env::args().skip(1 + recipes.len() + 1).collect();
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
for (i, argument) in arguments.into_iter().enumerate() {
|
|
|
|
std::env::set_var(format!("ARG{}", i), argument);
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
let mut command = std::process::Command::new(make.command());
|
|
|
|
|
|
|
|
command.arg("MAKEFLAGS=");
|
|
|
|
|
|
|
|
if make.gnu() {
|
|
|
|
command.arg("--always-make").arg("--no-print-directory");
|
|
|
|
}
|
|
|
|
|
2016-09-27 23:25:06 -07:00
|
|
|
command.arg("-f").arg(justfile);
|
2016-09-27 22:49:17 -07:00
|
|
|
|
|
|
|
for recipe in recipes {
|
|
|
|
command.arg(recipe);
|
|
|
|
}
|
|
|
|
|
|
|
|
match command.status() {
|
|
|
|
Err(error) => die!("Failed to execute `{:?}`: {}", command, error),
|
|
|
|
Ok(exit_status) => match exit_status.code() {
|
|
|
|
Some(code) => std::process::exit(code),
|
|
|
|
None => std::process::exit(-1),
|
|
|
|
}
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|