aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-03-23 15:37:31 -0600
committerMelody Horn <melody@boringcactus.com>2021-03-23 15:37:31 -0600
commit05b8b6339c4b00b0e898c8456677be2883c8a072 (patch)
treeb304096225f66e8b00ee913103d9a1b6bf3ab3d7
parentad8ee545d0f818dfb52c4ba154bed0b8c1bd6e44 (diff)
downloadmakers-05b8b6339c4b00b0e898c8456677be2883c8a072.tar.gz
makers-05b8b6339c4b00b0e898c8456677be2883c8a072.zip
read arguments
-rw-r--r--Cargo.lock218
-rw-r--r--Cargo.toml3
-rw-r--r--src/args.rs189
-rw-r--r--src/main.rs8
4 files changed, 416 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b856f0c..190d96a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,5 +1,223 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "clap"
+version = "2.33.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
+
+[[package]]
name = "makers"
version = "0.1.0"
+dependencies = [
+ "structopt",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 8fe21c4..59129c2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "makers"
version = "0.1.0"
-authors = ["Melody Horn <melody@boringcactus.com>"]
+authors = ["boringcactus / Melody Horn <melody@boringcactus.com>"]
edition = "2018"
description = "a POSIX-compatible make implemented in Rust"
readme = "README.md"
@@ -10,3 +10,4 @@ keywords = ["build", "make"]
categories = ["development-tools"]
[dependencies]
+structopt = "0.3.21"
diff --git a/src/args.rs b/src/args.rs
new file mode 100644
index 0000000..1fe6731
--- /dev/null
+++ b/src/args.rs
@@ -0,0 +1,189 @@
+use std::env;
+use std::ffi::OsString;
+use std::path::PathBuf;
+
+use structopt::StructOpt;
+
+#[derive(StructOpt, Debug, PartialEq, Eq)]
+#[structopt(author, about)]
+pub struct Args {
+ /// Cause environment variables, including those with null values, to override macro
+ /// assignments within makefiles.
+ #[structopt(short, long)]
+ environment_overrides: bool,
+
+ /// Specify a different makefile (or '-' for standard input).
+ ///
+ /// The argument makefile is a pathname of a description file, which is also referred
+ /// to as the makefile. A pathname of '-' shall denote the standard input. There can
+ /// be multiple instances of this option, and they shall be processed in the order
+ /// specified. The effect of specifying the same option-argument more than once is
+ /// unspecified.
+ #[structopt(short = "f", long = "file", visible_alias = "makefile", number_of_values = 1, parse(from_os_str))]
+ makefile: Vec<PathBuf>,
+
+ /// Ignore error codes returned by invoked commands.
+ ///
+ /// This mode is the same as if the special target .IGNORE were specified without
+ /// prerequisites.
+ #[structopt(short, long)]
+ ignore_errors: bool,
+
+ /// Continue to update other targets that do not depend on the current target if a
+ /// non-ignored error occurs while executing the commands to bring a target
+ /// up-to-date.
+ #[structopt(short, long)]
+ keep_going: bool,
+
+ /// Write commands that would be executed on standard output, but do not execute them
+ /// (but execute lines starting with '+').
+ ///
+ /// However, lines with a <plus-sign> ( '+' ) prefix shall be executed. In this mode,
+ /// lines with an at-sign ( '@' ) character prefix shall be written to standard
+ /// output.
+ #[structopt(short = "n", long, visible_alias = "just-print", visible_alias = "recon")]
+ dry_run: bool,
+
+ /// Write to standard output the complete set of macro definitions and target
+ /// descriptions.
+ ///
+ /// The output format is unspecified.
+ #[structopt(short, long, visible_alias = "print-data-base")]
+ print_everything: bool,
+
+ /// Return a zero exit value if the target file is up-to-date; otherwise, return an
+ /// exit value of 1.
+ ///
+ /// Targets shall not be updated if this option is specified. However, a makefile
+ /// command line (associated with the targets) with a <plus-sign> ( '+' ) prefix
+ /// shall be executed.
+ #[structopt(short, long)]
+ question: bool,
+
+ /// Clear the suffix list and do not use the built-in rules.
+ #[structopt(short = "r", long)]
+ no_builtin_rules: bool,
+
+ /// Terminate make if an error occurs while executing the commands to bring a target
+ /// up-to-date (default behavior, required by POSIX to be also a flag for some
+ /// reason).
+ ///
+ /// This shall be the default and the opposite of -k.
+ #[structopt(short = "S", long, visible_alias = "stop", hidden = true, overrides_with="keep-going")]
+ no_keep_going: bool,
+
+ /// Do not write makefile command lines or touch messages to standard output before
+ /// executing.
+ ///
+ /// This mode shall be the same as if the special target .SILENT were specified
+ /// without prerequisites.
+ #[structopt(short, long, visible_alias = "quiet")]
+ silent: bool,
+
+ /// Update the modification time of each target as though a touch target had been
+ /// executed.
+ ///
+ /// Targets that have prerequisites but no commands, or that are already up-to-date,
+ /// shall not be touched in this manner. Write messages to standard output for each
+ /// target file indicating the name of the file and that it was touched. Normally,
+ /// the makefile command lines associated with each target are not executed. However,
+ /// a command line with a <plus-sign> ( '+' ) prefix shall be executed.
+ #[structopt(short, long)]
+ touch: bool,
+
+ /// Target names or macro definitions.
+ ///
+ /// If no target is specified, while make is processing the makefiles, the first
+ /// target that make encounters that is not a special target or an inference rule
+ /// shall be used.
+ targets_or_macros: Vec<String>,
+}
+
+impl Args {
+ pub fn from_env_and_args() -> Args {
+ // POSIX spec says "Any options specified in the MAKEFLAGS environment variable
+ // shall be evaluated before any options specified on the make utility command
+ // line."
+ // TODO make sure only flags show up in MAKEFLAGS (i.e. not -f or other stuff)
+ // TODO accept "option letters without the leading <hyphen-minus> characters"
+ let env_makeflags = env::var("MAKEFLAGS").unwrap_or_default();
+ let env_makeflags = env_makeflags.split_whitespace()
+ .map(|x| OsString::from(x));
+ let mut args = env::args_os();
+ // per the structopt docs, the first argument will be used as the binary name,
+ // so we need to make sure it goes in before MAKEFLAGS
+ let arg0 = args.next().unwrap_or_else(|| env!("CARGO_PKG_NAME").into());
+
+ let args = ::std::iter::once(arg0)
+ .chain(env_makeflags.into_iter())
+ .chain(args);
+ Args::from_iter(args)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn no_args() {
+ let args: Vec<OsString> = vec!["makers".into()];
+ let args = Args::from_iter(args.into_iter());
+ assert_eq!(args, Args {
+ environment_overrides: false,
+ makefile: vec![],
+ ignore_errors: false,
+ keep_going: false,
+ dry_run: false,
+ print_everything: false,
+ question: false,
+ no_builtin_rules: false,
+ no_keep_going: false,
+ silent: false,
+ touch: false,
+ targets_or_macros: vec![],
+ });
+ }
+
+ #[test]
+ fn kitchen_sink_args() {
+ let args = "makers -eiknpqrstf foo -f bruh bar baz=yeet";
+ let args = Args::from_iter(args.split_whitespace());
+ assert_eq!(args, Args {
+ environment_overrides: true,
+ makefile: vec!["foo".into(), "bruh".into()],
+ ignore_errors: true,
+ keep_going: true,
+ dry_run: true,
+ print_everything: true,
+ question: true,
+ no_builtin_rules: true,
+ no_keep_going: false,
+ silent: true,
+ touch: true,
+ targets_or_macros: vec!["bar".into(), "baz=yeet".into()],
+ });
+ }
+
+ #[test]
+ fn keep_going_wrestling() {
+ let args = "makers -kSkSkSSSkSkkSk -k -S -k -k -S -S -k";
+ let args = Args::from_iter(args.split_whitespace());
+ assert_eq!(args, Args {
+ environment_overrides: false,
+ makefile: vec![],
+ ignore_errors: false,
+ keep_going: true,
+ dry_run: false,
+ print_everything: false,
+ question: false,
+ no_builtin_rules: false,
+ no_keep_going: false,
+ silent: false,
+ touch: false,
+ targets_or_macros: vec![],
+ });
+ }
+
+ // TODO test MAKEFLAGS
+}
diff --git a/src/main.rs b/src/main.rs
index e7a11a9..2316546 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,9 @@
+
+mod args;
+
+use args::Args;
+
fn main() {
- println!("Hello, world!");
+ let args = Args::from_env_and_args();
+ dbg!(args);
}