From 4565b9cc3e5c15d68af458da4d1e14a757fe0f79 Mon Sep 17 00:00:00 2001 From: Guilleag01 Date: Tue, 18 Feb 2025 21:30:24 +0100 Subject: [PATCH] initial commit --- .gitignore | 1 + Cargo.lock | 392 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 11 ++ src/compiler.rs | 304 +++++++++++++++++++++++++++++++++++++ src/config.rs | 20 +++ src/lib.rs | 2 + src/main.rs | 119 +++++++++++++++ 7 files changed, 849 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/compiler.rs create mode 100644 src/config.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2bc57b3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,392 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys", +] + +[[package]] +name = "boat" +version = "0.1.0" +dependencies = [ + "clap", + "lazy_static", + "regex", + "serde", + "toml", +] + +[[package]] +name = "clap" +version = "4.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c386e5c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "boat" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.30", features = ["derive"] } +lazy_static = "1.5.0" +regex = "1.11.1" +serde = { version = "1.0.217", features = ["derive"] } +toml = "0.8.20" diff --git a/src/compiler.rs b/src/compiler.rs new file mode 100644 index 0000000..f12ca67 --- /dev/null +++ b/src/compiler.rs @@ -0,0 +1,304 @@ +use lazy_static::lazy_static; +use regex::Regex; +use std::process::Command; +use std::{collections::HashSet, fs, path}; + +use crate::config::Config; + +pub struct Compiler { + config: Config, + path: String, + src_files: Vec, + header_files: Vec, + needed_src: Vec, + inc_dirs: Vec, +} + +impl Compiler { + pub fn new( + config: Config, + path: String, + src_files: Vec, + header_files: Vec, + ) -> Self { + Self { + config, + path, + src_files, + header_files, + needed_src: Vec::new(), + inc_dirs: Vec::new(), + } + } + + pub fn prepare(&mut self) { + let (needed_src, inc_dirs) = self.get_needed_files(); + self.needed_src = needed_src; + self.inc_dirs = inc_dirs; + } + + pub fn compile(&self, verbose: bool) { + let mut o_s: Vec = Vec::new(); + + for file in self.needed_src.clone() { + let o_file = format!("{}.o", file.split(".").collect::>()[0]); + let o_path = path::Path::new(&o_file); + let mut o_comp = o_path.components(); + o_comp.next(); + + let o_path_dir = path::Path::new(&self.path) + .join(&self.config.build.build_dir) + .join(o_comp.as_path()); + + let o_path_strip = o_path_dir.to_str().unwrap(); + + println!("Compiling {}", file); + + let mut c_path = path::Path::new(&file).parent().unwrap().components(); + c_path.next(); + + let c_path_full = path::Path::new(&self.path) + .join(self.config.build.build_dir.clone()) + .join(c_path.as_path()); + + let mkdir_command = format!("mkdir -p {}", c_path_full.to_str().unwrap()); + + Command::new("sh") + .arg("-c") + .arg(mkdir_command) + .output() + .unwrap(); + + // TODO: PRINT WHEN VERBOSE + + let command = format!( + "{} {} -c {} {} -o {}", + self.config.build.cc, + self.config.build.cflags, + file.clone(), + self.get_inc_string(), + o_path_strip + ); + + if verbose { + println!("{}", command); + } + + o_s.push(o_path_strip.to_string()); + + let out = Command::new("sh").arg("-c").arg(command).output().unwrap(); + + let stdout = std::str::from_utf8(&out.stdout).unwrap(); + let stderr = std::str::from_utf8(&out.stderr).unwrap(); + + if !stdout.is_empty() { + println!("{}", stdout); + } + if !stderr.is_empty() { + println!("{}", stderr); + } + } + + let mut link_command = format!( + "{} {}", + self.config.build.cc.clone(), + self.config.build.cflags + ); + + for o_file in o_s { + link_command = format!("{} {}", link_command, o_file); + } + + let target_path = path::Path::new(&self.path).join(&self.config.general.target); + + link_command = format!( + "{} {} -o {}", + link_command, + self.get_inc_string(), + target_path.to_str().unwrap() + ); + + println!("Building {}", target_path.to_str().unwrap()); + + if verbose { + println!("{}", link_command); + } + + let out = Command::new("sh") + .arg("-c") + .arg(link_command) + .output() + .unwrap(); + + let stdout = std::str::from_utf8(&out.stdout).unwrap(); + let stderr = std::str::from_utf8(&out.stderr).unwrap(); + + if !stdout.is_empty() { + println!("{}", stdout); + } + if !stderr.is_empty() { + println!("{}", stderr); + } + } + + pub fn get_needed_files(&self) -> (Vec, Vec) { + let mut scanned_files = Vec::new(); + + let (mut src_file, header_files) = self.get_needed_files_recursive( + path::Path::new(self.path.as_str()) + .join(self.config.general.main.clone()) + .to_str() + .unwrap() + .to_string(), + &mut scanned_files, + ); + src_file.push( + path::Path::new(self.path.as_str()) + .join(self.config.general.main.clone()) + .to_str() + .unwrap() + .to_string(), + ); + (src_file, header_files) + } + + fn get_needed_files_recursive( + &self, + file: String, + scanned_files: &mut Vec, + ) -> (Vec, Vec) { + let file_path = path::Path::new(file.as_str()); + + let contents = fs::read_to_string(file_path) + .unwrap_or_else(|_| panic!("Couldn't read {}", file_path.to_str().unwrap())); + + lazy_static! { + static ref RE: Regex = Regex::new(r#"#include (<\w+.h>|\"\w+\.h\")"#).unwrap(); + } + + let mut header_paths: HashSet = HashSet::new(); + let mut src_paths: HashSet = HashSet::new(); + + let headers_names = self + .header_files + .iter() + .map(|name| { + path::Path::new(name.as_str()) + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string() + }) + .collect::>(); + + let src_names = self + .src_files + .iter() + .map(|name| { + path::Path::new(name.as_str()) + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string() + }) + .collect::>(); + + let finds = RE + .find_iter(&contents) + .map(|f| f.as_str()[10..f.len() - 1].to_string()) + .collect::>(); + + // let mut scanned_files = Vec::new(); + + for find in finds.clone() { + // let find_name = fin[10..find.len() - 1].to_string(); + + if headers_names.contains(&find) { + let h_path = path::Path::new( + self.header_files[headers_names.iter().position(|e| *e == find).unwrap()] + .as_str(), + ); + + let h_dir = h_path.parent().unwrap().to_str().unwrap().to_string(); + + header_paths.insert(h_dir.clone()); + + if !scanned_files.contains(&h_path.to_str().unwrap().to_string()) { + scanned_files.push(h_path.to_str().unwrap().to_string()); + let (recursive_src, recursive_header) = self.get_needed_files_recursive( + h_path.to_str().unwrap().to_string(), + scanned_files, + ); + + for e in recursive_src { + src_paths.insert(e); + } + for e in recursive_header { + header_paths.insert(e); + } + } + } + + let h_to_c = format!("{}.c", find.split(".").collect::>()[0]); + + if src_names.contains(&h_to_c) { + let c_path = + self.src_files[src_names.iter().position(|e| *e == h_to_c).unwrap()].clone(); + + src_paths.insert(c_path.clone()); + + if !scanned_files.contains(&c_path) { + scanned_files.push(c_path.clone()); + + let (recursive_src, recursive_header) = + self.get_needed_files_recursive(c_path.clone(), scanned_files); + + for e in recursive_src { + src_paths.insert(e); + } + for e in recursive_header { + header_paths.insert(e); + } + } + } + } + + // println!("finds: \n{:?}", src_names); + + ( + src_paths.iter().cloned().collect::>(), + header_paths.iter().cloned().collect::>(), + ) + } + + pub fn clean(&self) { + let build_dir = path::Path::new(&self.path).join(self.config.build.build_dir.clone()); + let target_path = path::Path::new(&self.path).join(self.config.general.target.clone()); + println!("Removing dir {}", build_dir.to_str().unwrap()); + fs::remove_dir_all(build_dir).unwrap(); + println!("Removing file {}", target_path.to_str().unwrap()); + fs::remove_file(target_path).unwrap(); + } + + pub fn run(&self) { + let target_path = path::Path::new(&self.path).join(self.config.general.target.clone()); + println!("Running {}", target_path.to_str().unwrap()); + Command::new("sh") + .arg("-c") + .arg(format!("./{}", target_path.to_str().unwrap()).as_str()) + .output() + .unwrap(); + } + + fn get_inc_string(&self) -> String { + let mut inc_string = "".to_string(); + + for inc_dir in self.inc_dirs.clone() { + inc_string = format!("{} -I{}", inc_string, inc_dir); + } + + inc_string + } +} diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..747fe8c --- /dev/null +++ b/src/config.rs @@ -0,0 +1,20 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct Config { + pub general: General, + pub build: Build, +} + +#[derive(Debug, Deserialize)] +pub struct General { + pub target: String, + pub main: String, +} + +#[derive(Debug, Deserialize)] +pub struct Build { + pub build_dir: String, + pub cc: String, + pub cflags: String, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0831c01 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod compiler; +pub mod config; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ed9bf9e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,119 @@ +use std::{ + fmt::Display, + fs, + path::{self, Path}, +}; + +use boat::{compiler::Compiler, config::Config}; +use clap::Parser; + +#[derive(clap::ValueEnum, Clone, Debug)] +enum Modes { + Build, + Clean, + Run, +} + +impl Display for Modes { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Modes::Build => f.write_str("build"), // "build".to_string(), + Modes::Clean => f.write_str("clean"), + Modes::Run => f.write_str("run"), + } + } +} + +// impl ToString for Modes { +// fn to_string(&self) -> String { +// match self { +// Modes::Build => "build".to_string(), +// Modes::Clean => "clean".to_string(), +// Modes::Run => "run".to_string(), +// } +// } +// } + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct Args { + /// Verbose + #[arg(short, long, default_value_t = false)] + verbose: bool, + + /// Mode + #[arg( default_value_t = Modes::Build)] + mode: Modes, + + /// Path of the directory to list + #[arg(default_value_t = String::from("."))] + path: String, +} + +fn main() { + let args = Args::parse(); + let conf_path = path::Path::new(args.path.as_str()).join("c_config.toml"); + + let contents = fs::read_to_string(conf_path.clone()) + .unwrap_or_else(|_| panic!("Couldn't read {}", conf_path.to_str().unwrap())); + + let config: Config = toml::from_str(&contents).unwrap(); + + // println!("{:?}", config); + + let (src_files, header_files) = get_file_list(&args.path).expect("Error while readig files"); + + // println!("{:?}, {:?}", src_files, header_files); + + let mut compiler = Compiler::new(config, args.path, src_files, header_files); + + match args.mode { + Modes::Build => { + compiler.prepare(); + compiler.compile(args.verbose); + } + Modes::Clean => compiler.clean(), + Modes::Run => { + compiler.prepare(); + compiler.compile(args.verbose); + compiler.run(); + } + } +} + +fn get_file_list(path_str: &str) -> Result<(Vec, Vec), std::io::Error> { + let path = Path::new(path_str); + let mut src_files = Vec::new(); + let mut header_files = Vec::new(); + + if path.is_dir() { + for entry in std::fs::read_dir(path_str)? { + let entry = entry?; + + if entry.path().is_dir() { + let (mut r_src_files, mut r_header_files) = + get_file_list(entry.path().to_str().unwrap())?; + + header_files.append(&mut r_header_files); + src_files.append(&mut r_src_files); + } + + let f_name = entry.path().to_str().unwrap().to_string(); + + match f_name.as_str().split(".").last().unwrap() { + "h" => header_files.push(f_name), + "c" => src_files.push(f_name), + _ => (), + } + + // files.push(); + } + } else { + return Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "The path is not a valid directory.", + )); + } + + Ok((src_files, header_files)) +}