-
Notifications
You must be signed in to change notification settings - Fork 10
/
build.rs
179 lines (166 loc) · 6.28 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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
use std::env;
fn main() {
println!("cargo:rerun-if-env-changed=RIOTBUILD_CONFIG_HEADER_C");
let riotbuildh = env::var("RIOTBUILD_CONFIG_HEADER_C")
.expect("riotbuild.h is expected to be indicated in the RIOTBUILD_CONFIG_HEADER_C environment variable, or another source of enabled modules provided.");
println!("cargo:rerun-if-changed={riotbuildh}");
let mut defines = std::collections::HashMap::new();
use std::io::BufRead;
for line in std::io::BufReader::new(
std::fs::File::open(riotbuildh)
.expect("Failed to read riotbuild.h (RIOTBUILD_CONFIG_HEADER_C)"),
)
.lines()
{
let line = line.expect("Error reading line from riotbuild.h (RIOTBUILD_CONFIG_HEADER_C)");
if let Some(name) = line.strip_prefix("#undef ") {
defines.remove(name.trim());
}
if let Some((name, val)) = line
.strip_prefix("#define ")
.and_then(|nv| nv.split_once(" "))
{
defines.insert(name.trim().to_owned(), val.trim().to_owned());
}
}
const BOOLEAN_FLAGS: &[&str] = &[
// This decides whether or not some fields are populated ... and unlike with other
// structs, the zeroed default is not a good solution here. (It'd kind of work, but
// it'd produce incorrect debug output).
"CONFIG_AUTO_INIT_ENABLE_DEBUG",
];
for marker in BOOLEAN_FLAGS {
println!(
"cargo::rustc-check-cfg=cfg(marker_{})",
marker.to_lowercase()
);
}
for (def, val) in defines {
if val != "1" {
// So far, only processing boolean flags
continue;
}
if let Some(module) = def.strip_prefix("MODULE_") {
// Some modules like cmsis-dsp_StatisticsFunctions have funny characters
println!(
"cargo:rustc-cfg=riot_module_{}",
module.to_lowercase().replace("-", "_")
);
}
if def == "DEVELHELP" {
println!("cargo:rustc-cfg=riot_develhelp");
}
if BOOLEAN_FLAGS.contains(&def.as_str()) {
println!("cargo:rustc-cfg=marker_{}", def.to_lowercase());
}
}
println!("cargo::rustc-check-cfg=cfg(riot_develhelp)");
// FIXME: This list is currently maintained manually;
let known_modules = &[
"auto_init",
"auto_init_random",
"bluetil_ad",
"core_msg",
"gcoap",
"gnrc",
"gnrc_icmpv6",
"gnrc_ipv6_nib",
"gnrc_netapi_callbacks",
"gnrc_nettype_ccn",
"gnrc_nettype_custom",
"gnrc_nettype_gomach",
"gnrc_nettype_icmpv6",
"gnrc_nettype_ipv6",
"gnrc_nettype_ipv6_ext",
"gnrc_nettype_lwmac",
"gnrc_nettype_ndn",
"gnrc_nettype_sixlowpan",
"gnrc_nettype_tcp",
"gnrc_nettype_udp",
"gnrc_pktbuf",
"gnrc_udp",
"ipv6",
"microbit",
"nimble_host",
"periph_adc",
"periph_dac",
"periph_gpio",
"periph_i2c",
"periph_spi",
"periph_uart",
"periph_uart_collision",
"periph_uart_hw_fc",
"periph_uart_modecfg",
"periph_uart_nonblocking",
"periph_uart_reconfigure",
"periph_uart_rxstart_irq",
"periph_uart_tx_ondemand",
"prng_shaxprng",
"pthread",
"random",
"saul",
"shell",
"sock",
"sock_aux_local",
"sock_tcp",
"sock_udp",
"tiny_strerror",
"tiny_strerror_minimal",
"udp",
"vfs",
"ws281x",
"ztimer",
"ztimer_msec",
"ztimer_periodic",
"ztimer_sec",
"ztimer_usec",
];
for module in known_modules {
println!("cargo::rustc-check-cfg=cfg(riot_module_{})", module);
}
// As a means of last resort, we emulate cfg(accessible(::path::to::thing)), as a
// workaround for https://github.com/rust-lang/rust/issues/64797
//
// This is sometimes necessary when some C API compatible change (eg. renaming a field with a
// deprecated union while introducing a proper accessor, as done in
// https://github.com/RIOT-OS/RIOT/pull/20900) leads to changes in bindgen and c2rust outputs.
//
// This is similar to the markers that were previously used in riot-sys. We access files
// directly to avoid going through `links=` (see also
// <https://github.com/RIOT-OS/rust-riot-sys/pull/38>). This
//
// * limits the impact of source changes (this way, only changs to relevant headerst trigger
// a rebuild of riot-wrappers), and
// * removes the need for lock-stepping riot-sys and riot-wrappers.
//
// The downside of the tighter coupling with the paths in RIOT is reduced by keeping things
// local and the stabiity structure: All these access checks can be removed once riot-wrappers
// stops supporting a RIOT version that has the symbol unconditionally, without any concern for
// compatibility between crates (as the cfgs are just internal).
let riotbase: std::path::PathBuf = env::var("RIOTBASE")
.expect("No RIOTBASE set, can not inspect source files for symbol presence.")
.into();
println!("cargo:rerun-if-env-changed=RIOTBASE");
let emulate_accessible = [
// It's a static inline function and riot-sys currently only gives the file for the bindgen
// output, not the c2rust output. Using coap_build_udp_hdr presence as a stand-in.
//
// Remove this after a release including coap_pkt_set_code
// <https://github.com/RIOT-OS/riot/issues/20900> has been published.
(
&"inline_coap_pkt_set_code",
&"sys/include/net/nanocoap.h",
&"coap_pkt_set_code",
),
];
for (rust_name, header_file, header_search_string) in emulate_accessible {
let header_file = riotbase.join(header_file);
println!("cargo:rerun-if-changed={}", header_file.display());
let header_code =
std::fs::read_to_string(&header_file).expect("Failed to read header file");
println!("cargo:rustc-check-cfg=cfg(accessible_riot_sys_{rust_name})");
if header_code.contains(header_search_string) {
println!("cargo:rustc-cfg=accessible_riot_sys_{rust_name}");
}
}
}