rust-analyzer format
This commit is contained in:
parent
0c73dd3f56
commit
3eafbff7f9
4 changed files with 115 additions and 63 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::{path::PathBuf, fs};
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use path_clean::PathClean;
|
||||
use regex::Regex;
|
||||
|
@ -15,7 +15,7 @@ pub enum BuildRuleKind<T> {
|
|||
Convenience(T),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BuildRule {
|
||||
pub target: String,
|
||||
pub prerequisites: Vec<String>,
|
||||
|
@ -40,7 +40,7 @@ impl BuildRule {
|
|||
true => {
|
||||
headers.push(String::from(path.to_str().unwrap()));
|
||||
continue;
|
||||
},
|
||||
}
|
||||
false => (),
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ impl BuildRule {
|
|||
true => {
|
||||
headers.push(String::from(path.to_str().unwrap()));
|
||||
continue 'fileloop;
|
||||
},
|
||||
}
|
||||
false => (),
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ impl BuildRule {
|
|||
headers
|
||||
}
|
||||
pub fn new_from_c_file(path: &str, makefile: &Makefile) -> BuildRule {
|
||||
|
||||
let mut prerequisites: Vec<String> = Vec::new();
|
||||
|
||||
prerequisites.push((PathBuf::from(path)).clean().to_str().unwrap().to_string());
|
||||
|
@ -82,7 +81,11 @@ impl BuildRule {
|
|||
|
||||
let compile_command = format!("$(CC) $(CFLAGS) $(INCS) -o {} -c {}", obj_path, path);
|
||||
|
||||
BuildRule { target: String::from(obj_path), prerequisites, recipe_commands: vec![compile_command] }
|
||||
BuildRule {
|
||||
target: String::from(obj_path),
|
||||
prerequisites,
|
||||
recipe_commands: vec![compile_command],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use std::process::exit;
|
||||
use clap::Parser;
|
||||
use std::process::exit;
|
||||
|
||||
mod build_rule;
|
||||
mod makefile;
|
||||
|
@ -52,9 +52,11 @@ fn main() {
|
|||
let makefile = Makefile::new_from_path(&makefile_name);
|
||||
|
||||
let mut rule_list = RuleList::new();
|
||||
rule_list.recursively_gen_objects(".", &makefile).unwrap_or_else(|e| {
|
||||
panic!("error: problem in recursive search: {e}");
|
||||
});
|
||||
rule_list
|
||||
.recursively_gen_objects(".", &makefile)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("error: problem in recursive search: {e}");
|
||||
});
|
||||
|
||||
if rule_list.0.is_empty() {
|
||||
eprintln!("no source files found, nothing to do. exiting...");
|
||||
|
@ -65,12 +67,12 @@ fn main() {
|
|||
|
||||
// Only include directory defaults if the user has not specified them
|
||||
let mut dirdefwritten = false;
|
||||
if ! makefile.contains_builddir_def() {
|
||||
if !makefile.contains_builddir_def() {
|
||||
generated_content.push_str("BUILDDIR = build\n");
|
||||
dirdefwritten = true;
|
||||
}
|
||||
|
||||
if ! makefile.contains_objdir_def() {
|
||||
if !makefile.contains_objdir_def() {
|
||||
generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n");
|
||||
dirdefwritten = true;
|
||||
}
|
||||
|
@ -81,8 +83,10 @@ fn main() {
|
|||
|
||||
ARGS.with(|args| {
|
||||
if args.dynamic_library {
|
||||
generated_content.push_str("# dynamic library\nCFLAGS += -fPIC\nLDFLAGS += -shared\n\n");
|
||||
} else {}
|
||||
generated_content
|
||||
.push_str("# dynamic library\nCFLAGS += -fPIC\nLDFLAGS += -shared\n\n");
|
||||
} else {
|
||||
}
|
||||
});
|
||||
|
||||
rule_list.add_target_rule();
|
||||
|
@ -101,7 +105,9 @@ fn main() {
|
|||
generated_content.push_str(&rule_list.to_string());
|
||||
|
||||
// Write makefile
|
||||
makefile.write_new_generated_content(generated_content).unwrap_or_else(|e| {
|
||||
panic!("error: could not write makefile at {}: {e}", makefile.path);
|
||||
});
|
||||
makefile
|
||||
.write_new_generated_content(generated_content)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("error: could not write makefile at {}: {e}", makefile.path);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::{fs, io::ErrorKind};
|
||||
use regex::Regex;
|
||||
use std::{fs, io::ErrorKind};
|
||||
|
||||
const START_KEY: &str = "#=mgen_start=#\n";
|
||||
const END_KEY: &str = "\n#=mgen_end=#";
|
||||
|
@ -19,28 +19,37 @@ impl Makefile {
|
|||
let contents = match fs::read_to_string(path) {
|
||||
Ok(v) => v,
|
||||
Err(e) => match e.kind() {
|
||||
// doesn't matter if the file doesn't exist, it will be created
|
||||
// doesn't matter if the file doesn't exist, it will be created
|
||||
// later.
|
||||
ErrorKind::NotFound => return Makefile {
|
||||
path: String::from(path), prologue: String::from(""),
|
||||
mgen_zone: String::from(""), epilogue: String::from(""),
|
||||
include_dirs: vec![String::from("")] },
|
||||
_ => panic!("error: cannot read makefile: {e}")
|
||||
}
|
||||
ErrorKind::NotFound => {
|
||||
return Makefile {
|
||||
path: String::from(path),
|
||||
prologue: String::from(""),
|
||||
mgen_zone: String::from(""),
|
||||
epilogue: String::from(""),
|
||||
include_dirs: vec![String::from("")],
|
||||
}
|
||||
}
|
||||
_ => panic!("error: cannot read makefile: {e}"),
|
||||
},
|
||||
};
|
||||
|
||||
let contains_start = contents.find(START_KEY).is_some();
|
||||
let contains_end = contents.find(END_KEY).is_some();
|
||||
|
||||
if (contains_start && !contains_end) || (!contains_start &&
|
||||
contains_end) {
|
||||
if (contains_start && !contains_end) || (!contains_start && contains_end) {
|
||||
panic!("error: makefile contains one mgen guard but not the other. cannot continue.");
|
||||
}
|
||||
|
||||
if !(contains_start && contains_end) {
|
||||
let include_dirs = Makefile::get_include_dirs(&contents);
|
||||
return Makefile { path: String::from(path), prologue: contents,
|
||||
mgen_zone: String::from(""), epilogue: String::from(""), include_dirs };
|
||||
return Makefile {
|
||||
path: String::from(path),
|
||||
prologue: contents,
|
||||
mgen_zone: String::from(""),
|
||||
epilogue: String::from(""),
|
||||
include_dirs,
|
||||
};
|
||||
}
|
||||
|
||||
// contains the part before the start key and everything after
|
||||
|
@ -49,16 +58,16 @@ impl Makefile {
|
|||
let gen_and_post: Vec<&str> = pre_and_after[1].split(END_KEY).collect();
|
||||
|
||||
let include_dirs = Makefile::get_include_dirs(&contents);
|
||||
|
||||
Makefile {
|
||||
|
||||
Makefile {
|
||||
path: String::from(path),
|
||||
prologue: String::from(pre_and_after[0]),
|
||||
mgen_zone: String::from(gen_and_post[0]),
|
||||
epilogue: String::from(gen_and_post[1]),
|
||||
include_dirs
|
||||
include_dirs,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_include_dirs(search: &String) -> Vec<String> {
|
||||
let mut include_dirs: Vec<String> = Vec::new();
|
||||
|
||||
|
@ -66,23 +75,18 @@ impl Makefile {
|
|||
let caps = makefile_regex.captures_iter(search);
|
||||
let dirlist = match caps.map(|c| c.extract()).last() {
|
||||
Some((_, [v])) => v,
|
||||
None => {
|
||||
return include_dirs
|
||||
}
|
||||
,
|
||||
None => return include_dirs,
|
||||
};
|
||||
|
||||
|
||||
let incdir_regex = Regex::new(r"\s*-I\s*(.*?)(?:[\s]|$)").unwrap();
|
||||
let caps = incdir_regex.captures_iter(&dirlist);
|
||||
for (_, [dir]) in caps.map(|c| c.extract()) {
|
||||
include_dirs.push(String::from(dir));
|
||||
}
|
||||
|
||||
|
||||
include_dirs
|
||||
}
|
||||
|
||||
|
||||
pub fn contains_builddir_def(&self) -> bool {
|
||||
let re = Regex::new(r"\s+BUILDDIR = ").unwrap();
|
||||
re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue))
|
||||
|
@ -92,9 +96,16 @@ impl Makefile {
|
|||
let re = Regex::new(r"\s+OBJDIR = ").unwrap();
|
||||
re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue))
|
||||
}
|
||||
|
||||
|
||||
pub fn write_new_generated_content(&self, generated_content: String) -> std::io::Result<()> {
|
||||
let content = [&self.prologue, START_KEY, &generated_content, END_KEY, &self.epilogue].concat();
|
||||
let content = [
|
||||
&self.prologue,
|
||||
START_KEY,
|
||||
&generated_content,
|
||||
END_KEY,
|
||||
&self.epilogue,
|
||||
]
|
||||
.concat();
|
||||
|
||||
fs::write(&self.path, &content)?;
|
||||
|
||||
|
|
|
@ -9,11 +9,15 @@ use crate::ARGS;
|
|||
pub struct RuleList(pub Vec<BuildRuleKind<BuildRule>>);
|
||||
|
||||
impl RuleList {
|
||||
pub fn new() -> RuleList{
|
||||
pub fn new() -> RuleList {
|
||||
RuleList(vec![])
|
||||
}
|
||||
|
||||
pub fn recursively_gen_objects(&mut self, proj_dir_path: &str, makefile: &Makefile) -> std::io::Result<()>{
|
||||
pub fn recursively_gen_objects(
|
||||
&mut self,
|
||||
proj_dir_path: &str,
|
||||
makefile: &Makefile,
|
||||
) -> std::io::Result<()> {
|
||||
let files = fs::read_dir(proj_dir_path)?;
|
||||
for file in files {
|
||||
let file = file?;
|
||||
|
@ -36,18 +40,21 @@ impl RuleList {
|
|||
continue;
|
||||
}
|
||||
let path = path.to_str().unwrap();
|
||||
self.0.push(BuildRuleKind::Object(BuildRule::new_from_c_file(path, makefile)));
|
||||
},
|
||||
self.0
|
||||
.push(BuildRuleKind::Object(BuildRule::new_from_c_file(
|
||||
path, makefile,
|
||||
)));
|
||||
}
|
||||
None => {
|
||||
continue;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_obj_targets(&self) -> Vec<String>{
|
||||
pub fn get_obj_targets(&self) -> Vec<String> {
|
||||
let mut ret: Vec<String> = Vec::new();
|
||||
for rule in &self.0 {
|
||||
match rule {
|
||||
|
@ -63,13 +70,15 @@ impl RuleList {
|
|||
let mut target_comm = String::new();
|
||||
ARGS.with(|args| {
|
||||
if args.static_library {
|
||||
target_comm = String::from(
|
||||
format!("$(AR) $(ARFLAGS) $(BUILDDIR)/$(TARGET) {}", objects.join(" "))
|
||||
);
|
||||
target_comm = String::from(format!(
|
||||
"$(AR) $(ARFLAGS) $(BUILDDIR)/$(TARGET) {}",
|
||||
objects.join(" ")
|
||||
));
|
||||
} else {
|
||||
target_comm = String::from(
|
||||
format!("$(CC) $(LDFLAGS) $(INCS) -o $(BUILDDIR)/$(TARGET) {} $(LDLIBS)", objects.join(" "))
|
||||
);
|
||||
target_comm = String::from(format!(
|
||||
"$(CC) $(LDFLAGS) $(INCS) -o $(BUILDDIR)/$(TARGET) {} $(LDLIBS)",
|
||||
objects.join(" ")
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -87,7 +96,7 @@ impl RuleList {
|
|||
self.0.push(BuildRuleKind::Directory(BuildRule {
|
||||
target: dir.to_string(),
|
||||
prerequisites: vec![],
|
||||
recipe_commands: vec![format!("mkdir -p {dir}").to_string()]
|
||||
recipe_commands: vec![format!("mkdir -p {dir}").to_string()],
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -95,7 +104,10 @@ impl RuleList {
|
|||
self.0.push(BuildRuleKind::Convenience(BuildRule {
|
||||
target: String::from(".PHONY: clean\nclean"),
|
||||
prerequisites: vec![],
|
||||
recipe_commands: vec![String::from("rm -r $(OBJDIR)"), String::from("rm -r $(BUILDDIR)")]
|
||||
recipe_commands: vec![
|
||||
String::from("rm -r $(OBJDIR)"),
|
||||
String::from("rm -r $(BUILDDIR)"),
|
||||
],
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -103,7 +115,7 @@ impl RuleList {
|
|||
self.0.push(BuildRuleKind::Convenience(BuildRule {
|
||||
target: String::from(".PHONY: run\nrun"),
|
||||
prerequisites: vec![String::from("$(BUILDDIR)/$(TARGET)")],
|
||||
recipe_commands: vec![String::from("./$(BUILDDIR)/$(TARGET)")]
|
||||
recipe_commands: vec![String::from("./$(BUILDDIR)/$(TARGET)")],
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -152,7 +164,7 @@ impl RuleList {
|
|||
}
|
||||
}
|
||||
|
||||
fn file_is_hidden(file: &DirEntry) -> bool{
|
||||
fn file_is_hidden(file: &DirEntry) -> bool {
|
||||
let file_name = file.file_name();
|
||||
let str_name = file_name.to_str().unwrap();
|
||||
let first_char = str_name.chars().nth(0).unwrap();
|
||||
|
@ -165,10 +177,30 @@ fn file_is_hidden(file: &DirEntry) -> bool{
|
|||
|
||||
impl ToString for RuleList {
|
||||
fn to_string(&self) -> String {
|
||||
let targets = &self.get_target_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
|
||||
let objects = &self.get_object_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
|
||||
let directories = &self.get_directory_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
|
||||
let conveniences = &self.get_convenience_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
|
||||
let targets = &self
|
||||
.get_target_rules()
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let objects = &self
|
||||
.get_object_rules()
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let directories = &self
|
||||
.get_directory_rules()
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let conveniences = &self
|
||||
.get_convenience_rules()
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let all = [targets, objects, directories, conveniences];
|
||||
let mut nonzero: Vec<String> = Vec::new();
|
||||
|
@ -178,7 +210,7 @@ impl ToString for RuleList {
|
|||
nonzero.push(category.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nonzero.join("\n\n")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue