Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution for issue#8 #11

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@
use clap::Parser;
use const_format::formatcp;

const SUBMAKE_FORBIDDEN_FLAGS: [&str; 5] = ["-j", "-C", "-f", "-o", "-W"];

const BUILD_MODE: &str = if cfg!(debug_assertions) {
"Debug"
} else {
"Release"
};

/// Represents the `clap`-based arguments provided by this binary.
#[derive(Clone, Debug, Parser)]
#[clap(
name = "make (oxidized)",
version,
about,
after_help = formatcp!(
"License: {}\nSource: {}", env!("CARGO_PKG_LICENSE"), env!("CARGO_PKG_REPOSITORY")
"License: {}\nSource: {}\nVersion: {}\nBuild type: {}",
env!("CARGO_PKG_LICENSE"),
env!("CARGO_PKG_REPOSITORY"),
env!("CARGO_PKG_VERSION"),
BUILD_MODE
),
)]
pub struct Args {
Expand Down Expand Up @@ -56,3 +68,37 @@ pub struct Args {
#[arg(long)]
pub license: bool,
}

/// Converts the arguments to a string that can be passed to a sub-make invocation.
pub fn args_to_submake_str() -> String {
// Rudimetary MAKEFLAGS parsing, the '-j' flag handling is not implemented yet.
// TODO: This should probably be a `Result` instead of a `panic!`.
// NOTE: Maybe change the way this is done to a pure IPC solution? when sub-make is used?
let args = std::env::args()
.collect::<Vec<_>>()
.iter()
.map(|arg| {
let mut arg_mod = arg.clone();

// If the argument contains a space, we need to quote it.
if arg_mod.contains(' ') {
arg_mod = format!("\"{}\"", arg_mod);
}

if arg_mod.starts_with("--") {
arg_mod = arg_mod[2..].to_string();
} else if arg_mod.starts_with('-') {
arg_mod = arg_mod[1..].to_string();
}

// remove special cases
if SUBMAKE_FORBIDDEN_FLAGS.contains(&arg_mod.as_str()) {
arg_mod = "".to_string();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure, but I think this would fail for an argument like -abc, where it's 3 single flags passed as a single arg. I know clap handles that, so it might be better to add this as a method under impl Args and use the struct information to construct args to pass to any sub-make.

If I'm wrong about this not working for coalesced flags, then feel free to ignore this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will get around to this one tomorrow, should we add the args to the context?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think context should contain the args, I just think the helper should use the args struct that is attached to the Makefile.

arg_mod
})
.collect::<Vec<_>>()
.join(" ");

format!("-{}", args)
}
25 changes: 25 additions & 0 deletions src/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,25 @@ pub struct Vars {
// multiple allocations and lifetime tracking.
blank: Var,
default_recipe_prefix: Var,
make_var: Var,
makeargs_var: Var,
xadaemon marked this conversation as resolved.
Show resolved Hide resolved
}

impl Vars {
/// Primary interface for configuring a new instance. We also create some cached values that
/// live for the lifetime of this instance to reduce the number of allocations.
pub fn new<const N: usize>(init: [(&str, &str); N]) -> Self {
// Get the executable path for the `MAKE` variable.
let exe_path = match std::env::current_exe() {
// TODO: This should probably be a `Result` instead of a `panic!`.
// Try to canonicalize the path, but if that fails we panic because
// this means something is very wrong with the system.
Ok(path) => path.canonicalize().unwrap().to_string_lossy().into_owned(),
Err(_) => panic!("Unable to get executable path!"),
xadaemon marked this conversation as resolved.
Show resolved Hide resolved
};



xadaemon marked this conversation as resolved.
Show resolved Hide resolved
let mut vars = Self {
map: HashMap::new(),
blank: Var {
Expand All @@ -46,6 +59,14 @@ impl Vars {
value: DEFAULT_RECIPE_PREFIX.to_string(),
recursive: false,
},
make_var: Var {
value: exe_path,
recursive: false,
},
makeargs_var: Var {
value: crate::args::args_to_submake_str(),
recursive: false,
},
};

// Use `set` to initialize data.
Expand All @@ -61,6 +82,9 @@ impl Vars {
pub fn get(&self, k: impl AsRef<str>) -> &Var {
let k = k.as_ref().trim();
match k {
// Special variables.
"MAKE" => &self.make_var,
"MAKEFLAGS" => &self.makeargs_var,
xadaemon marked this conversation as resolved.
Show resolved Hide resolved
".RECIPEPREFIX" => match self.map.get(k) {
None => &self.default_recipe_prefix,
Some(var) => {
Expand All @@ -71,6 +95,7 @@ impl Vars {
}
}
},
// Normal variables.
_ => match self.map.get(k) {
None => &self.blank,
Some(var) => var,
Expand Down