diff --git a/src/file_writing/compile_commands.rs b/src/file_writing/compile_commands.rs index e69de29..3c5e979 100644 --- a/src/file_writing/compile_commands.rs +++ b/src/file_writing/compile_commands.rs @@ -0,0 +1,50 @@ +use std::path::Path; + +use crate::parsed_config_processing::*; + +use super::*; + +pub fn gen_compile_commands( + name: &str, + target: &Target, + config: &ConfigTable, +) -> Result { + let mut ret = "[\n".to_string(); + + let compiler_flags = target.compiler_flags.join(" "); + + let pwd = Path::new("."); + let pwd = pwd.canonicalize().unwrap(); + let pwd = pwd.to_str().unwrap(); + + if target.sources.len() == 0 { + return Err(ContentGenerationError { + message: format!( + "compile_commands_target is set to `{0}`, however `{0}` has no sources.", + name + ), + }); + } + + for (i, source) in target.sources.iter().enumerate() { + let new_file = source.replace("/", "-"); + let obj_name = format!("{}/{}/obj/{}.o", config.build_dir, name, new_file); + + ret.push_str(&format!( + " {{ + \"directory\": \"{0}\", + \"command\": \"{1} {2} -o {3} -c {4}\", + \"file\": \"{4}\" + }}", + pwd, target.compiler, compiler_flags, obj_name, source + )); + if i != target.sources.len() - 1 { + ret.push(','); + } + ret.push('\n'); + } + + ret.push_str("]\n"); + + Ok(ret) +} diff --git a/src/file_writing/content_generation_error.rs b/src/file_writing/content_generation_error.rs new file mode 100644 index 0000000..1e55f34 --- /dev/null +++ b/src/file_writing/content_generation_error.rs @@ -0,0 +1,11 @@ +use std::fmt::Display; + +pub struct ContentGenerationError { + pub message: String, +} + +impl Display for ContentGenerationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "content generation error: {}", self.message) + } +} diff --git a/src/file_writing/mod.rs b/src/file_writing/mod.rs index 9ad1f1a..f306caa 100644 --- a/src/file_writing/mod.rs +++ b/src/file_writing/mod.rs @@ -1,5 +1,7 @@ pub mod compile_commands; +pub mod content_generation_error; pub mod ninja_file; pub use compile_commands::*; +pub use content_generation_error::*; pub use ninja_file::*; diff --git a/src/file_writing/ninja_file.rs b/src/file_writing/ninja_file.rs index 55a16be..984958b 100644 --- a/src/file_writing/ninja_file.rs +++ b/src/file_writing/ninja_file.rs @@ -1,18 +1,7 @@ -use std::fmt::Display; - +use super::*; use crate::parsed_config_processing::*; use crate::Args; -pub struct ContentGenerationError { - pub message: String, -} - -impl Display for ContentGenerationError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "content generation error: {}", self.message) - } -} - pub fn gen_ninja_header(config: &ConfigTable, cmdline_args: &Args) -> String { let mut ret = "".to_string(); ret.push_str(&format!( diff --git a/src/main.rs b/src/main.rs index 7cee5b4..f199109 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use core::panic; use std::collections::HashMap; use std::fs::{read_to_string, OpenOptions}; use std::io::{BufWriter, Write}; +use std::process::exit; mod ngen_toml; use ngen_toml::*; @@ -36,26 +37,20 @@ fn main() { let toml_config: NgenToml = toml::from_str(&config_file) .unwrap_or_else(|e| panic!("error parsing config file `{}`: {e}", args.config_file)); - let config_table: ConfigTable; - match &toml_config.config { - Some(v) => { - config_table = ConfigTable::from_parsed_config(&v).unwrap_or_else(|e| panic!("{e}")) - } - None => config_table = ConfigTable::get_default(), - } + let config_table: ConfigTable = match &toml_config.config { + Some(v) => ConfigTable::from_parsed_config(&v).unwrap_or_else(|e| panic!("{e}")), + None => ConfigTable::get_default(), + }; - let all_parsed_targets: &HashMap; - match &toml_config.targets { - Some(v) => { - all_parsed_targets = v; - } + let all_parsed_targets: &HashMap = match &toml_config.targets { + Some(v) => v, None => panic!( "{}", ConfigurationError { message: "no targets found, nothing to do. Exiting".to_string() } ), - } + }; let mut sources_found = false; for target in all_parsed_targets.values() { @@ -92,6 +87,44 @@ fn main() { Err(e) => panic!("{e}"), } } + + if let Some(filename) = &args.write_compile_commands { + let target = match targets.get(config_table.compile_commands_target) { + Some(v) => v, + None => panic!( + "{}", + ContentGenerationError { + message: format!( + "compile_commands_target is set to `{0}`, however target `{0}` does not exist.", + config_table.compile_commands_target + ) + } + ), + }; + let compile_commands = match gen_compile_commands( + config_table.compile_commands_target, + &target, + &config_table, + ) { + Ok(v) => v, + Err(e) => panic!("{e}"), + }; + let mut comp_cmds_file = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(&filename) + .unwrap_or_else(|e| panic!("error opening compile commands file `{}`: {e}", filename)); + comp_cmds_file + .write_all(&compile_commands.as_bytes()) + .unwrap_or_else(|e| { + panic!("error writing to compile commands file `{}`: {e}", filename) + }); + + // no need to generate the ninja file + exit(0); + } + let ninjafile = OpenOptions::new() .write(true) .truncate(true)