Skip to content

Commit 3478e5a

Browse files
committed
Catch wrong feature selection more robustly
As we are now using build.rs to check the feature selection, we can now make more sophisticated checks. Therefor we use build.rs to compare the selected features and the features in the Cargo.toml (via cargo_metadata), and verify, that only a single valid device feature is selected.
1 parent 420062a commit 3478e5a

File tree

2 files changed

+78
-29
lines changed

2 files changed

+78
-29
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ panic-probe = "0.2"
6161
defmt-rtt = "0.2"
6262
defmt-test = "0.2"
6363

64+
[build-dependencies]
65+
cargo_metadata = "0.13.1"
66+
slice-group-by = "0.2.6"
67+
6468
[features]
6569
default = ["unproven"]
6670
unproven = ["embedded-hal/unproven"]

build.rs

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
use std::{env, fs::File, io::prelude::*, path::PathBuf};
1+
use std::collections::hash_set::HashSet;
2+
use std::env;
3+
use std::fs::File;
4+
use std::io::prelude::*;
5+
use std::path::PathBuf;
6+
7+
use cargo_metadata::MetadataCommand;
8+
// TODO(Sh3Rm4n - 2021-04-28):
9+
// Remove when [feature="slice_group_by"] is stable.
10+
// See with https://github.com/rust-lang/rust/issues/80552.
11+
use slice_group_by::GroupBy;
212

313
fn main() {
414
check_device_feature();
@@ -10,40 +20,75 @@ fn main() {
1020

1121
/// Check device feature selection
1222
fn check_device_feature() {
13-
if !cfg!(feature = "device-selected") {
14-
if cfg!(feature = "direct-call-deprecated") {
15-
eprintln!(
16-
"The feature you selected is deprecated, because it was split up into sub-devices.
23+
// Check if the device is deprecated
24+
if !cfg!(feature = "device-selected") && cfg!(feature = "direct-call-deprecated") {
25+
eprintln!(
26+
"The (device-)feature you selected is deprecated, because it was split up into sub-devices.\n\
27+
\n\
28+
Example: The STM32F3Discovery board has a STM32F303VCT6 chip.\n\
29+
You probably used to use `stm32f303` but now functionalities for the sub-device were added.\n\
30+
In this case replace it with `stm32f303xc` to make your code build again.\n\
31+
\n\
32+
For more information, see \
33+
\x1b]8;;https://github.com/stm32-rs/stm32f3xx-hal#selecting-the-right-chip\x1b\\README\
34+
-> Selecting the right chip\x1b]8;;\x1b\\."
35+
);
36+
std::process::exit(1);
37+
}
1738

18-
Example: The STM32F3Discovery board has a STM32F303VCT6 chip.
19-
You probably used to use `stm32f303` but now functionalities for the sub-device were added.
20-
In this case replace it with `stm32f303xc` to make your code build again.
39+
// get all device variants from the metadata
40+
let metadata = MetadataCommand::new().exec().unwrap();
41+
let device_variants: HashSet<String> = metadata
42+
.root_package()
43+
.unwrap()
44+
.features
45+
.iter()
46+
.filter_map(|(feature, dependend_features)| {
47+
dependend_features
48+
.iter()
49+
.any(|dependend_feature| dependend_feature == "device-selected")
50+
.then(|| feature.clone())
51+
})
52+
.collect();
2153

22-
For more information, see \x1b]8;;https://github.com/stm32-rs/stm32f3xx-hal#selecting-the-right-chip\x1b\\README -> Selecting the right chip\x1b]8;;\x1b\\."
23-
);
24-
} else {
25-
eprintln!(
26-
"This crate requires you to specify your target chip as a feature.
54+
// get all selected features via env variables
55+
let selected_features: HashSet<String> = env::vars()
56+
.filter_map(|(key, _)| {
57+
key.split("CARGO_FEATURE_")
58+
.nth(1)
59+
.map(|s| s.to_owned().to_ascii_lowercase())
60+
})
61+
.collect();
2762

28-
Please select one of the following (`x` denotes any character in [a-z]):
29-
30-
stm32f301x6 stm32f301x8
31-
stm32f318x8
32-
stm32f302x6 stm32f302x8 stm32f302xb stm32f302xc stm32f302xd stm32f302xe
33-
stm32f303x6 stm32f303x8 stm32f303xb stm32f303xc stm32f303xd stm32f303xe
34-
stm32f328x8
35-
stm32f358xc
36-
stm32f398xe
37-
stm32f373x8 stm32f373xb stm32f373xc
38-
stm32f378xc
39-
stm32f334x4 stm32f334x6 stm32f334x8
63+
// check if exactly one device was selected
64+
if device_variants.intersection(&selected_features).count() != 1 {
65+
eprintln!(
66+
"This crate requires you to specify your target chip as a feature.\n\
67+
\n\
68+
Please select **one** of the following (`x` denotes any character in [a-z]):\n"
69+
);
4070

41-
Example: The STM32F3Discovery board has a STM32F303VCT6 chip.
42-
So you need to specify stm32f303xc in your Cargo.toml (note that VC → xc).
71+
// group device variants by type
72+
let mut device_variants: Vec<String> = device_variants.into_iter().collect();
73+
device_variants.sort_unstable();
74+
let device_variants = device_variants.linear_group_by(|a, b| a[..9] == b[..9]);
4375

44-
For more information, see \x1b]8;;https://github.com/stm32-rs/stm32f3xx-hal#selecting-the-right-chip\x1b\\README -> Selecting the right chip\x1b]8;;\x1b\\."
45-
);
76+
// pretty print all avaliable devices
77+
for line in device_variants {
78+
for device in line {
79+
eprint!("{} ", device);
80+
}
81+
eprintln!();
4682
}
83+
84+
eprintln!(
85+
"\nExample: The STM32F3Discovery board has a STM32F303VCT6 chip.\n\
86+
So you need to specify stm32f303xc in your Cargo.toml (note that VC → xc).\n\
87+
\n\
88+
For more information, see \
89+
\x1b]8;;https://github.com/stm32-rs/stm32f3xx-hal#selecting-the-right-chip\x1b\\README \
90+
-> Selecting the right chip\x1b]8;;\x1b\\."
91+
);
4792
std::process::exit(1);
4893
}
4994
}

0 commit comments

Comments
 (0)