-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.rs
83 lines (69 loc) · 2.55 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::env;
use std::error::Error;
use std::fs;
use std::io;
use std::path::PathBuf;
use glob::glob;
use regex::{Captures, Regex};
struct JunosVersion {
major: usize,
minor: usize,
}
impl JunosVersion {
fn from_captures(caps: Captures<'_>) -> Option<Self> {
let get = |name| caps.name(name).and_then(|m| m.as_str().parse().ok());
let (major, minor) = (get("major")?, get("minor")?);
Some(Self { major, minor })
}
fn paths(&self, suffix: &str) -> Result<Vec<PathBuf>, Box<dyn Error>> {
let pattern = format!("protos/{}.{}/**/2/{suffix}", self.major, self.minor);
Ok(glob(&pattern)?.collect::<Result<_, _>>()?)
}
fn out_dir(&self) -> Result<PathBuf, Box<dyn Error>> {
let path = env::var("OUT_DIR")
.map(PathBuf::from)
.map(|base| base.join(format!("junos_{}_{}", self.major, self.minor)))?;
fs::create_dir(&path).or_else(|err| match err.kind() {
io::ErrorKind::AlreadyExists => Ok(()),
_ => Err(err),
})?;
Ok(path)
}
fn compile_protos(&self) -> Result<(), Box<dyn Error>> {
// create the version specific output directory
let out_dir = self.out_dir()?;
// construct the paths to the `*.proto` files and includes directory
let includes = self.paths("")?;
let protos = self.paths("*.proto")?;
// configure prost source code generator
let config = {
let mut config = prost_build::Config::new();
config.disable_comments([".jnx.jet.routing.base.AsPath"]);
config
};
// compile the protobuf definitions into rust source code
tonic_build::configure()
.build_server(false)
.out_dir(out_dir)
.include_file("jnx.jet.rs")
.compile_with_config(config, &protos, &includes)?;
Ok(())
}
}
fn main() -> Result<(), Box<dyn Error>> {
// build a `Vec` of requested `junos-*` features
let feature_re = Regex::new(r"^CARGO_FEATURE_JUNOS_(?P<major>\d+)_(?P<minor>\d+)$")?;
let versions = env::vars()
.filter_map(|(key, _)| {
feature_re
.captures(&key)
.and_then(JunosVersion::from_captures)
})
.collect::<Vec<_>>();
// check that we have at least one "version" feature enabled
if versions.is_empty() {
return Err("At least one `junos-X-Y` feature must be enabled".into());
}
// compile the versioned protobuf definitions
versions.iter().try_for_each(JunosVersion::compile_protos)
}