Skip to content

Commit 2bbc0fd

Browse files
committed
ensure sysroot is correct
1 parent bb3df1b commit 2bbc0fd

File tree

4 files changed

+136
-37
lines changed

4 files changed

+136
-37
lines changed

src/bin/commands/containers.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use std::io;
22

33
use clap::{Args, Subcommand};
4-
use cross::docker::ImagePlatform;
54
use cross::rustc::{QualifiedToolchain, Toolchain};
65
use cross::shell::{MessageInfo, Stream};
76
use cross::{docker, CommandExt, TargetTriple};
7+
use cross::{docker::ImagePlatform, rustup::ToolchainMode};
88

99
#[derive(Args, Debug)]
1010
pub struct ListVolumes {
@@ -392,7 +392,8 @@ pub fn create_persistent_volume(
392392
channel: Option<&Toolchain>,
393393
msg_info: &mut MessageInfo,
394394
) -> cross::Result<()> {
395-
let mut toolchain = toolchain_or_target(&toolchain, msg_info)?;
395+
let installed_toolchains = cross::rustup::installed_toolchains(msg_info)?;
396+
let mut toolchain = toolchain_or_target(&toolchain, &installed_toolchains, msg_info)?;
396397
if let Some(channel) = channel {
397398
toolchain.channel = channel.channel.clone();
398399
};
@@ -460,7 +461,8 @@ pub fn remove_persistent_volume(
460461
channel: Option<&Toolchain>,
461462
msg_info: &mut MessageInfo,
462463
) -> cross::Result<()> {
463-
let mut toolchain = toolchain_or_target(&toolchain, msg_info)?;
464+
let installed_toolchains = cross::rustup::installed_toolchains(msg_info)?;
465+
let mut toolchain = toolchain_or_target(&toolchain, &installed_toolchains, msg_info)?;
464466
if let Some(channel) = channel {
465467
toolchain.channel = channel.channel.clone();
466468
};
@@ -557,10 +559,11 @@ pub fn remove_all_containers(
557559

558560
fn toolchain_or_target(
559561
s: &str,
562+
installed_toolchains: &[(String, ToolchainMode, std::path::PathBuf)],
560563
msg_info: &mut MessageInfo,
561564
) -> Result<QualifiedToolchain, color_eyre::Report> {
562565
let config = cross::config::Config::new(None);
563-
let mut toolchain = QualifiedToolchain::default(&config, msg_info)?;
566+
let mut toolchain = QualifiedToolchain::default(&config, installed_toolchains, msg_info)?;
564567
let target_list = cross::rustc::target_list(msg_info)?;
565568
if target_list.contains(s) {
566569
toolchain.replace_host(&ImagePlatform::from_target(s.into())?);

src/lib.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use color_eyre::{Help, SectionExt};
5555
use config::Config;
5656
use rustc::{QualifiedToolchain, Toolchain};
5757
use rustc_version::Channel;
58+
use rustup::ToolchainMode;
5859
use serde::{Deserialize, Serialize, Serializer};
5960

6061
pub use self::cargo::{cargo_command, cargo_metadata_with_args, CargoMetadata, Subcommand};
@@ -525,10 +526,11 @@ pub fn run(
525526
uses_zig,
526527
uses_build_std,
527528
zig_version,
528-
toolchain,
529+
mut toolchain,
529530
is_remote,
530531
engine,
531532
image,
533+
installed_toolchains,
532534
} = match setup(&host_version_meta, &metadata, &args, target_list, msg_info)? {
533535
Some(setup) => setup,
534536
_ => {
@@ -547,6 +549,11 @@ pub fn run(
547549
"toolchain `{toolchain}` may not run on image `{image}`"
548550
))?;
549551
}
552+
553+
let available_targets =
554+
rustup::setup_rustup(&toolchain, &installed_toolchains, msg_info)?;
555+
toolchain.ensure_sysroot(installed_toolchains, msg_info)?;
556+
550557
let mut is_nightly = toolchain.channel.contains("nightly");
551558
let mut rustc_version = None;
552559
if let Some((version, channel, commit)) = toolchain.rustc_version()? {
@@ -563,8 +570,6 @@ pub fn run(
563570
rustc_version = Some(version);
564571
}
565572

566-
let available_targets = rustup::setup_rustup(&toolchain, msg_info)?;
567-
568573
rustup::setup_components(
569574
&target,
570575
uses_xargo,
@@ -739,7 +744,9 @@ pub fn setup(
739744
return Ok(None);
740745
}
741746
};
742-
let default_toolchain = QualifiedToolchain::default(&config, msg_info)?;
747+
let installed_toolchains = rustup::installed_toolchains(msg_info)?;
748+
749+
let default_toolchain = QualifiedToolchain::default(&config, &installed_toolchains, msg_info)?;
743750
let mut toolchain = if let Some(channel) = &args.channel {
744751
let picked_toolchain: Toolchain = channel.parse()?;
745752

@@ -774,6 +781,7 @@ To override the toolchain mounted in the image, set `target.{target}.image.toolc
774781
is_remote,
775782
engine,
776783
image,
784+
installed_toolchains,
777785
}))
778786
}
779787

@@ -789,6 +797,7 @@ pub struct CrossSetup {
789797
pub is_remote: bool,
790798
pub engine: docker::Engine,
791799
pub image: docker::Image,
800+
pub installed_toolchains: Vec<(String, ToolchainMode, PathBuf)>,
792801
}
793802

794803
#[derive(PartialEq, Eq, Debug)]

src/rustc.rs

+42-20
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ use std::process::Command;
44
use rustc_version::{Version, VersionMeta};
55
use serde::Deserialize;
66

7-
use crate::docker::ImagePlatform;
87
use crate::errors::*;
98
use crate::extensions::{env_program, CommandExt};
109
use crate::shell::MessageInfo;
1110
use crate::TargetTriple;
11+
use crate::{docker::ImagePlatform, rustup::ToolchainMode};
1212

1313
#[derive(Debug)]
1414
pub struct TargetList {
@@ -196,19 +196,30 @@ impl QualifiedToolchain {
196196
}
197197

198198
/// Grab the current default toolchain
199-
pub fn default(config: &crate::config::Config, msg_info: &mut MessageInfo) -> Result<Self> {
200-
let sysroot = sysroot(msg_info)?;
201-
202-
let default_toolchain_name = sysroot
203-
.file_name()
204-
.ok_or_else(|| eyre::eyre!("couldn't get name of active toolchain"))?
205-
.to_str()
206-
.ok_or_else(|| eyre::eyre!("toolchain was not utf-8"))?;
199+
pub fn default(
200+
config: &crate::config::Config,
201+
installed_toolchains: &[(String, ToolchainMode, PathBuf)],
202+
msg_info: &mut MessageInfo,
203+
) -> Result<Self> {
204+
let (toolchain_name, sysroot) = if let Some((toolchain_name, _, sysroot)) =
205+
installed_toolchains
206+
.iter()
207+
.find(|(_, mode, _)| mode.is_overriden())
208+
{
209+
(toolchain_name, sysroot)
210+
} else if let Some((toolchain_name, _, sysroot)) = installed_toolchains
211+
.iter()
212+
.find(|(_, mode, _)| mode.is_defaulted())
213+
{
214+
(toolchain_name, sysroot)
215+
} else {
216+
eyre::bail!("no default toolchain found");
217+
};
207218

208219
if !config.custom_toolchain() {
209-
QualifiedToolchain::parse(sysroot.clone(), default_toolchain_name, config, msg_info)
220+
QualifiedToolchain::parse(sysroot.clone(), toolchain_name, config, msg_info)
210221
} else {
211-
QualifiedToolchain::custom(default_toolchain_name, &sysroot, config, msg_info)
222+
QualifiedToolchain::custom(toolchain_name, sysroot, config, msg_info)
212223
}
213224
}
214225

@@ -232,6 +243,26 @@ impl QualifiedToolchain {
232243
pub fn set_sysroot(&mut self, convert: impl Fn(&Path) -> PathBuf) {
233244
self.sysroot = convert(&self.sysroot);
234245
}
246+
247+
pub fn ensure_sysroot(
248+
&mut self,
249+
installed_toolchains: Vec<(String, ToolchainMode, std::path::PathBuf)>,
250+
msg_info: &mut MessageInfo,
251+
) -> Result<()> {
252+
self.sysroot = if let Some((_, _, sysroot)) = installed_toolchains
253+
.iter()
254+
.find(|(name, _, _)| &self.full == name)
255+
{
256+
sysroot.clone()
257+
} else {
258+
let (_, _, sysroot) = crate::rustup::installed_toolchains(msg_info)?
259+
.into_iter()
260+
.find(|(name, _, _)| &self.full == name)
261+
.ok_or_else(|| eyre::eyre!("toolchain not found"))?;
262+
sysroot
263+
};
264+
Ok(())
265+
}
235266
}
236267

237268
impl std::fmt::Display for QualifiedToolchain {
@@ -364,15 +395,6 @@ pub fn target_list(msg_info: &mut MessageInfo) -> Result<TargetList> {
364395
})
365396
}
366397

367-
pub fn sysroot(msg_info: &mut MessageInfo) -> Result<PathBuf> {
368-
let stdout = rustc_command()
369-
.args(["--print", "sysroot"])
370-
.run_and_get_stdout(msg_info)?
371-
.trim()
372-
.to_owned();
373-
Ok(PathBuf::from(stdout))
374-
}
375-
376398
pub fn version_meta() -> Result<rustc_version::VersionMeta> {
377399
rustc_version::version_meta().wrap_err("couldn't fetch the `rustc` version")
378400
}

src/rustup.rs

+74-9
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ impl AvailableTargets {
3030

3131
pub fn setup_rustup(
3232
toolchain: &QualifiedToolchain,
33+
installed_toolchains: &[(String, ToolchainMode, PathBuf)],
3334
msg_info: &mut MessageInfo,
3435
) -> Result<AvailableTargets, color_eyre::Report> {
3536
if !toolchain.is_custom
36-
&& !installed_toolchains(msg_info)?
37-
.into_iter()
38-
.any(|t| t == toolchain.to_string())
37+
&& !installed_toolchains
38+
.iter()
39+
.any(|(t, _, _)| t == &toolchain.to_string())
3940
{
4041
install_toolchain(toolchain, msg_info)?;
4142
}
@@ -83,18 +84,82 @@ pub fn active_toolchain(msg_info: &mut MessageInfo) -> Result<String> {
8384
.to_owned())
8485
}
8586

86-
pub fn installed_toolchains(msg_info: &mut MessageInfo) -> Result<Vec<String>> {
87+
#[derive(Debug)]
88+
pub enum ToolchainMode {
89+
Override,
90+
Default,
91+
DefaultOverride,
92+
None,
93+
Other,
94+
}
95+
96+
impl ToolchainMode {
97+
/// Returns `true` if the toolchain mode is [`Override`] or [`DefaultOverride`].
98+
///
99+
/// [`Override`]: ToolchainMode::Override
100+
/// [`DefaultOverride`]: ToolchainMode::DefaultOverride
101+
#[must_use]
102+
pub fn is_overriden(&self) -> bool {
103+
matches!(self, Self::Override | Self::DefaultOverride)
104+
}
105+
106+
/// Returns `true` if the toolchain mode is [`None`].
107+
///
108+
/// [`None`]: ToolchainMode::None
109+
#[must_use]
110+
pub fn is_none(&self) -> bool {
111+
matches!(self, Self::None)
112+
}
113+
114+
/// Returns `true` if the toolchain mode is [`Default`] or [`DefaultOverride`].
115+
///
116+
/// [`Default`]: ToolchainMode::Default
117+
/// [`DefaultOverride`]: ToolchainMode::DefaultOverride
118+
#[must_use]
119+
pub fn is_defaulted(&self) -> bool {
120+
matches!(self, Self::Default)
121+
}
122+
}
123+
124+
pub fn installed_toolchains(
125+
msg_info: &mut MessageInfo,
126+
) -> Result<Vec<(String, ToolchainMode, std::path::PathBuf)>> {
87127
let out = rustup_command(msg_info, true)
88-
.args(["toolchain", "list"])
128+
.args(["toolchain", "list", "-v"])
89129
.run_and_get_stdout(msg_info)?;
90130

91131
Ok(out
92132
.lines()
93133
.map(|l| {
94-
l.replace(" (default)", "")
95-
.replace(" (override)", "")
96-
.trim()
97-
.to_owned()
134+
let mut mode = ToolchainMode::None;
135+
let mut l = if l.contains(" (override)") {
136+
mode = ToolchainMode::Override;
137+
l.replace(" (override)", "")
138+
} else {
139+
l.to_owned()
140+
};
141+
if l.contains(" (default)") {
142+
if mode.is_overriden() {
143+
mode = ToolchainMode::DefaultOverride;
144+
} else {
145+
mode = ToolchainMode::Default;
146+
}
147+
l = l.replace(" (default)", "");
148+
}
149+
150+
(l, mode)
151+
})
152+
.map(|(l, mode)| {
153+
let mut i = l.split_whitespace();
154+
(
155+
i.next()
156+
.map(|s| s.to_owned())
157+
.expect("rustup output should be consistent"),
158+
mode,
159+
i.next()
160+
.map(PathBuf::from)
161+
.expect("rustup output should be consistent"),
162+
)
98163
})
99164
.collect())
100165
}

0 commit comments

Comments
 (0)