breaking up generate_makefile() func into smaller parts... for better compile times

unstable
Penguin 2 years ago
parent 71d029f231
commit 4ddbf21ade

45
Cargo.lock generated

@ -93,6 +93,26 @@ dependencies = [
"yaml-rust", "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]] [[package]]
name = "directories" name = "directories"
version = "3.0.2" version = "3.0.2"
@ -173,6 +193,7 @@ dependencies = [
"directories", "directories",
"igloo_util", "igloo_util",
"serde 1.0.132", "serde 1.0.132",
"sscanf",
"toml", "toml",
] ]
@ -407,6 +428,30 @@ dependencies = [
"serde 1.0.132", "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]] [[package]]
name = "static_assertions" name = "static_assertions"
version = "1.1.0" version = "1.1.0"

@ -11,4 +11,5 @@ config = "0.11"
directories = "3.0.1" directories = "3.0.1"
toml = "0.5.8" toml = "0.5.8"
serde = { version = "1.0.132", features = ["derive"]} serde = { version = "1.0.132", features = ["derive"]}
sscanf = "0.1.2"
igloo_util = { path="../igloo_util" } igloo_util = { path="../igloo_util" }

@ -1,3 +1,4 @@
#![allow(warnings)]
use clap::ArgMatches; use clap::ArgMatches;
use igloo_util::IglooDebugSeverity::*; 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.config.add_target(initial_target);
prj.targets = Settings::get_targets_from_config(&prj); prj.targets = Settings::get_targets_from_config(&prj);
// Now populate // Now populate project files
ret = prj.generate(); ret = prj.generate();
if ret != IS_GOOD if ret != IS_GOOD
{ {
@ -118,31 +119,21 @@ pub fn ia_new(igloo: &Igloo, project_name: String, initial_target: String) -> Ig
return ret return ret
} }
ret = prj.generate_igloo_header(); // now do target folders
ret = prj.generate_targets();
if ret != IS_GOOD if ret != IS_GOOD
{ {
igloo_debug!(ERROR, ret); igloo_debug!(WARNING, ret);
return 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 ret
} }
/// Debugging function to make sure projects are being loaded correctly /// Debugging function to make sure projects are being loaded correctly
pub fn ia_debug(igloo: &Igloo) -> IglooStatus pub fn ia_debug(igloo: &Igloo) -> IglooStatus
{ {
let mut ret = IS_GOOD; let mut ret: IglooStatus = IS_GOOD;
ret ret
} }

@ -3,7 +3,7 @@ use crate::Igloo;
use crate::igloo_target::IglooTarget; use crate::igloo_target::IglooTarget;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::fs::{OpenOptions}; use std::io::prelude::*;
use igloo_util::IglooDebugSeverity::*; use igloo_util::IglooDebugSeverity::*;
use igloo_util::IglooStatus::{self, *}; use igloo_util::IglooStatus::{self, *};
use igloo_util::TRACE_LEVEL; use igloo_util::TRACE_LEVEL;
@ -70,16 +70,15 @@ impl Settings
.clone() .clone()
.join("igloo") .join("igloo")
.join("igloo.toml"); .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(); let contents = toml::to_string(&prj.config).unwrap();
igloo_debug!(TRACE, IS_NONE, "{}", contents); igloo_debug!(INFO, IS_NONE, "Project file to be written:\n{}", contents);
println!("PRINTING THIS ON ITS OWN: {}", 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 IglooStatus::IS_GOOD
} }
@ -99,7 +98,7 @@ impl Settings
let mut _targets: Vec<IglooTarget> = Vec::new(); let mut _targets: Vec<IglooTarget> = Vec::new();
for target in prj.config.profile.targets.iter() 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 _targets
} }
@ -110,6 +109,7 @@ pub struct IglooProject<'a>
pub igloo: &'a Igloo, pub igloo: &'a Igloo,
pub config: Settings, pub config: Settings,
pub targets: Vec::<IglooTarget>, pub targets: Vec::<IglooTarget>,
// $PWD/${PROJECT_NAME}
pub root: std::path::PathBuf, pub root: std::path::PathBuf,
} }
@ -180,104 +180,149 @@ impl<'a> IglooProject<'a>
// making this root and then cloning to work with active directory // 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 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 // so far i havent needed it so i may just remove this
let active_dir = self.root.clone(); let active_dir = self.root.clone();
// create new project directory loop
match std::fs::create_dir(&active_dir)
{ {
Err(e) => // create new project directory
match std::fs::create_dir(&active_dir)
{ {
ret = IS_FAILED_TO_CREATE_DIR; Err(e) =>
igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir, e); {
return ret ret = IS_FAILED_TO_CREATE_DIR;
igloo_debug!(ERROR,
ret,
"Failed to create dir: {:?} | {:?}",
&active_dir,
e);
break;
}
_ => (),
} }
_ => (),
}
// create igloo directory // create igloo directory
match std::fs::create_dir(&active_dir.clone().join("igloo")) match std::fs::create_dir(&active_dir.clone().join("igloo"))
{
Err(e) =>
{ {
ret = IS_FAILED_TO_CREATE_DIR; Err(e) =>
igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("igloo"), e); {
return ret 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"))
}
match std::fs::create_dir(&active_dir.clone().join("inc"))
{
Err(e) =>
{ {
ret = IS_FAILED_TO_CREATE_DIR; Err(e) =>
igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("inc"), e); {
return ret ret = IS_FAILED_TO_CREATE_DIR;
igloo_debug!(ERROR,
ret,
"Failed to create dir: {:?} | {:?}",
&active_dir.clone().join("inc"),
e);
break;
}
_ => (),
} }
_ => (),
}
// create src directory // create src directory
match std::fs::create_dir(&active_dir.clone().join("src")) match std::fs::create_dir(&active_dir.clone().join("src"))
{
Err(e) =>
{ {
ret = IS_FAILED_TO_CREATE_DIR; Err(e) =>
igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("src"), e); {
return ret 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")) match std::fs::create_dir(&active_dir.clone().join("cfg"))
{
Err(e) =>
{ {
ret = IS_FAILED_TO_CREATE_DIR; Err(e) =>
igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("cfg"), e); {
return ret 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")) match std::fs::create_dir(&active_dir.clone().join("esf"))
{
Err(e) =>
{ {
ret = IS_FAILED_TO_CREATE_DIR; Err(e) =>
igloo_debug!(ERROR, ret, "Failed to create dir: {:?} | {:?}", &active_dir.clone().join("esf"), e); {
return ret ret = IS_FAILED_TO_CREATE_DIR;
igloo_debug!(ERROR,
ret,
"Failed to create dir: {:?} | {:?}",
&active_dir.clone().join("esf"),
e);
break;
}
_ => (),
} }
_ => (),
}
// project folders finished // project folders finished
// create project settings file (igloo.toml) // create project settings file (igloo.toml)
ret = self.generate_project_config(); ret = self.generate_project_config();
if ret != IS_GOOD if ret != IS_GOOD
{ {
igloo_debug!(WARNING, ret); break;
return ret }
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 if ret != IS_GOOD
{ {
igloo_debug!(WARNING, ret); igloo_debug!(ERROR, ret);
return ret return 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 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 pub fn generate_igloo_header(&self) -> IglooStatus

@ -14,16 +14,18 @@
// structs, but this is honestly just a trash way of doing it and I think the idea // 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. // of doing it that way is only an ideal solution. It isn't very practical.
use igloo_util::*; use igloo_util::*;
use crate::Igloo;
use crate::IglooProject; use crate::IglooProject;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::vec::Vec; use std::vec::Vec;
use igloo_util::IglooDebugSeverity::*; use igloo_util::IglooDebugSeverity::*;
use igloo_util::IglooStatus::{self, *}; use igloo_util::IglooStatus::{self, *};
use igloo_util::TRACE_LEVEL; use igloo_util::TRACE_LEVEL;
use std::collections::HashMap;
use std::fs::OpenOptions;
use std::io::prelude::*;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct IglooTarget pub struct IglooTargetConfig
{ {
name: String, name: String,
common: String, common: String,
@ -35,11 +37,19 @@ pub struct IglooTarget
series: String, series: String,
} }
impl IglooTarget #[derive(Debug)]
pub struct IglooTarget
{ {
fn _default() -> IglooTarget root: std::path::PathBuf,
makefile: HashMap<String, config::Value>,
config: IglooTargetConfig,
}
impl IglooTargetConfig
{
fn _default() -> IglooTargetConfig
{ {
IglooTarget IglooTargetConfig
{ {
name: String::new(), name: String::new(),
common: String::new(), common: String::new(),
@ -51,16 +61,29 @@ impl IglooTarget
series: String::new(), 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 /// takes the targets name and looks up the path
/// deserializes the targets manifest file and creates the target /// deserializes the targets manifest file and creates the target
pub fn target_from_name(igloo: &Igloo, name: String) -> Result<IglooTarget, IglooStatus> pub fn target_from_name(prj: &IglooProject, name: String) -> Result<IglooTarget, IglooStatus>
{ {
let target_path = igloo let target_path = prj
.igloo
.env .env
.esfd .esfd
.clone() .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 // 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) 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 // get [esf] (which is technically a table...) from our config
let target_table: config::Value = target_config.get("esf").unwrap(); let target_table: config::Value = target_config.get("esf").unwrap();
// turn it into an IglooTarget // turn it into an IglooTargetConfig
let ret_target = target_table.try_into::<IglooTarget>().unwrap(); let ret_target_config = target_table.try_into::<IglooTargetConfig>().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, igloo_debug!(INFO,
IS_NONE, IS_NONE,
"Found Igloo target and deserialized it: {:?}", "Found Igloo target and deserialized it: {:?}",
ret_target); ret_target);
Ok(ret_target) Ok(ret_target)
} }
@ -107,14 +141,29 @@ impl IglooTarget
{ {
let mut ret = IS_GOOD; 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 ret
} }
/*
pub fn generate_makefile(&self, project: &IglooProject) -> IglooStatus pub fn generate_makefile(&self, project: &IglooProject) -> IglooStatus
{ {
let mut ret = IS_GOOD; 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 the Makefile already exists, trash it
if target_root.join("Makefile").exists() if target_root.join("Makefile").exists()
{ {
@ -131,46 +180,47 @@ impl IglooTarget
// //
writeln!(app_file, "# ePenguin Generated Variables").unwrap(); writeln!(app_file, "# ePenguin Generated Variables").unwrap();
writeln!(app_file, "PROJECT_NAME={}", project.config.profile.name).unwrap(); writeln!(app_file, "PROJECT_NAME={}", project.config.profile.name).unwrap();
writeln!(app_file, "TARGET_NAME={}", self.name).unwrap(); writeln!(app_file, "TARGET_NAME={}", self.config.name).unwrap();
let makefile: HashMap<String, config::Value> = HashMap::new();
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(); break;
writeln!(app_file, "{}", v.to_string()).unwrap();
},
}
match project.igloo.master_make_manifest.get("CC")
{
None =>
{
println!("CC Not found");
} }
Some(v) => ret = self.makefile_write_var(
"CXX",
&mut app_file);
if ret != IS_GOOD
{ {
write!(app_file, "CC=").unwrap(); break;
writeln!(app_file, "{}", v.to_string()).unwrap();
},
}
match project.igloo.master_make_manifest.get("CXX")
{
None =>
{
println!("CXX Not found");
} }
Some(v) =>
ret = self.makefile_write_var(
"ELF_FLAGS",
&mut app_file);
if ret != IS_GOOD
{ {
write!(app_file, "CXX=").unwrap(); break;
writeln!(app_file, "{}", v.to_string()).unwrap(); }
},
} break;}
writeln!(app_file, "\n\nQUOTE:=\"").unwrap();
ret
}
/*
match project.igloo.master_make_manifest.get("OBJCOPY") match project.igloo.master_make_manifest.get("OBJCOPY")
{ {
None => 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
} }
*/
} }

@ -1,5 +1,5 @@
#![allow(non_snake_case)] // #![allow(non_snake_case)]
#![allow(non_camel_case_types)] // #![allow(non_camel_case_types)]
pub extern crate clap; pub extern crate clap;
pub extern crate config; pub extern crate config;
@ -24,7 +24,7 @@ use igloo_project::IglooProject;
use igloo_manifest::IglooTargetManifest; use igloo_manifest::IglooTargetManifest;
#[macro_use] extern crate igloo_util; #[macro_use] extern crate igloo_util;
use igloo_util::IglooDebugSeverity::{self, *}; use igloo_util::IglooDebugSeverity::*;
use igloo_util::IglooStatus::{self, *}; use igloo_util::IglooStatus::{self, *};
use igloo_util::IglooType::{self, *}; use igloo_util::IglooType::{self, *};
use igloo_util::TRACE_LEVEL; use igloo_util::TRACE_LEVEL;
@ -53,8 +53,6 @@ impl Igloo
pub fn start(&mut self) -> Result<IglooType, IglooStatus> pub fn start(&mut self) -> Result<IglooType, IglooStatus>
{ {
let mut res: IglooType = IT_NULL;
// get master target manifest // get master target manifest
self.master_target_manifest = IglooTargetManifest::get(self).unwrap(); self.master_target_manifest = IglooTargetManifest::get(self).unwrap();

@ -59,6 +59,8 @@ pub enum IglooStatus
IS_NEW_DIR_ALREADY_EXISTS = 0x05, IS_NEW_DIR_ALREADY_EXISTS = 0x05,
IS_FAILED_TO_CREATE_PRJ_CFG_FILE = 0x06, IS_FAILED_TO_CREATE_PRJ_CFG_FILE = 0x06,
IS_FAILED_TO_CREATE_DIR = 0x07, IS_FAILED_TO_CREATE_DIR = 0x07,
IS_FAILED_TO_EXTRACT_MF_VAR = 0x08,
IS_FAILED_TO_WRITE_MF_VAR = 0x09,
IS_NONE = 0xFF, IS_NONE = 0xFF,
} }

@ -0,0 +1,3 @@
[profile]
name = "projecttest"
targets = ["samd21j18a"]

@ -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:="

@ -18,6 +18,7 @@ fn main()
{ {
match ig.run(it) match ig.run(it)
{ {
IS_GOOD => (), IS_GOOD => (),
// this is actually so dumb and should not exist in any language // this is actually so dumb and should not exist in any language
ANYTHING_ELSE => igloo_debug!(ERROR, ANYTHING_ELSE), ANYTHING_ELSE => igloo_debug!(ERROR, ANYTHING_ELSE),

Loading…
Cancel
Save