diff --git a/Cargo.toml b/Cargo.toml index c998b18..44ee86f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ getopts = "0.2.18" lazy_static = "1.4.0" pad = "0.1.6" regex = "1.7.3" +toml = "0.7.3" # [lib] # name = "crit" diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3846599..1a1d808 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -15,7 +15,7 @@ # INSTALL BINARIES FROM SOURCE ```console -$ cargo install --path . +$ cargo install --bins --path . ``` # UNINSTALL BINARIES diff --git a/README.md b/README.md index fe54418..e63e616 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ $ cd example $ crit -$ ls .crit/cross +$ ls .crit/bin aarch64-apple-darwin -aarch64-linux-android aarch64-unknown-linux-gnu +aarch64-unknown-linux-musl ... ``` @@ -42,7 +42,7 @@ https://github.com/mcandre/crit/releases # INSTALL FROM SOURCE ```console -$ cargo install --path . +$ cargo install --bins --path . ``` # LICENSE diff --git a/example/Cargo.toml b/example/Cargo.toml index f565876..11f665a 100644 --- a/example/Cargo.toml +++ b/example/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "hello" -description = "Hello World" +name = "demo" +description = "Demo applications" version = "0.0.1" authors = ["Andrew Pennebaker "] license = "BSD-2-Clause" @@ -8,3 +8,7 @@ license = "BSD-2-Clause" [[bin]] name = "hello" path = "src/hello.rs" + +[[bin]] +name = "fizzbuzz" +path = "src/fizzbuzz.rs" diff --git a/example/README.md b/example/README.md index bcdd0b7..ab1c887 100644 --- a/example/README.md +++ b/example/README.md @@ -1,11 +1,17 @@ -# Hello World +# DEMO APPS -This application says, "Hello World!" - -# EXAMPLE +# EXAMPLES ```console $ hello +Hello World! + +$ fizzbuzz +1 +2 +Fizz +4 +Buzz ... ``` @@ -16,6 +22,18 @@ $ hello * [Docker](https://www.docker.com/) 20.10.23+ * [crit](https://github.com/mcandre/crit) +# BUILD & INSTALL + +```console +$ cargo install --bins --path . +``` + +# UNINSTALL + +```console +$ cargo uninstall demo +``` + # PORT ```console diff --git a/example/src/fizzbuzz.rs b/example/src/fizzbuzz.rs new file mode 100644 index 0000000..f096877 --- /dev/null +++ b/example/src/fizzbuzz.rs @@ -0,0 +1,23 @@ +//! FizzBuzz + +fn fizzbuzz(n: i64) -> String { + match (n % 3 == 0, n % 5 == 0) { + (true, true) => "FizzBuzz".to_string(), + (true, _) => "Fizz".to_string(), + (_, true) => "Buzz".to_string(), + _ => n.to_string() + } +} + +#[test] +fn smoketest() { + assert_eq!(fizzbuzz(3), "Fizz"); + assert_eq!(fizzbuzz(5), "Buzz"); + assert_eq!(fizzbuzz(15), "FizzBuzz"); +} + +fn main() { + for n in 1..101 { + println!("{}", fizzbuzz(n)); + } +} diff --git a/src/crit.rs b/src/crit.rs index a6ced3f..ba9ff28 100644 --- a/src/crit.rs +++ b/src/crit.rs @@ -4,6 +4,7 @@ extern crate getopts; extern crate lazy_static; extern crate pad; extern crate regex; +extern crate toml; use pad::PadStr; use std::cmp; @@ -39,6 +40,24 @@ lazy_static::lazy_static! { "wasm", ].join("|") ).unwrap(); + + static ref BUILD_MODES : Vec = vec![ + "debug", + "release", + ] + .iter() + .map(|e| e.to_string()) + .collect(); + + static ref BINARY_FILE_EXTENSIONS : Vec = vec![ + "", + "exe", + "js", + "wasm", + ] + .iter() + .map(|e| e.to_string()) + .collect(); } // Show short CLI spec @@ -57,6 +76,7 @@ fn main() { let artifact_root : &path::Path = path::Path::new(CRIT_ARTIFACT_ROOT); let mut target_exclusion_pattern : regex::Regex = DEFAULT_TARGET_EXCLUSION_PATTERNS.clone(); let list_targets : bool; + let mut rest : Vec = vec!["-r"] .iter() .map(|e| e.to_string()) @@ -68,6 +88,7 @@ fn main() { opts.optflag("l", "list-targets", "list enabled targets"); opts.optflag("h", "help", "print usage info"); opts.optflag("v", "version", "print version info"); + let arguments : Vec = env::args().collect(); match opts.parse(&arguments[1..]) { @@ -92,7 +113,9 @@ fn main() { process::exit(0); } else if optmatches.opt_present("e") { - let ep = optmatches.opt_str("e").unwrap(); + let ep = optmatches.opt_str("e") + .expect("error: missing exclusion pattern flag value"); + target_exclusion_pattern = regex::Regex::new(&ep) .expect("error: unable to compile Rust regular expression"); } @@ -103,6 +126,30 @@ fn main() { } } + let cargo_str : String = fs::read_to_string("Cargo.toml") + .expect("error: unable to read Cargo.toml"); + + let cargo_table : toml::Table = cargo_str.parse::() + .expect("error: unable to parse Cargo.toml"); + + let bin_tables : &Vec = cargo_table["bin"] + .as_array() + .expect("error: unable to retrieve bin sections from Cargo.toml"); + + let mut applications : Vec<&str> = Vec::new(); + + for bin_table in bin_tables { + let application : &str = bin_table["name"] + .as_str() + .expect("error: Cargo.toml binary missing name field"); + + applications.push(application); + } + + if applications.is_empty() { + eprintln!("error: no binaries declared in Cargo.toml") + } + let rustup_output : process::Output = process::Command::new("rustup") .args(["target", "list"]) .stdout(process::Stdio::piped()) @@ -114,7 +161,7 @@ fn main() { let rustup_stderr : String = String::from_utf8(rustup_output.stderr) .expect("error: unable to read stderr stream from rustup"); - println!("{}", rustup_stderr); + eprintln!("{}", rustup_stderr); process::exit(1); } @@ -159,18 +206,21 @@ fn main() { targets.retain(|_, &mut enabled| enabled); if targets.is_empty() { - println!("no targets enabled"); + eprintln!("error: no targets enabled"); process::exit(1); } - let cross_dir : &path::PathBuf = &artifact_root - .join("cross"); + let bin_dir : &path::PathBuf = &artifact_root.join("bin"); + + // cross automatically creates its --target-dir paths + let cross_dir : &path::PathBuf = &artifact_root.join("cross"); for target in targets.keys() { println!("building {}...", target); - let target_dir : &str = &cross_dir - .join(target) + let target_dir_pathbuf : path::PathBuf = cross_dir + .join(target); + let target_dir : &str = &target_dir_pathbuf .display() .to_string(); @@ -186,8 +236,47 @@ fn main() { let cross_stderr : String = String::from_utf8(cross_output.stderr) .expect("error: unable to read stderr stream from cross"); - println!("{}", cross_stderr); + eprintln!("{}", cross_stderr); process::exit(1); } + + for mode in BUILD_MODES.iter() { + for application in &applications { + let application_dir_pathbuf : path::PathBuf = bin_dir + .join(target); + + let application_dir : &str = &application_dir_pathbuf + .display() + .to_string(); + + _ = fs::create_dir_all(application_dir) + .expect("error: unable to create bin directory"); + + for extension in BINARY_FILE_EXTENSIONS.iter() { + let mut application_source_pathbuf : path::PathBuf = target_dir_pathbuf + .join(target) + .join(mode) + .join(application); + application_source_pathbuf.set_extension(extension); + + if application_source_pathbuf.exists() { + let application_source_path : &str = &application_source_pathbuf + .display() + .to_string(); + + let mut application_destination_pathbuf : path::PathBuf = application_dir_pathbuf + .join(application); + application_destination_pathbuf.set_extension(extension); + + let application_destination_path : &str = &application_destination_pathbuf + .display() + .to_string(); + + _ = fs::copy(application_source_path, application_destination_path) + .expect("error: unable to copy binary"); + } + } + } + } } }