custom format strings

This commit is contained in:
Noah Swerhun 2024-03-15 09:27:43 -05:00
parent 9a96f4dfb6
commit 3363b23335
6 changed files with 71 additions and 11 deletions

7
Cargo.lock generated
View file

@ -86,6 +86,7 @@ version = "0.1.0"
dependencies = [
"clap",
"serde",
"strfmt",
"toml",
]
@ -136,6 +137,12 @@ dependencies = [
"serde",
]
[[package]]
name = "strfmt"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65"
[[package]]
name = "syn"
version = "2.0.52"

View file

@ -8,4 +8,5 @@ edition = "2021"
[dependencies]
clap = { version = "4.5.1", features = ["derive", "std", "help", "usage"], default-features = false }
serde = { version = "1.0.197", features = ["derive"] }
strfmt = "0.2.4"
toml = "0.8.10"

View file

@ -2,6 +2,7 @@ use std::fmt::Display;
pub enum ErrorKind {
NoSources,
FormatError,
}
pub struct Error {

View file

@ -1,12 +1,14 @@
use std::collections::HashMap;
use std::fs::OpenOptions;
use std::io::BufWriter;
use std::io::Write;
use strfmt::strfmt;
use super::*;
use crate::parse_deser::*;
use crate::Args;
pub fn gen_ninja_header(config: &Config, cmdline_args: &Args) -> Result<String> {
fn gen_ninja_header(config: &Config, cmdline_args: &Args) -> Result<String> {
let mut ret = "".to_string();
ret.push_str(&format!(
"## Generated by ngen
@ -52,7 +54,7 @@ build {0}: regen_ninjafile {1} || $builddir/compile_commands.json
Ok(ret)
}
pub fn gen_ninja_target(name: &str, target: &Target) -> Result<String> {
fn gen_ninja_target(name: &str, target: &Target) -> Result<String> {
if target.sources.len() == 0 {
return Err(Error {
kind: ErrorKind::NoSources,
@ -66,23 +68,58 @@ pub fn gen_ninja_target(name: &str, target: &Target) -> Result<String> {
let linker_flags = target.linker_flags.join(" ");
let linker_libs = target.linker_libs.join(" ");
let mut fmt_args = HashMap::new();
fmt_args.insert("outfile".to_string(), "$out");
fmt_args.insert("compiler".to_string(), target.compiler);
fmt_args.insert("compiler_flags".to_string(), &compiler_flags);
fmt_args.insert("linker".to_string(), target.compiler);
fmt_args.insert("object".to_string(), "$out");
fmt_args.insert("objects".to_string(), "$in");
fmt_args.insert("source".to_string(), "$in");
fmt_args.insert("depfile".to_string(), "$dep");
fmt_args.insert("linker_flags".to_string(), &linker_flags);
fmt_args.insert("linker_libs".to_string(), &linker_libs);
ret.push_str(&format!(
"\
# BEGIN TARGET {0}
rule cc_{0}
# BEGIN TARGET {name}
rule cc_{name}
deps = gcc
depfile = $dep
command = {1} {2} -MD -MF $dep -o $out -c $in
command = "
));
match strfmt(target.opts.compile_cmd_fmt, &fmt_args) {
Ok(v) => ret.push_str(&v),
Err(e) => {
return Err(Error {
kind: ErrorKind::FormatError,
message: e.to_string(),
});
}
}
ret.push_str(&format!(
"
description = Building $in -> $out
rule link_{name}
command = {3} {4} -o $out $in {5}
command = "
));
match strfmt(target.opts.link_cmd_fmt, &fmt_args) {
Ok(v) => ret.push_str(&v),
Err(e) => {
return Err(Error {
kind: ErrorKind::FormatError,
message: e.to_string(),
});
}
}
ret.push_str(&format!(
"
description = Linking $out
build $builddir/{0}/obj: mkdir
build $builddir/{0}/dep: mkdir
build $builddir/{name}/obj: mkdir
build $builddir/{name}/dep: mkdir
",
name, target.compiler, compiler_flags, target.linker, linker_flags, linker_libs
"
));
let mut object_list: Vec<String> = Vec::new();
@ -127,7 +164,6 @@ pub fn create_ninja_file_content(
Ok(v) => ret.push_str(&v),
Err(e) => match e.kind {
ErrorKind::NoSources => eprintln!("WARNING: {e}. Skipping `{}`", name),
#[allow(unreachable_patterns)]
_ => {
return Err(e);
}

View file

@ -21,6 +21,8 @@ pub struct DeserTargetOptions {
pub inherit_from: Option<String>,
pub depend_on: Option<Vec<String>>,
pub default: Option<bool>,
pub compile_cmd_fmt: Option<String>,
pub link_cmd_fmt: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]

View file

@ -6,6 +6,8 @@ pub struct TargetOptions<'a> {
pub inherit_from: &'a str,
pub default: bool,
pub depend_on: Vec<&'a str>,
pub compile_cmd_fmt: &'a str,
pub link_cmd_fmt: &'a str,
}
impl<'a> From<&'a DeserTargetOptions> for TargetOptions<'a> {
@ -30,6 +32,14 @@ impl<'a> From<&'a DeserTargetOptions> for TargetOptions<'a> {
}
}
if let Some(v) = &value.compile_cmd_fmt {
ret.compile_cmd_fmt = v;
}
if let Some(v) = &value.link_cmd_fmt {
ret.link_cmd_fmt = v;
}
ret
}
}
@ -41,6 +51,9 @@ impl<'a> TargetOptions<'a> {
inherit_from: "main",
default: false,
depend_on: vec![],
compile_cmd_fmt:
"{compiler} {compiler_flags} -MD -MF {depfile} -o {object} -c {source}",
link_cmd_fmt: "{linker} {linker_flags} -o {outfile} {objects} {linker_libs}",
}
}
}