custom format strings
This commit is contained in:
parent
9a96f4dfb6
commit
3363b23335
6 changed files with 71 additions and 11 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -86,6 +86,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"serde",
|
"serde",
|
||||||
|
"strfmt",
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -136,6 +137,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strfmt"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.52"
|
version = "2.0.52"
|
||||||
|
|
|
@ -8,4 +8,5 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.1", features = ["derive", "std", "help", "usage"], default-features = false }
|
clap = { version = "4.5.1", features = ["derive", "std", "help", "usage"], default-features = false }
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
|
strfmt = "0.2.4"
|
||||||
toml = "0.8.10"
|
toml = "0.8.10"
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::fmt::Display;
|
||||||
|
|
||||||
pub enum ErrorKind {
|
pub enum ErrorKind {
|
||||||
NoSources,
|
NoSources,
|
||||||
|
FormatError,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::BufWriter;
|
use std::io::BufWriter;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use strfmt::strfmt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parse_deser::*;
|
use crate::parse_deser::*;
|
||||||
use crate::Args;
|
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();
|
let mut ret = "".to_string();
|
||||||
ret.push_str(&format!(
|
ret.push_str(&format!(
|
||||||
"## Generated by ngen
|
"## Generated by ngen
|
||||||
|
@ -52,7 +54,7 @@ build {0}: regen_ninjafile {1} || $builddir/compile_commands.json
|
||||||
Ok(ret)
|
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 {
|
if target.sources.len() == 0 {
|
||||||
return Err(Error {
|
return Err(Error {
|
||||||
kind: ErrorKind::NoSources,
|
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_flags = target.linker_flags.join(" ");
|
||||||
let linker_libs = target.linker_libs.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!(
|
ret.push_str(&format!(
|
||||||
"\
|
"\
|
||||||
# BEGIN TARGET {0}
|
# BEGIN TARGET {name}
|
||||||
rule cc_{0}
|
rule cc_{name}
|
||||||
deps = gcc
|
deps = gcc
|
||||||
depfile = $dep
|
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
|
description = Building $in -> $out
|
||||||
rule link_{name}
|
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
|
description = Linking $out
|
||||||
|
|
||||||
build $builddir/{0}/obj: mkdir
|
build $builddir/{name}/obj: mkdir
|
||||||
build $builddir/{0}/dep: 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();
|
let mut object_list: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
@ -127,7 +164,6 @@ pub fn create_ninja_file_content(
|
||||||
Ok(v) => ret.push_str(&v),
|
Ok(v) => ret.push_str(&v),
|
||||||
Err(e) => match e.kind {
|
Err(e) => match e.kind {
|
||||||
ErrorKind::NoSources => eprintln!("WARNING: {e}. Skipping `{}`", name),
|
ErrorKind::NoSources => eprintln!("WARNING: {e}. Skipping `{}`", name),
|
||||||
#[allow(unreachable_patterns)]
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ pub struct DeserTargetOptions {
|
||||||
pub inherit_from: Option<String>,
|
pub inherit_from: Option<String>,
|
||||||
pub depend_on: Option<Vec<String>>,
|
pub depend_on: Option<Vec<String>>,
|
||||||
pub default: Option<bool>,
|
pub default: Option<bool>,
|
||||||
|
pub compile_cmd_fmt: Option<String>,
|
||||||
|
pub link_cmd_fmt: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
|
|
@ -6,6 +6,8 @@ pub struct TargetOptions<'a> {
|
||||||
pub inherit_from: &'a str,
|
pub inherit_from: &'a str,
|
||||||
pub default: bool,
|
pub default: bool,
|
||||||
pub depend_on: Vec<&'a str>,
|
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> {
|
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
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +51,9 @@ impl<'a> TargetOptions<'a> {
|
||||||
inherit_from: "main",
|
inherit_from: "main",
|
||||||
default: false,
|
default: false,
|
||||||
depend_on: vec![],
|
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}",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue