Skip to content

Commit e130aee

Browse files
committed
Some interstate
1 parent 694bd2e commit e130aee

File tree

5 files changed

+133
-8
lines changed

5 files changed

+133
-8
lines changed

src/main.rs

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ struct Args {
7474
#[arg(short, long, global = true, action)]
7575
#[cfg(feature = "update-informer")]
7676
skip_update_check: bool,
77+
78+
#[arg(short, long)]
79+
toolchain_name: Option<String>,
7780
}
7881

7982
/// Check crates.io for a new version of the application
@@ -98,9 +101,7 @@ fn setup_args_interactive(args: &mut Args) -> Result<()> {
98101

99102
if args.chip.is_none() {
100103
let chip_variants = Chip::iter().collect::<Vec<_>>();
101-
102104
let chip = Select::new("Select your target chip:", chip_variants).prompt()?;
103-
104105
args.chip = Some(chip);
105106
}
106107

@@ -112,9 +113,47 @@ fn setup_args_interactive(args: &mut Args) -> Result<()> {
112113
args.name = Some(project_name);
113114
}
114115

116+
if args.toolchain_name.is_none() {
117+
let chip = args
118+
.chip
119+
.expect("chip must be set by now in setup_args_interactive");
120+
let target = chip.target().to_string();
121+
122+
let toolchains = toolchains_for_target(&target)?;
123+
124+
if toolchains.is_empty() {
125+
log::warn!(
126+
"No rustup toolchains with target `{}` found. \
127+
Using default toolchain name `esp`. \
128+
Install an appropriate toolchain or pass --toolchain-name explicitly.",
129+
target
130+
);
131+
args.toolchain_name = Some("esp".to_string());
132+
} else if toolchains.len() == 1 {
133+
let only = toolchains[0].clone();
134+
println!(
135+
"Using toolchain `{}` for target `{}`",
136+
only, target
137+
);
138+
args.toolchain_name = Some(only);
139+
} else {
140+
let selected = Select::new(
141+
&format!(
142+
"Multiple Rust toolchains with target `{}` found.\nSelect the toolchain to use:",
143+
target
144+
),
145+
toolchains,
146+
)
147+
.prompt()?;
148+
149+
args.toolchain_name = Some(selected);
150+
}
151+
}
152+
115153
Ok(())
116154
}
117155

156+
118157
fn main() -> Result<()> {
119158
Builder::from_env(Env::default().default_filter_or(log::LevelFilter::Info.as_str()))
120159
.format_target(false)
@@ -131,14 +170,16 @@ fn main() -> Result<()> {
131170
}
132171

133172
// Run the interactive TUI only if chip or name is missing
134-
if args.chip.is_none() || args.name.is_none() {
173+
if args.chip.is_none() || args.name.is_none() || args.toolchain_name.is_none() {
135174
setup_args_interactive(&mut args)?;
136175
}
137176

138177
let chip = args.chip.unwrap();
139178

140179
let name = args.name.clone().unwrap();
141180

181+
let toolchain_name = args.toolchain_name.clone().unwrap();
182+
142183
let path = &args
143184
.output_path
144185
.clone()
@@ -250,6 +291,7 @@ fn main() -> Result<()> {
250291
),
251292
("esp-hal-version".to_string(), esp_hal_version),
252293
("max-dram2-uninit".to_string(), format!("{max_dram2}")),
294+
("toolchain-name".to_string(), toolchain_name),
253295
];
254296

255297
variables.push(("rust_target".to_string(), chip.target().to_string()));
@@ -651,6 +693,84 @@ fn should_initialize_git_repo(mut path: &Path) -> bool {
651693
true
652694
}
653695

696+
fn toolchains_for_target(target: &str) -> Result<Vec<String>> {
697+
let output = Command::new("rustup").args(["toolchain", "list"]).output();
698+
699+
let output = match output {
700+
Ok(o) => o,
701+
Err(err) => {
702+
log::warn!("Failed to run `rustup toolchain list`: {err}");
703+
return Ok(Vec::new());
704+
}
705+
};
706+
707+
if !output.status.success() {
708+
log::warn!(
709+
"`rustup toolchain list` failed with status: {:?}",
710+
output.status.code()
711+
);
712+
return Ok(Vec::new());
713+
}
714+
715+
let stdout = String::from_utf8_lossy(&output.stdout);
716+
717+
let mut applicable = Vec::new();
718+
719+
for line in stdout.lines() {
720+
// Line there are like: "stable-aarch64-apple-darwin (active, default)"
721+
let Some(name) = line.split_whitespace().next() else {
722+
continue;
723+
};
724+
725+
let toolchain = name.to_string();
726+
727+
// For Xtensa targets, hide "stable-*", "beta-*", "nightly-*"
728+
if target.starts_with("xtensa-")
729+
&& (toolchain.starts_with("stable-")
730+
|| toolchain.starts_with("beta-")
731+
|| toolchain.starts_with("nightly-"))
732+
{
733+
continue;
734+
}
735+
736+
// Use rustc with an explicit +toolchain spec, which works for custom
737+
// toolchains like `esp` and `esp-alt`.
738+
let spec = format!("+{}", toolchain);
739+
740+
let targets_output = Command::new("rustc")
741+
.arg(&spec)
742+
.args(["--print", "target-list"])
743+
.output();
744+
745+
let targets_output = match targets_output {
746+
Ok(o) => o,
747+
Err(err) => {
748+
log::warn!("Failed to run `rustc {spec} --print target-list`: {err}");
749+
continue;
750+
}
751+
};
752+
753+
if !targets_output.status.success() {
754+
log::warn!(
755+
"`rustc {spec} --print target-list` failed with status: {:?}",
756+
targets_output.status.code()
757+
);
758+
continue;
759+
}
760+
761+
let targets_stdout = String::from_utf8_lossy(&targets_output.stdout);
762+
763+
let has_target = targets_stdout.lines().any(|t| t.trim() == target);
764+
765+
if has_target {
766+
applicable.push(toolchain);
767+
}
768+
}
769+
770+
Ok(applicable)
771+
}
772+
773+
654774
#[cfg(test)]
655775
mod test {
656776
use super::*;

template/.helix/languages.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ cargo.allTargets = false
1212
#REPLACE riscv32imac-unknown-none-elf rust_target
1313
cargo.target = "riscv32imac-unknown-none-elf"
1414
#IF option("xtensa")
15+
#REPLACE esp toolchain-name
1516
check.extraEnv.RUSTUP_TOOLCHAIN = "esp"
17+
#REPLACE esp toolchain-name
1618
cargo.extraEnv.RUSTUP_TOOLCHAIN = "esp"
1719
#ENDIF

template/.nvim.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ local rust_analyzer = {
88
},
99
}
1010
--IF option("xtensa")
11+
--REPLACE esp toolchain-name
1112
rust_analyzer.cargo.extraEnv = { RUST_TOOLCHAIN = "esp" }
13+
--REPLACE esp toolchain-name
1214
rust_analyzer.check = { extraEnv = { RUST_TOOLCHAIN = "esp" } }
1315
rust_analyzer.server = { extraEnv = { RUST_TOOLCHAIN = "stable" } }
1416
--ENDIF

template/rust-toolchain.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ components = ["rust-src"]
99
#REPLACE riscv32imac-unknown-none-elf rust_target
1010
targets = ["riscv32imac-unknown-none-elf"]
1111
#ELIF option("xtensa")
12+
#REPLACE esp toolchain-name
1213
#+channel = "esp"
1314
#ENDIF

xtask/Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)