ngen/src/main.rs

101 lines
3.3 KiB
Rust

use core::panic;
use std::{collections::HashMap, env::args, fs::read_to_string, process::exit};
use clap::Parser;
mod content_generation;
mod deser;
mod parse_deser;
mod validation;
use content_generation::*;
use deser::*;
use parse_deser::*;
/// ngen is a build file generator for the ninja build system.
#[derive(Parser)]
struct Args {
/// Path to the toml configuration file
#[arg(short, long, default_value = "ngen.toml")]
config_file: String,
/// Path to generated ninja file
#[arg(short, long, default_value = "build.ninja")]
output_file: String,
#[arg(long, hide = true)]
write_compile_commands: Option<String>,
}
fn main() {
let args = Args::parse();
let ngen_toml = read_to_string(&args.config_file)
.unwrap_or_else(|e| panic!("error reading config file `{}`: {e}", args.config_file));
let deser_ngen_toml: DeserNgenToml = toml::from_str(&ngen_toml)
.unwrap_or_else(|e| panic!("error parsing config file `{}`: {e}", args.config_file));
let target_option_list: TargetOptionList;
let deser_target_list: &DeserTargetList;
match &deser_ngen_toml.targets {
Some(v) => {
target_option_list = TargetOptionList::from(v);
deser_target_list = &v;
}
None => panic!("no targets provided, nothing to do. Exiting"),
};
target_option_list
.check_for_dependency_cycle()
.unwrap_or_else(|e| panic!("{e}. cannont continue. Exiting"));
let inheritance_order = target_option_list
.get_inheritance_order()
.unwrap_or_else(|e| panic!("{e}. cannot continue. Exiting"));
let mut target_list: TargetList = TargetList(HashMap::new());
for order in &inheritance_order {
for name in order.into_iter().rev() {
let opts = target_option_list.0.get(name as &str).unwrap();
let deser = deser_target_list.get(name as &str).unwrap();
let parent: Option<&Target>;
if opts.inherit && (name != opts.inherit_from) {
parent = Some(target_list.0.get(opts.inherit_from as &str).unwrap());
} else {
parent = None;
}
target_list.0.insert(name, Target::new(opts, deser, parent));
}
}
target_list
.check_if_any_sources_are_provided()
.unwrap_or_else(|e| panic!("{e}, nothing to do. Exiting"));
let config = match &deser_ngen_toml.config {
Some(v) => Config::from(v),
None => Config::get_default(),
};
config
.check_compile_commands_target(&target_list)
.unwrap_or_else(|e| panic!("{e}"));
if let Some(filename) = &args.write_compile_commands {
let name = config.compile_commands_target;
let target = target_list.0.get(name).unwrap();
let content = create_compile_commands_content(name, target, &config)
.unwrap_or_else(|e| panic!("{e}"));
write_compile_commands(filename, content.as_bytes()).unwrap_or_else(|e| {
panic!("could not write compile commands file `{}`: {e}", filename)
});
exit(0);
}
let ninja_file_content =
create_ninja_file_content(&target_list, &config, &args).unwrap_or_else(|e| panic!("{e}"));
write_ninja_file(&args.output_file, ninja_file_content.as_bytes())
.unwrap_or_else(|e| panic!("could not write ninja file `{}`: {e}", args.output_file));
}