Skip to content

Commit

Permalink
ensure sysroot is correct
Browse files Browse the repository at this point in the history
  • Loading branch information
Emilgardis committed Mar 25, 2023
1 parent bb3df1b commit 2bbc0fd
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 37 deletions.
11 changes: 7 additions & 4 deletions src/bin/commands/containers.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::io;

use clap::{Args, Subcommand};
use cross::docker::ImagePlatform;
use cross::rustc::{QualifiedToolchain, Toolchain};
use cross::shell::{MessageInfo, Stream};
use cross::{docker, CommandExt, TargetTriple};
use cross::{docker::ImagePlatform, rustup::ToolchainMode};

#[derive(Args, Debug)]
pub struct ListVolumes {
Expand Down Expand Up @@ -392,7 +392,8 @@ pub fn create_persistent_volume(
channel: Option<&Toolchain>,
msg_info: &mut MessageInfo,
) -> cross::Result<()> {
let mut toolchain = toolchain_or_target(&toolchain, msg_info)?;
let installed_toolchains = cross::rustup::installed_toolchains(msg_info)?;
let mut toolchain = toolchain_or_target(&toolchain, &installed_toolchains, msg_info)?;
if let Some(channel) = channel {
toolchain.channel = channel.channel.clone();
};
Expand Down Expand Up @@ -460,7 +461,8 @@ pub fn remove_persistent_volume(
channel: Option<&Toolchain>,
msg_info: &mut MessageInfo,
) -> cross::Result<()> {
let mut toolchain = toolchain_or_target(&toolchain, msg_info)?;
let installed_toolchains = cross::rustup::installed_toolchains(msg_info)?;
let mut toolchain = toolchain_or_target(&toolchain, &installed_toolchains, msg_info)?;
if let Some(channel) = channel {
toolchain.channel = channel.channel.clone();
};
Expand Down Expand Up @@ -557,10 +559,11 @@ pub fn remove_all_containers(

fn toolchain_or_target(
s: &str,
installed_toolchains: &[(String, ToolchainMode, std::path::PathBuf)],
msg_info: &mut MessageInfo,
) -> Result<QualifiedToolchain, color_eyre::Report> {
let config = cross::config::Config::new(None);
let mut toolchain = QualifiedToolchain::default(&config, msg_info)?;
let mut toolchain = QualifiedToolchain::default(&config, installed_toolchains, msg_info)?;
let target_list = cross::rustc::target_list(msg_info)?;
if target_list.contains(s) {
toolchain.replace_host(&ImagePlatform::from_target(s.into())?);
Expand Down
17 changes: 13 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ use color_eyre::{Help, SectionExt};
use config::Config;
use rustc::{QualifiedToolchain, Toolchain};
use rustc_version::Channel;
use rustup::ToolchainMode;
use serde::{Deserialize, Serialize, Serializer};

pub use self::cargo::{cargo_command, cargo_metadata_with_args, CargoMetadata, Subcommand};
Expand Down Expand Up @@ -525,10 +526,11 @@ pub fn run(
uses_zig,
uses_build_std,
zig_version,
toolchain,
mut toolchain,
is_remote,
engine,
image,
installed_toolchains,
} = match setup(&host_version_meta, &metadata, &args, target_list, msg_info)? {
Some(setup) => setup,
_ => {
Expand All @@ -547,6 +549,11 @@ pub fn run(
"toolchain `{toolchain}` may not run on image `{image}`"
))?;
}

let available_targets =
rustup::setup_rustup(&toolchain, &installed_toolchains, msg_info)?;
toolchain.ensure_sysroot(installed_toolchains, msg_info)?;

let mut is_nightly = toolchain.channel.contains("nightly");
let mut rustc_version = None;
if let Some((version, channel, commit)) = toolchain.rustc_version()? {
Expand All @@ -563,8 +570,6 @@ pub fn run(
rustc_version = Some(version);
}

let available_targets = rustup::setup_rustup(&toolchain, msg_info)?;

rustup::setup_components(
&target,
uses_xargo,
Expand Down Expand Up @@ -739,7 +744,9 @@ pub fn setup(
return Ok(None);
}
};
let default_toolchain = QualifiedToolchain::default(&config, msg_info)?;
let installed_toolchains = rustup::installed_toolchains(msg_info)?;

let default_toolchain = QualifiedToolchain::default(&config, &installed_toolchains, msg_info)?;
let mut toolchain = if let Some(channel) = &args.channel {
let picked_toolchain: Toolchain = channel.parse()?;

Expand Down Expand Up @@ -774,6 +781,7 @@ To override the toolchain mounted in the image, set `target.{target}.image.toolc
is_remote,
engine,
image,
installed_toolchains,
}))
}

Expand All @@ -789,6 +797,7 @@ pub struct CrossSetup {
pub is_remote: bool,
pub engine: docker::Engine,
pub image: docker::Image,
pub installed_toolchains: Vec<(String, ToolchainMode, PathBuf)>,
}

#[derive(PartialEq, Eq, Debug)]
Expand Down
62 changes: 42 additions & 20 deletions src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use std::process::Command;
use rustc_version::{Version, VersionMeta};
use serde::Deserialize;

use crate::docker::ImagePlatform;
use crate::errors::*;
use crate::extensions::{env_program, CommandExt};
use crate::shell::MessageInfo;
use crate::TargetTriple;
use crate::{docker::ImagePlatform, rustup::ToolchainMode};

#[derive(Debug)]
pub struct TargetList {
Expand Down Expand Up @@ -196,19 +196,30 @@ impl QualifiedToolchain {
}

/// Grab the current default toolchain
pub fn default(config: &crate::config::Config, msg_info: &mut MessageInfo) -> Result<Self> {
let sysroot = sysroot(msg_info)?;

let default_toolchain_name = sysroot
.file_name()
.ok_or_else(|| eyre::eyre!("couldn't get name of active toolchain"))?
.to_str()
.ok_or_else(|| eyre::eyre!("toolchain was not utf-8"))?;
pub fn default(
config: &crate::config::Config,
installed_toolchains: &[(String, ToolchainMode, PathBuf)],
msg_info: &mut MessageInfo,
) -> Result<Self> {
let (toolchain_name, sysroot) = if let Some((toolchain_name, _, sysroot)) =
installed_toolchains
.iter()
.find(|(_, mode, _)| mode.is_overriden())
{
(toolchain_name, sysroot)
} else if let Some((toolchain_name, _, sysroot)) = installed_toolchains
.iter()
.find(|(_, mode, _)| mode.is_defaulted())
{
(toolchain_name, sysroot)
} else {
eyre::bail!("no default toolchain found");
};

if !config.custom_toolchain() {
QualifiedToolchain::parse(sysroot.clone(), default_toolchain_name, config, msg_info)
QualifiedToolchain::parse(sysroot.clone(), toolchain_name, config, msg_info)
} else {
QualifiedToolchain::custom(default_toolchain_name, &sysroot, config, msg_info)
QualifiedToolchain::custom(toolchain_name, sysroot, config, msg_info)
}
}

Expand All @@ -232,6 +243,26 @@ impl QualifiedToolchain {
pub fn set_sysroot(&mut self, convert: impl Fn(&Path) -> PathBuf) {
self.sysroot = convert(&self.sysroot);
}

pub fn ensure_sysroot(
&mut self,
installed_toolchains: Vec<(String, ToolchainMode, std::path::PathBuf)>,
msg_info: &mut MessageInfo,
) -> Result<()> {
self.sysroot = if let Some((_, _, sysroot)) = installed_toolchains
.iter()
.find(|(name, _, _)| &self.full == name)
{
sysroot.clone()
} else {
let (_, _, sysroot) = crate::rustup::installed_toolchains(msg_info)?
.into_iter()
.find(|(name, _, _)| &self.full == name)
.ok_or_else(|| eyre::eyre!("toolchain not found"))?;
sysroot
};
Ok(())
}
}

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

pub fn sysroot(msg_info: &mut MessageInfo) -> Result<PathBuf> {
let stdout = rustc_command()
.args(["--print", "sysroot"])
.run_and_get_stdout(msg_info)?
.trim()
.to_owned();
Ok(PathBuf::from(stdout))
}

pub fn version_meta() -> Result<rustc_version::VersionMeta> {
rustc_version::version_meta().wrap_err("couldn't fetch the `rustc` version")
}
Expand Down
83 changes: 74 additions & 9 deletions src/rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ impl AvailableTargets {

pub fn setup_rustup(
toolchain: &QualifiedToolchain,
installed_toolchains: &[(String, ToolchainMode, PathBuf)],
msg_info: &mut MessageInfo,
) -> Result<AvailableTargets, color_eyre::Report> {
if !toolchain.is_custom
&& !installed_toolchains(msg_info)?
.into_iter()
.any(|t| t == toolchain.to_string())
&& !installed_toolchains
.iter()
.any(|(t, _, _)| t == &toolchain.to_string())
{
install_toolchain(toolchain, msg_info)?;
}
Expand Down Expand Up @@ -83,18 +84,82 @@ pub fn active_toolchain(msg_info: &mut MessageInfo) -> Result<String> {
.to_owned())
}

pub fn installed_toolchains(msg_info: &mut MessageInfo) -> Result<Vec<String>> {
#[derive(Debug)]
pub enum ToolchainMode {
Override,
Default,
DefaultOverride,
None,
Other,
}

impl ToolchainMode {
/// Returns `true` if the toolchain mode is [`Override`] or [`DefaultOverride`].
///
/// [`Override`]: ToolchainMode::Override
/// [`DefaultOverride`]: ToolchainMode::DefaultOverride
#[must_use]
pub fn is_overriden(&self) -> bool {
matches!(self, Self::Override | Self::DefaultOverride)
}

/// Returns `true` if the toolchain mode is [`None`].
///
/// [`None`]: ToolchainMode::None
#[must_use]
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}

/// Returns `true` if the toolchain mode is [`Default`] or [`DefaultOverride`].
///
/// [`Default`]: ToolchainMode::Default
/// [`DefaultOverride`]: ToolchainMode::DefaultOverride
#[must_use]
pub fn is_defaulted(&self) -> bool {
matches!(self, Self::Default)
}
}

pub fn installed_toolchains(
msg_info: &mut MessageInfo,
) -> Result<Vec<(String, ToolchainMode, std::path::PathBuf)>> {
let out = rustup_command(msg_info, true)
.args(["toolchain", "list"])
.args(["toolchain", "list", "-v"])
.run_and_get_stdout(msg_info)?;

Ok(out
.lines()
.map(|l| {
l.replace(" (default)", "")
.replace(" (override)", "")
.trim()
.to_owned()
let mut mode = ToolchainMode::None;
let mut l = if l.contains(" (override)") {
mode = ToolchainMode::Override;
l.replace(" (override)", "")
} else {
l.to_owned()
};
if l.contains(" (default)") {
if mode.is_overriden() {
mode = ToolchainMode::DefaultOverride;
} else {
mode = ToolchainMode::Default;
}
l = l.replace(" (default)", "");
}

(l, mode)
})
.map(|(l, mode)| {
let mut i = l.split_whitespace();
(
i.next()
.map(|s| s.to_owned())
.expect("rustup output should be consistent"),
mode,
i.next()
.map(PathBuf::from)
.expect("rustup output should be consistent"),
)
})
.collect())
}
Expand Down

0 comments on commit 2bbc0fd

Please sign in to comment.