-
Notifications
You must be signed in to change notification settings - Fork 41
/
build.rs
156 lines (141 loc) · 8.57 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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::io::Write;
const MIN: usize = 26;
const MAX: usize = 31;
println!("cargo::rerun-if-env-changed=K8S_OPENAPI_ENABLED_VERSION");
let enabled_version = {
let mut enabled_versions =
(MIN..=MAX).filter(|v| std::env::var(format!("CARGO_FEATURE_V1_{v}")).is_ok())
.chain(
std::env::var("K8S_OPENAPI_ENABLED_VERSION").ok()
.and_then(|value| value.strip_prefix("1.").and_then(|value| value.parse::<usize>().ok())))
.collect::<std::collections::BTreeSet<_>>()
.into_iter();
let v1 = enabled_versions.next().expect("\n\
None of the v1_* features are enabled on the k8s-openapi crate.\n\
\n\
The k8s-openapi crate requires a feature to be enabled to indicate which version of Kubernetes it should support.\n\
\n\
If you're using k8s-openapi in a binary crate, enable the feature corresponding to the minimum version of API server that you want to support. \
In case your binary crate does not directly depend on k8s-openapi, add a dependency on k8s-openapi and enable the corresponding feature in it.\n\
\n\
If you're using k8s-openapi in a library crate, add a dev-dependency on k8s-openapi and enable one of the features there. This way \
the feature will be enabled when buildings tests and examples of your library, but not when building the library itself. \
In case your library crate does not directly depend on k8s-openapi, add a dev-dependency on k8s-openapi and enable the corresponding feature in it.\n\
\n\
Alternatively, when running commands that do not build dev dependencies such as `cargo check` and `cargo doc`, you can set the `K8S_OPENAPI_ENABLED_VERSION` \
environment variable, such as `K8S_OPENAPI_ENABLED_VERSION=1.50`.\n\
\n\
Library crates *must not* enable any features in their direct dependency on k8s-openapi, only in their dev-dependency. \
The choice of which Kubernetes version to support should be left to the final binary crate, so only binary crates should enable a specific feature. \
If library crates also enabled features, it could cause multiple features to be enabled simultaneously, which k8s-openapi does not support.\n\
\n\
If your library crate only supports a single specific version or a specific range of versions of Kubernetes, \
please use the `k8s_if_*` version-specific macros or a build script to emit different code based on which feature gets enabled in the end.\n\
\n\
If you believe you *have* enabled a version feature and should not be seeing this error, check your Cargo.lock or run `cargo tree -i k8s-openapi` \
to ensure that this version of k8s-openapi is the only one being used in your project.\n\
\n\
See the k8s-openapi docs for more details.
");
if let Some(v2) = enabled_versions.next() {
panic!(
"\n\
Both v1_{v1} and v1_{v2} features are enabled on the k8s-openapi crate. These feature indicates which version of Kubernetes the k8s-openapi crate should support. \
Only one feature can be enabled at the same time.\n\
\n\
If you have enabled both of these features yourself, either via the k8s-openapi dependency in your Cargo.toml or via setting \
the `K8S_OPENAPI_ENABLED_VERSION` env var, please remove one of them. If you are writing a library crate, do not enable any features at all. \
Library crates *must not* enable any features on the k8s-openapi crate.\n\
\n\
If you have not enabled one or both of these features yourself, then one of the library crates in your dependency graph *has*. \
Locate which library crates in your dependency graph depend on k8s-openapi and enable one or more of its features, and file a bug against them, citing this text. \
You can search your Cargo.lock for \"k8s-openapi\" to discover these crates.\
");
}
v1
};
println!("cargo::metadata=version={}", 0x00_01_00_00_u32 | ((enabled_version as u32) << 8));
{
let mut enabled_version_possible_values = String::new();
for v in MIN..=MAX {
use std::fmt::Write;
if !enabled_version_possible_values.is_empty() {
enabled_version_possible_values.push_str(", ");
}
write!(enabled_version_possible_values, r#""1.{v}""#).unwrap();
}
println!("cargo::rustc-check-cfg=cfg(k8s_openapi_enabled_version, values({enabled_version_possible_values}))");
}
println!(r#"cargo::rustc-cfg=k8s_openapi_enabled_version="1.{enabled_version}""#);
let mut f = {
let mut out_file: std::path::PathBuf = std::env::var_os("OUT_DIR").ok_or("OUT_DIR not set")?.into();
out_file.push("conditional_compilation_macros.rs");
std::io::BufWriter::new(std::fs::File::create(out_file)?)
};
for v in MIN..=MAX {
writeln!(f, "/// This macro evaluates to its contents if the `v1_{v}` feature is enabled, otherwise it evaluates to nothing.")?;
writeln!(f, "///")?;
writeln!(f, "/// # Examples")?;
writeln!(f, "///")?;
writeln!(f, "/// ```rust")?;
writeln!(f, "/// # #[macro_use] extern crate k8s_openapi;")?;
writeln!(f, "/// k8s_if_1_{v}! {{")?;
writeln!(f, "/// use k8s_openapi::api::core::v1 as api;")?;
writeln!(f, "/// }}")?;
writeln!(f, "/// ```")?;
if enabled_version == v {
writeln!(f, "#[macro_export] macro_rules! k8s_if_1_{v} {{ ($($tt:tt)*) => {{ $($tt)* }}; }}")?;
}
else {
writeln!(f, "#[macro_export] macro_rules! k8s_if_1_{v} {{ ($($tt:tt)*) => {{ }}; }}")?;
}
writeln!(f)?;
writeln!(f, "/// This macro evaluates to its contents if the `v1_{v}` or higher feature is enabled, otherwise it evaluates to nothing.")?;
if enabled_version >= v {
writeln!(f, "#[macro_export] macro_rules! k8s_if_ge_1_{v} {{ ($($tt:tt)*) => {{ $($tt)* }}; }}")?;
}
else {
writeln!(f, "#[macro_export] macro_rules! k8s_if_ge_1_{v} {{ ($($tt:tt)*) => {{ }}; }}")?;
}
writeln!(f)?;
writeln!(f, "/// This macro evaluates to its contents if the `v1_{v}` or lower feature is enabled, otherwise it evaluates to nothing.")?;
if enabled_version <= v {
writeln!(f, "#[macro_export] macro_rules! k8s_if_le_1_{v} {{ ($($tt:tt)*) => {{ $($tt)* }}; }}")?;
}
else {
writeln!(f, "#[macro_export] macro_rules! k8s_if_le_1_{v} {{ ($($tt:tt)*) => {{ }}; }}")?;
}
writeln!(f)?;
}
writeln!(f, "/// A macro that emits a `match` expr with the given test expression and arms.")?;
writeln!(f, "/// The match arms can be annotated with the other conditional compilation macros in this crate so that they're only emitted")?;
writeln!(f, "/// if the predicate is true.")?;
writeln!(f, "#[macro_export] macro_rules! k8s_match {{")?;
writeln!(f, " (@inner {{ $test:expr }} {{ $($arms:tt)* }} {{ }}) => {{")?;
writeln!(f, " match $test {{ $($arms)* }}")?;
writeln!(f, " }};")?;
for v in MIN..=MAX {
writeln!(f)?;
for (name_suffix, enabled) in [("", enabled_version == v), ("_ge", enabled_version >= v), ("_le", enabled_version <= v)] {
writeln!(f, " (@inner {{ $test:expr }} {{ $($arms:tt)* }} {{ k8s_if{name_suffix}_1_{v}!($($arm:tt)*), $($rest:tt)* }}) => {{")?;
if enabled {
writeln!(f, " k8s_match!(@inner {{ $test }} {{ $($arms)* }} {{ $($arm)*, $($rest)* }})")?;
}
else {
writeln!(f, " k8s_match!(@inner {{ $test }} {{ $($arms)* }} {{ $($rest)* }})")?;
}
writeln!(f, " }};")?;
}
}
writeln!(f)?;
writeln!(f, " (@inner {{ $test:expr }} {{ $($arms:tt)* }} {{ $next_pat:pat $(if $cond:expr)? => $next_expr:expr, $($rest:tt)* }}) => {{")?;
writeln!(f, " k8s_match!(@inner {{ $test }} {{ $($arms)* $next_pat $(if $cond)? => $next_expr, }} {{ $($rest)* }})")?;
writeln!(f, " }};")?;
writeln!(f)?;
writeln!(f, " ($test:expr, {{ $($rest:tt)* }}) => {{")?;
writeln!(f, " k8s_match!(@inner {{ $test }} {{ }} {{ $($rest)* }})")?;
writeln!(f, " }};")?;
writeln!(f, "}}")?;
Ok(())
}