ngen/src/file_writing/ninja_file.rs
2024-03-11 22:08:03 -05:00

109 lines
2.9 KiB
Rust

use super::*;
use crate::parsed_config_processing::*;
use crate::Args;
pub fn gen_ninja_header(config: &ConfigTable, cmdline_args: &Args) -> String {
let mut ret = "".to_string();
ret.push_str(&format!(
"## Generated by ngen
## Do not modify by hand
builddir = {0}
rule mkdir
command = mkdir -p $out
description = Creating directory $out
rule regen_ninjafile
command = ngen -c $in -o $out
generator = 1
description = Regenerating $out
",
config.build_dir
));
if config.compile_commands {
ret.push_str(&format!(
"\
rule regen_compile_commands
command = ngen -c $in --write-compile-commands $out
description = Regenerating $out
build $builddir: mkdir
build $builddir/compile_commands.json: regen_compile_commands {1} || $builddir
pool = console
build {0}: regen_ninjafile {1} || $builddir/compile_commands.json
pool = console
",
cmdline_args.output_file, cmdline_args.config_file
));
} else {
ret.push_str(&format!(
"build {}: regen_ninjafile {}\n pool = console\n",
cmdline_args.output_file, cmdline_args.config_file
));
}
ret
}
pub fn gen_ninja_target(name: &str, target: &Target) -> Result<String, ContentGenerationError> {
if target.sources.len() == 0 {
return Err(ContentGenerationError {
message: format!("target `{}` has no sources", name),
});
}
let mut ret = "\n".to_string();
let compiler_flags = target.compiler_flags.join(" ");
let linker_flags = target.linker_flags.join(" ");
let linker_libs = target.linker_libs.join(" ");
ret.push_str(&format!(
"\
# BEGIN TARGET {0}
rule cc_{0}
deps = gcc
depfile = $dep
command = {1} {2} -MD -MF $dep -o $out -c $in
description = Building $in -> $out
rule link_{name}
command = {3} {4} -o $out $in {5}
description = Linking $out
build $builddir/{0}/obj: mkdir
build $builddir/{0}/dep: mkdir
",
name, target.compiler, compiler_flags, target.linker, linker_flags, linker_libs
));
let mut object_list: Vec<String> = Vec::new();
for source in &target.sources {
let new_file = source.replace("/", "-");
let obj_name = format!("$builddir/{}/obj/{}.o", name, new_file);
let dep_name = format!("$builddir/{}/dep/{}.o.d", name, new_file);
ret.push_str(&format!(
"build {}: cc_{} {}\n dep = {}\n",
obj_name, name, source, dep_name
));
object_list.push(obj_name);
}
ret.push_str(&format!(
"\nbuild $builddir/{0}/{1}: link_{0} ",
name, target.outfile
));
ret.push_str(&object_list.join(" "));
ret.push_str(&format!(
" || $builddir/{0}/obj $builddir/{0}/dep\nbuild {0}: phony $builddir/{0}/{1}\n",
name, target.outfile
));
if target.opts.default {
ret.push_str(&format!("\ndefault {}\n", name));
}
ret.push_str(&format!("# END TARGET {}\n", name));
Ok(ret)
}