From 4ddbf21adee6d4e097c355d8d35dafcc633e4e78 Mon Sep 17 00:00:00 2001 From: Penguin Date: Thu, 30 Dec 2021 11:44:52 -0600 Subject: [PATCH] breaking up generate_makefile() func into smaller parts... for better compile times --- Cargo.lock | 45 ++++ igloo_core/Cargo.toml | 1 + igloo_core/src/igloo_action.rs | 21 +- igloo_core/src/igloo_project.rs | 195 ++++++++------ igloo_core/src/igloo_target.rs | 248 ++++++++++++++---- igloo_core/src/lib.rs | 8 +- igloo_util/src/lib.rs | 2 + projecttest/igloo/igloo.toml | 3 + projecttest/igloo/targets/samd21j18a/Makefile | 15 ++ src/main.rs | 1 + 10 files changed, 397 insertions(+), 142 deletions(-) create mode 100644 projecttest/igloo/igloo.toml create mode 100644 projecttest/igloo/targets/samd21j18a/Makefile diff --git a/Cargo.lock b/Cargo.lock index bdbaf4b..a9e62cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,6 +93,26 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "const_format" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22bc6cd49b0ec407b680c3e380182b6ac63b73991cb7602de350352fc309b614" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "directories" version = "3.0.2" @@ -173,6 +193,7 @@ dependencies = [ "directories", "igloo_util", "serde 1.0.132", + "sscanf", "toml", ] @@ -407,6 +428,30 @@ dependencies = [ "serde 1.0.132", ] +[[package]] +name = "sscanf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513162b19ce2aa5347d36a1d9cbc8ba2b20c63e0e82080b52d2cade9fb3a8cb7" +dependencies = [ + "const_format", + "lazy_static", + "regex", + "sscanf_macro", +] + +[[package]] +name = "sscanf_macro" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d697834866afffd34330ee55f6dbb2cf1eedd44b33cc63b8fdfd87bc3268eeac" +dependencies = [ + "proc-macro2", + "quote", + "regex-syntax", + "syn", +] + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/igloo_core/Cargo.toml b/igloo_core/Cargo.toml index c78fa95..25bc7aa 100644 --- a/igloo_core/Cargo.toml +++ b/igloo_core/Cargo.toml @@ -11,4 +11,5 @@ config = "0.11" directories = "3.0.1" toml = "0.5.8" serde = { version = "1.0.132", features = ["derive"]} +sscanf = "0.1.2" igloo_util = { path="../igloo_util" } \ No newline at end of file diff --git a/igloo_core/src/igloo_action.rs b/igloo_core/src/igloo_action.rs index 2ab5c77..1eabfd3 100644 --- a/igloo_core/src/igloo_action.rs +++ b/igloo_core/src/igloo_action.rs @@ -1,3 +1,4 @@ +#![allow(warnings)] use clap::ArgMatches; use igloo_util::IglooDebugSeverity::*; @@ -110,7 +111,7 @@ pub fn ia_new(igloo: &Igloo, project_name: String, initial_target: String) -> Ig prj.config.add_target(initial_target); prj.targets = Settings::get_targets_from_config(&prj); - // Now populate + // Now populate project files ret = prj.generate(); if ret != IS_GOOD { @@ -118,31 +119,21 @@ pub fn ia_new(igloo: &Igloo, project_name: String, initial_target: String) -> Ig return ret } - ret = prj.generate_igloo_header(); + // now do target folders + ret = prj.generate_targets(); if ret != IS_GOOD { - igloo_debug!(ERROR, ret); + igloo_debug!(WARNING, ret); return ret } - ret = prj.generate_igloo_main(); - if ret != IS_GOOD - { - igloo_debug!(ERROR, ret); - } - - ret = prj.generate_project_config(); - if ret != IS_GOOD - { - igloo_debug!(ERROR, ret); - } ret } /// Debugging function to make sure projects are being loaded correctly pub fn ia_debug(igloo: &Igloo) -> IglooStatus { - let mut ret = IS_GOOD; + let mut ret: IglooStatus = IS_GOOD; ret } diff --git a/igloo_core/src/igloo_project.rs b/igloo_core/src/igloo_project.rs index 0f373f2..95aadf1 100644 --- a/igloo_core/src/igloo_project.rs +++ b/igloo_core/src/igloo_project.rs @@ -3,7 +3,7 @@ use crate::Igloo; use crate::igloo_target::IglooTarget; use serde::{Serialize, Deserialize}; -use std::fs::{OpenOptions}; +use std::io::prelude::*; use igloo_util::IglooDebugSeverity::*; use igloo_util::IglooStatus::{self, *}; use igloo_util::TRACE_LEVEL; @@ -70,16 +70,15 @@ impl Settings .clone() .join("igloo") .join("igloo.toml"); - std::fs::File::create(&prj_cfg_path).unwrap(); - let mut prj_cfg_file = OpenOptions::new() - .write(true) - .append(true) - .open(&prj_cfg_path) - .unwrap(); let contents = toml::to_string(&prj.config).unwrap(); - igloo_debug!(TRACE, IS_NONE, "{}", contents); - println!("PRINTING THIS ON ITS OWN: {}", contents); + igloo_debug!(INFO, IS_NONE, "Project file to be written:\n{}", contents); + igloo_debug!(TRACE, + IS_NONE, + "Create project file: {}", + &prj_cfg_path.to_str().unwrap()); + let mut prj_cfg_file = std::fs::File::create(&prj_cfg_path).unwrap(); + prj_cfg_file.write_all(contents.as_bytes()).unwrap(); IglooStatus::IS_GOOD } @@ -99,7 +98,7 @@ impl Settings let mut _targets: Vec = Vec::new(); for target in prj.config.profile.targets.iter() { - _targets.push(IglooTarget::target_from_name(prj.igloo, String::from(target)).unwrap()); + _targets.push(IglooTarget::target_from_name(prj, String::from(target)).unwrap()); } _targets } @@ -110,6 +109,7 @@ pub struct IglooProject<'a> pub igloo: &'a Igloo, pub config: Settings, pub targets: Vec::, + // $PWD/${PROJECT_NAME} pub root: std::path::PathBuf, } @@ -180,104 +180,149 @@ impl<'a> IglooProject<'a> // making this root and then cloning to work with active directory // so i can make changes to active dir and still have my project root if i need it // so far i havent needed it so i may just remove this - let active_dir = self.root.clone(); - // create new project directory - match std::fs::create_dir(&active_dir) + loop { - Err(e) => + // create new project directory + match std::fs::create_dir(&active_dir) { - ret = IS_FAILED_TO_CREATE_DIR; - igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir, e); - return ret + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, + ret, + "Failed to create dir: {:?} | {:?}", + &active_dir, + e); + break; + } + _ => (), } - _ => (), - } - // create igloo directory - match std::fs::create_dir(&active_dir.clone().join("igloo")) - { - Err(e) => + // create igloo directory + match std::fs::create_dir(&active_dir.clone().join("igloo")) { - ret = IS_FAILED_TO_CREATE_DIR; - igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("igloo"), e); - return ret + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, + ret, + "Failed to create dir: {:?} | {:?}", + &active_dir.clone().join("igloo"), + e); + break; + } + _ => (), } - _ => (), - } - match std::fs::create_dir(&active_dir.clone().join("inc")) - { - Err(e) => + match std::fs::create_dir(&active_dir.clone().join("inc")) { - ret = IS_FAILED_TO_CREATE_DIR; - igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("inc"), e); - return ret + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, + ret, + "Failed to create dir: {:?} | {:?}", + &active_dir.clone().join("inc"), + e); + break; + } + _ => (), } - _ => (), - } - // create src directory - match std::fs::create_dir(&active_dir.clone().join("src")) - { - Err(e) => + // create src directory + match std::fs::create_dir(&active_dir.clone().join("src")) { - ret = IS_FAILED_TO_CREATE_DIR; - igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("src"), e); - return ret + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, + ret, + "Failed to create dir: {:?} | {:?}", + &active_dir.clone().join("src"), + e); + break; + } + _ => (), } - _ => (), - } - match std::fs::create_dir(&active_dir.clone().join("cfg")) - { - Err(e) => + match std::fs::create_dir(&active_dir.clone().join("cfg")) { - ret = IS_FAILED_TO_CREATE_DIR; - igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("cfg"), e); - return ret + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, + ret, + "Failed to create dir: {:?} | {:?}", + &active_dir.clone().join("cfg"), + e); + break; + } + _ => (), } - _ => (), - } - match std::fs::create_dir(&active_dir.clone().join("esf")) - { - Err(e) => + match std::fs::create_dir(&active_dir.clone().join("esf")) { - ret = IS_FAILED_TO_CREATE_DIR; - igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("esf"), e); - return ret + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, + ret, + "Failed to create dir: {:?} | {:?}", + &active_dir.clone().join("esf"), + e); + break; + } + _ => (), } - _ => (), - } - // project folders finished - // create project settings file (igloo.toml) - ret = self.generate_project_config(); - if ret != IS_GOOD - { - igloo_debug!(WARNING, ret); - return ret + // project folders finished + // create project settings file (igloo.toml) + ret = self.generate_project_config(); + if ret != IS_GOOD + { + break; + } + + ret = self.generate_igloo_header(); + if ret != IS_GOOD + { + igloo_debug!(ERROR, ret); + break; + + } + + ret = self.generate_igloo_main(); + if ret != IS_GOOD + { + igloo_debug!(ERROR, ret); + break; + } + + // + break; } - // now do target folders - ret = self.generate_targets(); if ret != IS_GOOD { - igloo_debug!(WARNING, ret); + igloo_debug!(ERROR, ret); return ret } - return ret } - fn generate_targets(&self) -> IglooStatus + pub fn generate_targets(&self) -> IglooStatus { + let mut ret = IS_GOOD; for target in &self.targets { - target.generate(self); + ret = target.generate(self); + if ret != IS_GOOD + { + return ret + } } - IS_GOOD + ret } pub fn generate_igloo_header(&self) -> IglooStatus diff --git a/igloo_core/src/igloo_target.rs b/igloo_core/src/igloo_target.rs index db512a4..f720c7f 100644 --- a/igloo_core/src/igloo_target.rs +++ b/igloo_core/src/igloo_target.rs @@ -14,16 +14,18 @@ // structs, but this is honestly just a trash way of doing it and I think the idea // of doing it that way is only an ideal solution. It isn't very practical. use igloo_util::*; -use crate::Igloo; use crate::IglooProject; use serde::{Serialize, Deserialize}; use std::vec::Vec; use igloo_util::IglooDebugSeverity::*; use igloo_util::IglooStatus::{self, *}; use igloo_util::TRACE_LEVEL; +use std::collections::HashMap; +use std::fs::OpenOptions; +use std::io::prelude::*; #[derive(Serialize, Deserialize, Debug)] -pub struct IglooTarget +pub struct IglooTargetConfig { name: String, common: String, @@ -35,11 +37,19 @@ pub struct IglooTarget series: String, } -impl IglooTarget +#[derive(Debug)] +pub struct IglooTarget { - fn _default() -> IglooTarget + root: std::path::PathBuf, + makefile: HashMap, + config: IglooTargetConfig, +} + +impl IglooTargetConfig +{ + fn _default() -> IglooTargetConfig { - IglooTarget + IglooTargetConfig { name: String::new(), common: String::new(), @@ -51,16 +61,29 @@ impl IglooTarget series: String::new(), } } +} +impl IglooTarget +{ + fn _default() -> IglooTarget + { + IglooTarget + { + root: std::path::PathBuf::default(), + makefile: HashMap::new(), + config: IglooTargetConfig::_default(), + } + } /// takes the targets name and looks up the path /// deserializes the targets manifest file and creates the target - pub fn target_from_name(igloo: &Igloo, name: String) -> Result + pub fn target_from_name(prj: &IglooProject, name: String) -> Result { - let target_path = igloo + let target_path = prj + .igloo .env .esfd .clone() - .join(&igloo.master_target_manifest.targets[&name]); + .join(&prj.igloo.master_target_manifest.targets[&name]); // We have to read in the file first so we can replace all variables with values let targ_templ = match std::fs::read_to_string(&target_path) @@ -90,14 +113,25 @@ impl IglooTarget // get [esf] (which is technically a table...) from our config let target_table: config::Value = target_config.get("esf").unwrap(); - // turn it into an IglooTarget - let ret_target = target_table.try_into::().unwrap(); + // turn it into an IglooTargetConfig + let ret_target_config = target_table.try_into::().unwrap(); + + // Finally, create our IglooTarget + let mut ret_target = IglooTarget + { + root: prj.root.clone() + .join("igloo") + .join("targets") + .join(&name), + config: ret_target_config, + makefile: HashMap::new(), + }; + ret_target.collect_makefile(prj); igloo_debug!(INFO, IS_NONE, "Found Igloo target and deserialized it: {:?}", ret_target); - Ok(ret_target) } @@ -107,14 +141,29 @@ impl IglooTarget { let mut ret = IS_GOOD; + if !self.root.exists() + { + // Make self target dir + match std::fs::create_dir_all(&self.root) + { + Ok(_v) => (), + Err(e) => + { + ret = IS_FAILED_TO_CREATE_DIR; + igloo_debug!(ERROR, ret, "Failed to create {} -- {}", self.root.to_str().unwrap(), e); + return ret + } + } + } + + ret = self.generate_makefile(project); ret } - /* pub fn generate_makefile(&self, project: &IglooProject) -> IglooStatus { let mut ret = IS_GOOD; - let target_root = project.root.join(self.name); + let target_root = self.root.clone(); // If the Makefile already exists, trash it if target_root.join("Makefile").exists() { @@ -131,46 +180,47 @@ impl IglooTarget // writeln!(app_file, "# ePenguin Generated Variables").unwrap(); writeln!(app_file, "PROJECT_NAME={}", project.config.profile.name).unwrap(); - writeln!(app_file, "TARGET_NAME={}", self.name).unwrap(); - - let makefile: HashMap = HashMap::new(); + writeln!(app_file, "TARGET_NAME={}", self.config.name).unwrap(); - match project.igloo.master_make_manifest.get("TOOLCHAIN") + loop { - None => + ret = self.makefile_write_var( + "TOOLCHAIN", + &mut app_file); + if ret != IS_GOOD { - println!("TOOLCHAIN Not found"); + break; } - Some(v) => + ret = self.makefile_write_var( + "CC", + &mut app_file); + if ret != IS_GOOD { - write!(app_file, "TOOLCHAIN=").unwrap(); - writeln!(app_file, "{}", v.to_string()).unwrap(); - }, - } - match project.igloo.master_make_manifest.get("CC") - { - None => - { - println!("CC Not found"); + break; } - Some(v) => + ret = self.makefile_write_var( + "CXX", + &mut app_file); + if ret != IS_GOOD { - write!(app_file, "CC=").unwrap(); - writeln!(app_file, "{}", v.to_string()).unwrap(); - }, - } - match project.igloo.master_make_manifest.get("CXX") - { - None => - { - println!("CXX Not found"); + break; } - Some(v) => + + ret = self.makefile_write_var( + "ELF_FLAGS", + &mut app_file); + if ret != IS_GOOD { - write!(app_file, "CXX=").unwrap(); - writeln!(app_file, "{}", v.to_string()).unwrap(); - }, - } + break; + } + + break;} + writeln!(app_file, "\n\nQUOTE:=\"").unwrap(); + ret + } + /* + + match project.igloo.master_make_manifest.get("OBJCOPY") { None => @@ -842,8 +892,112 @@ endif\n").unwrap(); }, } - writeln!(app_file, "\n\nQUOTE:=\"").unwrap(); - IS_GOOD + */ + + fn makefile_write_var(&self, + name: &str, + makefile: &mut std::fs::File) -> IglooStatus + { + let mut ret: IglooStatus = IS_GOOD; + println!("PRINTING MAKEFILE {:?}", self.makefile); + match self.makefile.get(name) + { + None => + { + ret = IS_FAILED_TO_EXTRACT_MF_VAR; + igloo_debug!(WARNING, ret, "Failed to write make var {} -- wasn't found", name); + } + Some(v) => + { + write!(makefile, "\n{}", String::from(name) + "=").unwrap(); + match v.clone().into_array() + { + Ok(arr) => + { + // is an array + for element in arr + { + writeln!(makefile, " \\").unwrap(); + write!(makefile, "{}", element).unwrap(); + } + } + Err(e) => + { + // not an array + write!(makefile, "{}", v.clone().into_str().unwrap()); + } + } + }, + } + ret + } + + // fn makefile_write_rule(targ: &str, makefile_manifest: &config::Config, makefile: &std::fs::File) + // { + + // match project.igloo.master_make_manifest.get("PUSH_CMDS") + // { + // None => + // { + // println!("PUSH_CMDS Not found"); + // } + // Some(v) => + // { + // write!(app_file, "\n").unwrap(); + // for cflag in v.clone().into_array().unwrap() + // { + // if !cflag.to_string().is_empty() + // { + // writeln!(app_file, "\t{}", cflag).unwrap() + // } + // } + // }, + // } + // } + + pub fn collect_makefile(&mut self, project: &IglooProject) -> IglooStatus + { + let mut ret: IglooStatus = IS_GOOD; + + let (dummy, arch, family, mcu_name) = sscanf::scanf!( + self.config.series, "{}.{}.{}.{}", String, String, String, String).unwrap(); + let mut make_table_head = &self.config.series[0..self.config.series.len()]; + let mut b_quit: bool = false; + loop + { + let mut _active_table = project.igloo.master_make_manifest.get_table(&make_table_head).unwrap(); + for(name, val) in _active_table + { + match val.clone().into_table() + { + // I have no idea why I did this in this way. Need to revisit... + Err(_e) => + { + if !self.makefile.contains_key(&name) + { + self.makefile.insert(name, val); + } + else + { + let mut newval = val.clone().into_array().unwrap(); + let mut newvec = self.makefile.get_key_value(&name).unwrap().1.clone().into_array().unwrap(); + newvec.append(&mut newval); + self.makefile.insert(name, config::Value::from(newvec)); + } + } + Ok(_v) => (), + } + } + match make_table_head.rfind('.') + { + None => b_quit = true, + Some(v) => make_table_head = &make_table_head[0..v], + } + if b_quit + { + break; + } + } + ret } - */ } diff --git a/igloo_core/src/lib.rs b/igloo_core/src/lib.rs index aa4f293..965dc3b 100644 --- a/igloo_core/src/lib.rs +++ b/igloo_core/src/lib.rs @@ -1,5 +1,5 @@ -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] +// #![allow(non_snake_case)] +// #![allow(non_camel_case_types)] pub extern crate clap; pub extern crate config; @@ -24,7 +24,7 @@ use igloo_project::IglooProject; use igloo_manifest::IglooTargetManifest; #[macro_use] extern crate igloo_util; -use igloo_util::IglooDebugSeverity::{self, *}; +use igloo_util::IglooDebugSeverity::*; use igloo_util::IglooStatus::{self, *}; use igloo_util::IglooType::{self, *}; use igloo_util::TRACE_LEVEL; @@ -53,8 +53,6 @@ impl Igloo pub fn start(&mut self) -> Result { - let mut res: IglooType = IT_NULL; - // get master target manifest self.master_target_manifest = IglooTargetManifest::get(self).unwrap(); diff --git a/igloo_util/src/lib.rs b/igloo_util/src/lib.rs index ad0f220..3271394 100644 --- a/igloo_util/src/lib.rs +++ b/igloo_util/src/lib.rs @@ -59,6 +59,8 @@ pub enum IglooStatus IS_NEW_DIR_ALREADY_EXISTS = 0x05, IS_FAILED_TO_CREATE_PRJ_CFG_FILE = 0x06, IS_FAILED_TO_CREATE_DIR = 0x07, + IS_FAILED_TO_EXTRACT_MF_VAR = 0x08, + IS_FAILED_TO_WRITE_MF_VAR = 0x09, IS_NONE = 0xFF, } diff --git a/projecttest/igloo/igloo.toml b/projecttest/igloo/igloo.toml new file mode 100644 index 0000000..ea6d32c --- /dev/null +++ b/projecttest/igloo/igloo.toml @@ -0,0 +1,3 @@ +[profile] +name = "projecttest" +targets = ["samd21j18a"] diff --git a/projecttest/igloo/targets/samd21j18a/Makefile b/projecttest/igloo/targets/samd21j18a/Makefile new file mode 100644 index 0000000..5e9fe8f --- /dev/null +++ b/projecttest/igloo/targets/samd21j18a/Makefile @@ -0,0 +1,15 @@ +# ePenguin Generated Variables +PROJECT_NAME=projecttest +TARGET_NAME=samd21j18a + +TOOLCHAIN=arm-none-eabi +ELF_FLAGS= \ +-Wl,--start-group -l m \ +-Wl,--end-group -mthumb \ +-Wl,-Map=$(QUOTE)$(PROJECT_NAME).map$(QUOTE) \ +--specs=nano.specs \ +-Wl,--gc-sections \ +-T$(QUOTE)$(LD_SCRIPT)$(QUOTE) \ +-L$(QUOTE)$(LD_PATH)$(QUOTE) + +QUOTE:=" diff --git a/src/main.rs b/src/main.rs index eefcb28..2f48fb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ fn main() { match ig.run(it) { + IS_GOOD => (), // this is actually so dumb and should not exist in any language ANYTHING_ELSE => igloo_debug!(ERROR, ANYTHING_ELSE),