From bcac46d7df3d68d38a3b61d3a26f2ed189933227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Thu, 30 Jun 2022 03:03:48 +0200 Subject: [PATCH] address code review --- src/bin/commands/containers.rs | 8 +- src/config.rs | 6 +- src/cross_toml.rs | 42 ++++---- src/docker/custom.rs | 31 ++++-- src/docker/image.rs | 113 +++++++++++++++------ src/docker/local.rs | 13 ++- src/docker/mod.rs | 26 ++++- src/docker/provided_images.rs | 112 ++++++++++---------- src/docker/remote.rs | 57 +++++++---- src/docker/shared.rs | 137 +++++++++++++++++++++---- src/lib.rs | 175 +++++++++++++++++--------------- src/rustc.rs | 49 ++++----- src/tests.rs | 4 +- xtask/src/build_docker_image.rs | 13 +-- xtask/src/codegen.rs | 13 +-- xtask/src/util.rs | 6 +- 16 files changed, 502 insertions(+), 303 deletions(-) diff --git a/src/bin/commands/containers.rs b/src/bin/commands/containers.rs index 5065766e8..602ca9e4a 100644 --- a/src/bin/commands/containers.rs +++ b/src/bin/commands/containers.rs @@ -3,7 +3,7 @@ use std::io; use clap::{Args, Subcommand}; use cross::shell::{self, MessageInfo, Stream}; use cross::{ - docker::{self, ImageArchitecture}, + docker::{self, ImagePlatform}, rustc::{QualifiedToolchain, Toolchain}, CommandExt, }; @@ -408,7 +408,7 @@ pub fn create_persistent_volume( triple: cross::TargetTriple::X86_64UnknownLinuxGnu, }; let mut toolchain = QualifiedToolchain::default(msg_info)?; - toolchain.replace_host(&ImageArchitecture::from_target(target.target().clone())); + toolchain.replace_host(&ImagePlatform::from_target(target.target().clone())?); if let Some(channel) = channel { toolchain = toolchain.with_picked(channel.clone(), msg_info)?; }; @@ -469,7 +469,7 @@ pub fn create_persistent_volume( docker::remote::copy_volume_container_rust( engine, &container, - &dirs.sysroot, + &toolchain, target.target(), mount_prefix.as_ref(), true, @@ -499,7 +499,7 @@ pub fn remove_persistent_volume( triple: cross::TargetTriple::X86_64UnknownLinuxGnu, }; let mut toolchain = QualifiedToolchain::default(msg_info)?; - toolchain.replace_host(&ImageArchitecture::from_target(target.target().clone())); + toolchain.replace_host(&ImagePlatform::from_target(target.target().clone())?); if let Some(channel) = channel { toolchain = toolchain.with_picked(channel.clone(), msg_info)?; }; diff --git a/src/config.rs b/src/config.rs index 62beae739..d5cba3c07 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,4 @@ -use crate::docker::{ImageArchitecture, PossibleImage}; +use crate::docker::{ImagePlatform, PossibleImage}; use crate::shell::{self, MessageInfo}; use crate::{CrossToml, Result, Target, TargetList}; @@ -68,10 +68,10 @@ impl Environment { fn image(&self, target: &Target) -> Result> { self.get_target_var(target, "IMAGE") - .map(|i| i.parse().expect("infallible")) + .map(Into::into) .map(|mut i: PossibleImage| { if let Some(toolchain) = self.get_target_var(target, "IMAGE_TOOLCHAIN") { - i.toolchain = Some(ImageArchitecture::from_target(toolchain.into())); + i.toolchain = Some(ImagePlatform::from_target(toolchain.into())?); Ok(i) } else { Ok(i) diff --git a/src/cross_toml.rs b/src/cross_toml.rs index a99d4cb2d..6c129f132 100644 --- a/src/cross_toml.rs +++ b/src/cross_toml.rs @@ -218,12 +218,12 @@ impl CrossToml { /// Returns the `target.{}.image` part of `Cross.toml` pub fn image(&self, target: &Target) -> Option { - self.get_string(target, |_| None, |t| t.image.as_ref()) + self.get_config(target, |_| None, |t| t.image.as_ref()) } /// Returns the `{}.dockerfile` or `{}.dockerfile.file` part of `Cross.toml` pub fn dockerfile(&self, target: &Target) -> Option { - self.get_string( + self.get_config( target, |b| b.dockerfile.as_ref().map(|c| &c.file), |t| t.dockerfile.as_ref().map(|c| &c.file), @@ -232,7 +232,7 @@ impl CrossToml { /// Returns the `target.{}.dockerfile.context` part of `Cross.toml` pub fn dockerfile_context(&self, target: &Target) -> Option { - self.get_string( + self.get_config( target, |b| b.dockerfile.as_ref().and_then(|c| c.context.as_ref()), |t| t.dockerfile.as_ref().and_then(|c| c.context.as_ref()), @@ -266,7 +266,7 @@ impl CrossToml { /// Returns the `target.{}.runner` part of `Cross.toml` pub fn runner(&self, target: &Target) -> Option { - self.get_string(target, |_| None, |t| t.runner.as_ref()) + self.get_config(target, |_| None, |t| t.runner.as_ref()) } /// Returns the `build.xargo` or the `target.{}.xargo` part of `Cross.toml` @@ -310,7 +310,7 @@ impl CrossToml { self.targets.get(target) } - fn get_string<'a, T: Clone + 'a>( + fn get_config<'a, T: Clone + 'a>( &'a self, target: &Target, get_build: impl Fn(&'a CrossBuildConfig) -> Option<&'a T>, @@ -406,7 +406,7 @@ where #[cfg(test)] mod tests { - use crate::docker::ImageArchitecture; + use crate::docker::ImagePlatform; use super::*; const MSG_INFO: MessageInfo = MessageInfo { @@ -414,7 +414,7 @@ mod tests { verbosity: shell::Verbosity::Quiet, }; - macro_rules! s { + macro_rules! p { ($x:literal) => { $x.parse()? }; @@ -482,7 +482,7 @@ mod tests { }, xargo: Some(false), build_std: Some(true), - image: Some("test-image".parse().expect("infallible")), + image: Some("test-image".into()), runner: None, dockerfile: None, pre_build: Some(vec![]), @@ -524,9 +524,9 @@ mod tests { build_std: None, image: Some(PossibleImage { name: "test-image".to_string(), - toolchain: Some(ImageArchitecture::from_target( + toolchain: Some(ImagePlatform::from_target( "aarch64-unknown-linux-musl".into(), - )), + )?), }), dockerfile: Some(CrossTargetDockerfileConfig { file: "Dockerfile.test".to_string(), @@ -750,39 +750,39 @@ mod tests { let build = &cfg_expected.build; assert_eq!(build.build_std, Some(true)); assert_eq!(build.xargo, Some(false)); - assert_eq!(build.default_target, Some(s!("aarch64-unknown-linux-gnu"))); + assert_eq!(build.default_target, Some(p!("aarch64-unknown-linux-gnu"))); assert_eq!(build.pre_build, None); assert_eq!(build.dockerfile, None); - assert_eq!(build.env.passthrough, Some(vec![s!("VAR3"), s!("VAR4")])); + assert_eq!(build.env.passthrough, Some(vec![p!("VAR3"), p!("VAR4")])); assert_eq!(build.env.volumes, Some(vec![])); let targets = &cfg_expected.targets; let aarch64 = &targets[&Target::new_built_in("aarch64-unknown-linux-gnu")]; assert_eq!(aarch64.build_std, Some(true)); assert_eq!(aarch64.xargo, Some(false)); - assert_eq!(aarch64.image, Some(s!("test-image1"))); + assert_eq!(aarch64.image, Some(p!("test-image1"))); assert_eq!(aarch64.pre_build, None); assert_eq!(aarch64.dockerfile, None); - assert_eq!(aarch64.env.passthrough, Some(vec![s!("VAR1")])); - assert_eq!(aarch64.env.volumes, Some(vec![s!("VOL1_ARG")])); + assert_eq!(aarch64.env.passthrough, Some(vec![p!("VAR1")])); + assert_eq!(aarch64.env.volumes, Some(vec![p!("VOL1_ARG")])); let target2 = &targets[&Target::new_custom("target2")]; assert_eq!(target2.build_std, Some(false)); assert_eq!(target2.xargo, Some(false)); - assert_eq!(target2.image, Some(s!("test-image2-precedence"))); + assert_eq!(target2.image, Some(p!("test-image2-precedence"))); assert_eq!(target2.pre_build, None); assert_eq!(target2.dockerfile, None); - assert_eq!(target2.env.passthrough, Some(vec![s!("VAR2_PRECEDENCE")])); - assert_eq!(target2.env.volumes, Some(vec![s!("VOL2_ARG_PRECEDENCE")])); + assert_eq!(target2.env.passthrough, Some(vec![p!("VAR2_PRECEDENCE")])); + assert_eq!(target2.env.volumes, Some(vec![p!("VOL2_ARG_PRECEDENCE")])); let target3 = &targets[&Target::new_custom("target3")]; assert_eq!(target3.build_std, Some(true)); assert_eq!(target3.xargo, Some(false)); - assert_eq!(target3.image, Some(s!("test-image3"))); + assert_eq!(target3.image, Some(p!("test-image3"))); assert_eq!(target3.pre_build, None); assert_eq!(target3.dockerfile, None); - assert_eq!(target3.env.passthrough, Some(vec![s!("VAR3")])); - assert_eq!(target3.env.volumes, Some(vec![s!("VOL3_ARG")])); + assert_eq!(target3.env.passthrough, Some(vec![p!("VAR3")])); + assert_eq!(target3.env.volumes, Some(vec![p!("VOL3_ARG")])); Ok(()) } diff --git a/src/docker/custom.rs b/src/docker/custom.rs index 8c9ad9fec..e1820c593 100644 --- a/src/docker/custom.rs +++ b/src/docker/custom.rs @@ -1,12 +1,12 @@ use std::io::Write; use std::path::{Path, PathBuf}; -use crate::docker::{Engine, ImageArchitecture}; +use crate::docker::{Engine, ImagePlatform}; use crate::shell::MessageInfo; use crate::{config::Config, docker, CargoMetadata, Target}; -use crate::{errors::*, file, CommandExt, ToUtf8}; +use crate::{errors::*, file, CommandExt, TargetTriple, ToUtf8}; -use super::{get_image, parse_docker_opts, path_hash}; +use super::{get_image_name, parse_docker_opts, path_hash}; pub const CROSS_CUSTOM_DOCKERFILE_IMAGE_PREFIX: &str = "cross-custom-"; @@ -16,11 +16,11 @@ pub enum Dockerfile<'a> { path: &'a str, context: Option<&'a str>, name: Option<&'a str>, - runs_with: &'a ImageArchitecture, + runs_with: &'a ImagePlatform, }, Custom { content: String, - runs_with: &'a ImageArchitecture, + runs_with: &'a ImagePlatform, }, } @@ -33,12 +33,14 @@ impl<'a> Dockerfile<'a> { engine: &Engine, host_root: &Path, build_args: impl IntoIterator, impl AsRef)>, - target_triple: &Target, msg_info: MessageInfo, ) -> Result { + let target_triple = &self.runs_with().target; let mut docker_build = docker::subcommand(engine, "build"); docker_build.current_dir(host_root); docker_build.env("DOCKER_SCAN_SUGGEST", "false"); + docker_build.args(&["--platform", &self.runs_with().docker_platform()]); + docker_build.args([ "--label", &format!( @@ -51,7 +53,6 @@ impl<'a> Dockerfile<'a> { &format!( "{}.runs-with={}", crate::CROSS_LABEL_DOMAIN, - // FIXME(emilgardis): this should maybe be the full image architecture, but that information is already encoded in the image self.runs_with().target ), ]); @@ -92,7 +93,13 @@ impl<'a> Dockerfile<'a> { }; if matches!(self, Dockerfile::File { .. }) { - if let Ok(cross_base_image) = self::get_image(config, target_triple) { + if let Ok(cross_base_image) = self::get_image_name( + config, + &Target::Custom { + // HACK: This shouldn't be needed, but fixing it requires a major rework of targets + triple: target_triple.clone(), + }, + ) { docker_build.args([ "--build-arg", &format!("CROSS_BASE_IMAGE={cross_base_image}"), @@ -116,7 +123,11 @@ impl<'a> Dockerfile<'a> { Ok(image_name) } - pub fn image_name(&self, target_triple: &Target, metadata: &CargoMetadata) -> Result { + pub fn image_name( + &self, + target_triple: &TargetTriple, + metadata: &CargoMetadata, + ) -> Result { match self { Dockerfile::File { name: Some(name), .. @@ -148,7 +159,7 @@ impl<'a> Dockerfile<'a> { _ => None, } } - fn runs_with(&self) -> &ImageArchitecture { + fn runs_with(&self) -> &ImagePlatform { match self { Dockerfile::File { runs_with, .. } => runs_with, Dockerfile::Custom { runs_with, .. } => runs_with, diff --git a/src/docker/image.rs b/src/docker/image.rs index 05a3a51ba..334f9d869 100644 --- a/src/docker/image.rs +++ b/src/docker/image.rs @@ -2,13 +2,13 @@ use std::str::FromStr; use serde::{Deserialize, Serialize}; -use crate::TargetTriple; +use crate::{errors::*, TargetTriple}; #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] pub struct Image { pub name: String, // The toolchain triple the image is built for - pub toolchain_triple: ImageArchitecture, + pub platform: ImagePlatform, } impl std::fmt::Display for Image { @@ -21,33 +21,39 @@ impl std::fmt::Display for Image { pub struct PossibleImage { pub name: String, // The toolchain triple the image is built for - pub toolchain: Option, + pub toolchain: Option, } impl PossibleImage { - pub(crate) fn to_definite_with(&self, architecture: &ImageArchitecture) -> Image { + pub(crate) fn to_definite_with(&self, architecture: &ImagePlatform) -> Image { if let Some(toolchain_triple) = &self.toolchain { Image { name: self.name.clone(), - toolchain_triple: toolchain_triple.clone(), + platform: toolchain_triple.clone(), } } else { Image { name: self.name.clone(), - toolchain_triple: architecture.clone(), + platform: architecture.clone(), } } } } +impl> From for PossibleImage { + fn from(s: T) -> Self { + PossibleImage { + name: s.as_ref().to_owned(), + toolchain: None, + } + } +} + impl FromStr for PossibleImage { type Err = std::convert::Infallible; fn from_str(s: &str) -> Result { - Ok(PossibleImage { - name: s.to_string(), - toolchain: None, - }) + Ok(s.into()) } } @@ -56,21 +62,27 @@ impl std::fmt::Display for PossibleImage { f.write_str(&self.name) } } - +/// The architecture/platform to use in the image +/// +/// https://github.com/containerd/containerd/blob/release/1.6/platforms/platforms.go#L63 #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[serde(try_from = "&str")] -pub struct ImageArchitecture { +pub struct ImagePlatform { + /// CPU architecture, x86_64, aarch64 etc pub architecture: Architecture, + /// The OS, i.e linux, windows, darwin pub os: Os, + /// The platform variant, i.e v8, v7, v6 etc pub variant: Option, pub target: TargetTriple, } -impl ImageArchitecture { +impl ImagePlatform { + pub const DEFAULT: Self = Self::X86_64_UNKNOWN_LINUX_GNU; pub const X86_64_UNKNOWN_LINUX_GNU: Self = - ImageArchitecture::from_target(TargetTriple::X86_64UnknownLinuxGnu); + ImagePlatform::from_const_target(TargetTriple::X86_64UnknownLinuxGnu); pub const AARCH64_UNKNOWN_LINUX_GNU: Self = - ImageArchitecture::from_target(TargetTriple::Aarch64UnknownLinuxGnu); + ImagePlatform::from_const_target(TargetTriple::Aarch64UnknownLinuxGnu); pub fn docker_platform(&self) -> String { if let Some(variant) = &self.variant { format!("{}/{}/{variant}", self.os, self.architecture) @@ -80,7 +92,7 @@ impl ImageArchitecture { } } -impl TryFrom<&str> for ImageArchitecture { +impl TryFrom<&str> for ImagePlatform { type Error = ::Err; fn try_from(value: &str) -> Result { @@ -88,7 +100,7 @@ impl TryFrom<&str> for ImageArchitecture { } } -impl std::str::FromStr for ImageArchitecture { +impl std::str::FromStr for ImagePlatform { type Err = eyre::Report; // [os/arch[/variant]=]toolchain fn from_str(s: &str) -> Result { @@ -111,14 +123,15 @@ impl std::str::FromStr for ImageArchitecture { } else { eyre::bail!("invalid platform specified") }; - Ok(ImageArchitecture { + Ok(ImagePlatform { architecture: Architecture::deserialize(arch)?, os: Os::deserialize(os)?, variant: variant.map(ToOwned::to_owned), target: image_toolchain, }) } else { - Ok(ImageArchitecture::from_target(s.into())) + Ok(ImagePlatform::from_target(s.into()) + .wrap_err_with(|| format!("could not map `{s}` to a platform"))?) } } } @@ -129,6 +142,7 @@ pub enum Architecture { I386, Amd64, Arm, + #[serde(alias = "aarch64")] Arm64, Mips, Mips64, @@ -141,6 +155,19 @@ pub enum Architecture { Wasm, } +impl Architecture { + pub fn from_target(target: &TargetTriple) -> Result { + use serde::de::IntoDeserializer; + let arch = target + .triple() + .split_once('-') + .ok_or_else(|| eyre::eyre!("malformed target"))? + .0; + Self::deserialize(<&str as IntoDeserializer>::into_deserializer(arch)) + .wrap_err_with(|| format!("architecture {arch} is not supported")) + } +} + impl std::fmt::Display for Architecture { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.serialize(f) @@ -153,6 +180,7 @@ impl std::fmt::Display for Architecture { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "lowercase")] pub enum Os { + #[serde(alias = "macos")] Darwin, Freebsd, Illumos, @@ -169,54 +197,81 @@ pub enum Os { //Solaris, } +impl Os { + pub fn from_target(target: &TargetTriple) -> Result { + use serde::de::IntoDeserializer; + let vendor = target + .triple() + .split('-') + .nth(2) + .ok_or_else(|| eyre::eyre!("malformed target"))?; + + Self::deserialize(<&str as IntoDeserializer>::into_deserializer(vendor)) + .wrap_err_with(|| format!("os {vendor} is not supported")) + } +} + impl std::fmt::Display for Os { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.serialize(f) } } -impl ImageArchitecture { +impl ImagePlatform { + pub fn from_target(target: TargetTriple) -> Result { + match target { + target @ TargetTriple::Other(_) => Ok(ImagePlatform { + architecture: Architecture::from_target(&target)?, + os: Os::from_target(&target)?, + variant: None, + target, + }), + target => Ok(Self::from_const_target(target)), + } + } #[track_caller] - pub const fn from_target(target: TargetTriple) -> Self { + pub const fn from_const_target(target: TargetTriple) -> Self { match target { - TargetTriple::Other(_) => todo!(), - TargetTriple::X86_64AppleDarwin => ImageArchitecture { + TargetTriple::Other(_) => { + unimplemented!() + } + TargetTriple::X86_64AppleDarwin => ImagePlatform { architecture: Architecture::Amd64, os: Os::Darwin, variant: None, target, }, - TargetTriple::Aarch64AppleDarwin => ImageArchitecture { + TargetTriple::Aarch64AppleDarwin => ImagePlatform { architecture: Architecture::Arm64, os: Os::Linux, variant: None, target, }, - TargetTriple::X86_64UnknownLinuxGnu => ImageArchitecture { + TargetTriple::X86_64UnknownLinuxGnu => ImagePlatform { architecture: Architecture::Amd64, os: Os::Linux, variant: None, target, }, - TargetTriple::Aarch64UnknownLinuxGnu => ImageArchitecture { + TargetTriple::Aarch64UnknownLinuxGnu => ImagePlatform { architecture: Architecture::Arm64, os: Os::Linux, variant: None, target, }, - TargetTriple::X86_64UnknownLinuxMusl => ImageArchitecture { + TargetTriple::X86_64UnknownLinuxMusl => ImagePlatform { architecture: Architecture::Amd64, os: Os::Linux, variant: None, target, }, - TargetTriple::Aarch64UnknownLinuxMusl => ImageArchitecture { + TargetTriple::Aarch64UnknownLinuxMusl => ImagePlatform { architecture: Architecture::Arm, os: Os::Linux, variant: None, target, }, - TargetTriple::X86_64PcWindowsMsvc => ImageArchitecture { + TargetTriple::X86_64PcWindowsMsvc => ImagePlatform { architecture: Architecture::Amd64, os: Os::Windows, variant: None, diff --git a/src/docker/local.rs b/src/docker/local.rs index 1f72076bd..1e68f5d2b 100644 --- a/src/docker/local.rs +++ b/src/docker/local.rs @@ -9,6 +9,7 @@ use crate::cargo::CargoMetadata; use crate::errors::Result; use crate::extensions::CommandExt; use crate::file::{PathExt, ToUtf8}; +use crate::rustc::QualifiedToolchain; use crate::shell::{MessageInfo, Stream}; use crate::{Config, Target}; use eyre::Context; @@ -22,18 +23,26 @@ pub(crate) fn run( metadata: &CargoMetadata, config: &Config, uses_xargo: bool, - sysroot: &Path, + toolchain: &QualifiedToolchain, msg_info: MessageInfo, docker_in_docker: bool, cwd: &Path, ) -> Result { - let dirs = Directories::create(engine, metadata, cwd, sysroot, docker_in_docker)?; + let dirs = Directories::create( + engine, + metadata, + cwd, + &toolchain.get_sysroot(), + docker_in_docker, + )?; let mut cmd = cargo_safe_command(uses_xargo); cmd.args(args); let mut docker = subcommand(engine, "run"); docker.args(&["--userns", "host"]); + docker.args(&["--platform", &image.platform.docker_platform()]); + docker_envvars(&mut docker, config, target, msg_info)?; let mount_volumes = docker_mount( diff --git a/src/docker/mod.rs b/src/docker/mod.rs index 5ea144780..07cf8344c 100644 --- a/src/docker/mod.rs +++ b/src/docker/mod.rs @@ -10,23 +10,39 @@ pub use self::engine::*; pub use self::provided_images::PROVIDED_IMAGES; pub use self::shared::*; -pub use image::{Architecture, Image, ImageArchitecture, Os as DockerOs, PossibleImage}; +pub use image::{Architecture, Image, ImagePlatform, Os as DockerOs, PossibleImage}; use std::path::Path; use std::process::ExitStatus; use crate::cargo::CargoMetadata; use crate::errors::*; +use crate::rustc::QualifiedToolchain; use crate::shell::MessageInfo; use crate::{Config, Target}; #[derive(Debug)] pub struct ProvidedImage { + /// The `name` of the image, usually the target triplet pub name: &'static str, - pub platforms: &'static [ImageArchitecture], + pub platforms: &'static [ImagePlatform], pub sub: Option<&'static str>, } +impl ProvidedImage { + pub fn image_name(&self, repository: &str, tag: &str) -> String { + image_name(self.name, self.sub, repository, tag) + } +} + +pub fn image_name(target: &str, sub: Option<&str>, repository: &str, tag: &str) -> String { + if let Some(sub) = sub { + format!("{repository}/{target}:{tag}-{sub}") + } else { + format!("{repository}/{target}:{tag}") + } +} + #[allow(clippy::too_many_arguments)] // TODO: refactor pub fn run( engine: &Engine, @@ -36,7 +52,7 @@ pub fn run( metadata: &CargoMetadata, config: &Config, uses_xargo: bool, - sysroot: &Path, + toolchain: &QualifiedToolchain, msg_info: MessageInfo, docker_in_docker: bool, cwd: &Path, @@ -50,7 +66,7 @@ pub fn run( metadata, config, uses_xargo, - sysroot, + toolchain, msg_info, docker_in_docker, cwd, @@ -64,7 +80,7 @@ pub fn run( metadata, config, uses_xargo, - sysroot, + toolchain, msg_info, docker_in_docker, cwd, diff --git a/src/docker/provided_images.rs b/src/docker/provided_images.rs index baf62bbf4..8ed09dc09 100644 --- a/src/docker/provided_images.rs +++ b/src/docker/provided_images.rs @@ -1,281 +1,281 @@ #![doc = "*** AUTO-GENERATED, do not touch. Run `cargo xtask codegen` to update ***"] -use super::{ImageArchitecture, ProvidedImage}; +use super::{ImagePlatform, ProvidedImage}; #[rustfmt::skip] pub static PROVIDED_IMAGES: &[ProvidedImage] = &[ ProvidedImage { name: "x86_64-apple-darwin", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-unknown-linux-musl", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-pc-windows-msvc", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: Some("centos") }, ProvidedImage { name: "aarch64-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "arm-unknown-linux-gnueabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "arm-unknown-linux-gnueabihf", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv7-unknown-linux-gnueabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv7-unknown-linux-gnueabihf", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "thumbv7neon-unknown-linux-gnueabihf", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i586-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i686-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mips-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mipsel-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mips64-unknown-linux-gnuabi64", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mips64el-unknown-linux-gnuabi64", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mips64-unknown-linux-muslabi64", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mips64el-unknown-linux-muslabi64", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "powerpc-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "powerpc64-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "powerpc64le-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "riscv64gc-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "s390x-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "sparc64-unknown-linux-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "aarch64-unknown-linux-musl", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "arm-unknown-linux-musleabihf", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "arm-unknown-linux-musleabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv5te-unknown-linux-gnueabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv5te-unknown-linux-musleabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv7-unknown-linux-musleabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv7-unknown-linux-musleabihf", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i586-unknown-linux-musl", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i686-unknown-linux-musl", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mips-unknown-linux-musl", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "mipsel-unknown-linux-musl", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "aarch64-linux-android", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "arm-linux-androideabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "armv7-linux-androideabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "thumbv7neon-linux-androideabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i686-linux-android", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-linux-android", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-pc-windows-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i686-pc-windows-gnu", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "wasm32-unknown-emscripten", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-unknown-dragonfly", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "i686-unknown-freebsd", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-unknown-freebsd", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-unknown-netbsd", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "sparcv9-sun-solaris", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "x86_64-sun-solaris", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "thumbv6m-none-eabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "thumbv7em-none-eabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "thumbv7em-none-eabihf", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ProvidedImage { name: "thumbv7m-none-eabi", - platforms: &[ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU], + platforms: &[ImagePlatform::DEFAULT], sub: None }, ]; diff --git a/src/docker/remote.rs b/src/docker/remote.rs index 56135dd65..67b306f4a 100644 --- a/src/docker/remote.rs +++ b/src/docker/remote.rs @@ -11,7 +11,7 @@ use crate::config::{bool_from_envvar, Config}; use crate::errors::Result; use crate::extensions::CommandExt; use crate::file::{self, PathExt, ToUtf8}; -use crate::rustc::{self, VersionMetaExt}; +use crate::rustc::{self, QualifiedToolchain, VersionMetaExt}; use crate::rustup; use crate::shell::{self, MessageInfo, Stream}; use crate::temp; @@ -331,20 +331,21 @@ fn copy_volume_container_rust_manifest( pub fn copy_volume_container_rust_triple( engine: &Engine, container: &str, - sysroot: &Path, - triple: &TargetTriple, + toolchain: &QualifiedToolchain, + target_triple: &TargetTriple, mount_prefix: &Path, skip_exists: bool, msg_info: MessageInfo, ) -> Result<()> { + let sysroot = toolchain.get_sysroot(); // copy over the files for a specific triple let dst = mount_prefix.join("rust"); let rustlib = Path::new("lib").join("rustlib"); let dst_rustlib = dst.join(&rustlib); - let src_toolchain = sysroot.join(&rustlib).join(triple.triple()); - let dst_toolchain = dst_rustlib.join(triple.triple()); + let src_toolchain = sysroot.join(&rustlib).join(target_triple.triple()); + let dst_toolchain = dst_rustlib.join(target_triple.triple()); - // skip if the toolchain already exists. for the host toolchain + // skip if the toolchain target component already exists. for the host toolchain // or the first run of the target toolchain, we know it doesn't exist. let mut skip = false; if skip_exists { @@ -356,7 +357,7 @@ pub fn copy_volume_container_rust_triple( if !skip && skip_exists { // this means we have a persistent data volume and we have a // new target, meaning we might have new manifests as well. - copy_volume_container_rust_manifest(engine, container, sysroot, mount_prefix, msg_info)?; + copy_volume_container_rust_manifest(engine, container, &sysroot, mount_prefix, msg_info)?; } Ok(()) @@ -365,31 +366,41 @@ pub fn copy_volume_container_rust_triple( pub fn copy_volume_container_rust( engine: &Engine, container: &str, - sysroot: &Path, + toolchain: &QualifiedToolchain, target_triple: &TargetTriple, mount_prefix: &Path, skip_target: bool, msg_info: MessageInfo, ) -> Result<()> { - let image_triple = TargetTriple::X86_64UnknownLinuxGnu; - - copy_volume_container_rust_base(engine, container, sysroot, mount_prefix, msg_info)?; - copy_volume_container_rust_manifest(engine, container, sysroot, mount_prefix, msg_info)?; + copy_volume_container_rust_base( + engine, + container, + &toolchain.get_sysroot(), + mount_prefix, + msg_info, + )?; + copy_volume_container_rust_manifest( + engine, + container, + &toolchain.get_sysroot(), + mount_prefix, + msg_info, + )?; copy_volume_container_rust_triple( engine, container, - sysroot, - &image_triple, + toolchain, + &toolchain.host().target, mount_prefix, false, msg_info, )?; // TODO: impl Eq - if !skip_target && target_triple.triple() != image_triple.triple() { + if !skip_target && target_triple.triple() != toolchain.host().target.triple() { copy_volume_container_rust_triple( engine, container, - sysroot, + toolchain, target_triple, mount_prefix, false, @@ -706,12 +717,18 @@ pub(crate) fn run( metadata: &CargoMetadata, config: &Config, uses_xargo: bool, - sysroot: &Path, + toolchain: &QualifiedToolchain, msg_info: MessageInfo, docker_in_docker: bool, cwd: &Path, ) -> Result { - let dirs = Directories::create(engine, metadata, cwd, sysroot, docker_in_docker)?; + let dirs = Directories::create( + engine, + metadata, + cwd, + &toolchain.get_sysroot(), + docker_in_docker, + )?; let mount_prefix = MOUNT_PREFIX; @@ -834,7 +851,7 @@ pub(crate) fn run( copy_volume_container_rust( engine, &container, - &dirs.sysroot, + toolchain, target.target(), mount_prefix_path, false, @@ -845,7 +862,7 @@ pub(crate) fn run( copy_volume_container_rust_triple( engine, &container, - &dirs.sysroot, + toolchain, target.target(), mount_prefix_path, true, diff --git a/src/docker/shared.rs b/src/docker/shared.rs index c0f10ad11..a87172346 100644 --- a/src/docker/shared.rs +++ b/src/docker/shared.rs @@ -4,19 +4,19 @@ use std::process::Command; use std::{env, fs}; use super::custom::Dockerfile; -use super::engine::*; use super::image::PossibleImage; use super::PROVIDED_IMAGES; -use super::{Image, ImageArchitecture}; +use super::{engine::*, DockerOs}; +use super::{Image, ImagePlatform}; use crate::cargo::{cargo_metadata_with_args, CargoMetadata}; use crate::config::Config; +use crate::errors::*; use crate::extensions::{CommandExt, SafeCommand}; use crate::file::{self, write_file, PathExt, ToUtf8}; use crate::id; use crate::rustc::QualifiedToolchain; use crate::shell::{self, MessageInfo, Verbosity}; use crate::Target; -use crate::{errors::*, TargetTriple}; pub use super::custom::CROSS_CUSTOM_DOCKERFILE_IMAGE_PREFIX; @@ -471,7 +471,7 @@ pub(crate) fn custom_image_build( } else { None }, - runs_with: &base_or_custom_image.toolchain_triple, + runs_with: &base_or_custom_image.platform, }; build @@ -481,7 +481,6 @@ pub(crate) fn custom_image_build( engine, &host_root, config.dockerfile_build_args(target)?.unwrap_or_default(), - target, msg_info, ) .wrap_err("when building dockerfile")? @@ -501,7 +500,7 @@ pub(crate) fn custom_image_build( ARG CROSS_CMD RUN eval "${{CROSS_CMD}}""# ), - runs_with: &base_or_custom_image.toolchain_triple, + runs_with: &base_or_custom_image.platform, }; custom .build( @@ -510,20 +509,20 @@ pub(crate) fn custom_image_build( engine, &host_root, Some(("CROSS_CMD", pre_build.join("\n"))), - target, msg_info, ) .wrap_err("when pre-building") .with_note(|| format!("CROSS_CMD={}", pre_build.join("\n")))?; - base_or_custom_image.name = custom.image_name(target, metadata)?; + base_or_custom_image.name = custom.image_name(target.target(), metadata)?; } } Ok(base_or_custom_image.name) } -pub(crate) fn get_image(config: &Config, target: &Target) -> Result { +/// Simpler version of [get_image] +pub fn get_image_name(config: &Config, target: &Target) -> Result { if let Some(image) = config.image(target)? { - return Ok(image); + return Ok(image.name); } let compatible = PROVIDED_IMAGES @@ -534,12 +533,42 @@ pub(crate) fn get_image(config: &Config, target: &Target) -> Result 1 { - // TODO: pick the best image. e.g not one that is not + let version = if include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")).is_empty() { + env!("CARGO_PKG_VERSION") + } else { + "main" + }; + + Ok(compatible + .get(0) + .expect("should not be empty") + .image_name(CROSS_IMAGE, version)) +} + +pub(crate) fn get_image( + config: &Config, + target: &Target, + host_platform: ImagePlatform, + msg_info: MessageInfo, +) -> Result { + if let Some(image) = config.image(target)? { + return Ok(image); + } + + let compatible = PROVIDED_IMAGES + .iter() + .filter(|p| p.name == target.triple()) + .collect::>(); + + if compatible.is_empty() { + eyre::bail!( + "`cross` does not provide a Docker image for target {target}, \ + specify a custom image in `Cross.toml`." + ); } let version = if include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")).is_empty() { @@ -548,13 +577,81 @@ pub(crate) fn get_image(config: &Config, target: &Target) -> Result>() + .join(", ") + ) + })); + }; + + let mut image: PossibleImage = pick.image_name(CROSS_IMAGE, version).into(); + + eyre::ensure!( + !pick.platforms.is_empty(), + "platforms for provided image `{image}` are not specified, this is a bug" + ); + + let toolchain = if pick.platforms.len() == 1 { + pick.platforms.get(0).expect("should not be empty") + } else { + let same_arch = pick + .platforms + .iter() + .filter(|platform| platform.architecture == host_platform.architecture) + .collect::>(); + + if same_arch.len() == 1 { + // pick the platform with the same architecture + same_arch.get(0).expect("should containt one element") + } else if let Some(platform) = same_arch + .iter() + .find(|platform| platform.os == host_platform.os) + { + *platform + } else if let Some(platform) = same_arch + .iter() + .find(|platform| platform.os == DockerOs::Linux) + { + // container engine should be fine with linux + platform + } else { + let platform = pick + .platforms + .get(0) + .expect("should be at least one platform"); + shell::warn( + "could not determine what toolchain to use for image, defaulting to `{platform}`", + msg_info, + )?; + platform + } + }; + image.toolchain = Some(toolchain.clone()); Ok(image) } diff --git a/src/lib.rs b/src/lib.rs index 1e7b5ab53..26f36348c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,73 @@ pub enum TargetTriple { } impl TargetTriple { + /// Returns the architecture name according to `dpkg` naming convention + /// + /// # Notes + /// + /// Some of these make no sense to use in our standard images + pub fn deb_arch(&self) -> Option<&'static str> { + match self.triple() { + "aarch64-unknown-linux-gnu" => Some("arm64"), + "aarch64-unknown-linux-musl" => Some("musl-linux-arm64"), + "aarch64-linux-android" => None, + "x86_64-unknown-linux-gnu" => Some("amd64"), + "x86_64-apple-darwin" => Some("darwin-amd64"), + "x86_64-unknown-linux-musl" => Some("musl-linux-amd64"), + + "x86_64-pc-windows-msvc" => None, + "arm-unknown-linux-gnueabi" => Some("armel"), + "arm-unknown-linux-gnueabihf" => Some("armhf"), + "armv7-unknown-linux-gnueabi" => Some("armel"), + "armv7-unknown-linux-gnueabihf" => Some("armhf"), + "thumbv7neon-unknown-linux-gnueabihf" => Some("armhf"), + "i586-unknown-linux-gnu" => Some("i386"), + "i686-unknown-linux-gnu" => Some("i386"), + "mips-unknown-linux-gnu" => Some("mips"), + "mipsel-unknown-linux-gnu" => Some("mipsel"), + "mips64-unknown-linux-gnuabi64" => Some("mips64"), + "mips64el-unknown-linux-gnuabi64" => Some("mips64el"), + "mips64-unknown-linux-muslabi64" => Some("musl-linux-mips64"), + "mips64el-unknown-linux-muslabi64" => Some("musl-linux-mips64el"), + "powerpc-unknown-linux-gnu" => Some("powerpc"), + "powerpc64-unknown-linux-gnu" => Some("ppc64"), + "powerpc64le-unknown-linux-gnu" => Some("ppc64el"), + "riscv64gc-unknown-linux-gnu" => Some("riscv64"), + "s390x-unknown-linux-gnu" => Some("s390x"), + "sparc64-unknown-linux-gnu" => Some("sparc64"), + "arm-unknown-linux-musleabihf" => Some("musl-linux-armhf"), + "arm-unknown-linux-musleabi" => Some("musl-linux-arm"), + "armv5te-unknown-linux-gnueabi" => None, + "armv5te-unknown-linux-musleabi" => None, + "armv7-unknown-linux-musleabi" => Some("musl-linux-arm"), + "armv7-unknown-linux-musleabihf" => Some("musl-linux-armhf"), + "i586-unknown-linux-musl" => Some("musl-linux-i386"), + "i686-unknown-linux-musl" => Some("musl-linux-i386"), + "mips-unknown-linux-musl" => Some("musl-linux-mips"), + "mipsel-unknown-linux-musl" => Some("musl-linux-mipsel"), + "arm-linux-androideabi" => None, + "armv7-linux-androideabi" => None, + "thumbv7neon-linux-androideabi" => None, + "i686-linux-android" => None, + "x86_64-linux-android" => None, + "x86_64-pc-windows-gnu" => None, + "i686-pc-windows-gnu" => None, + "asmjs-unknown-emscripten" => None, + "wasm32-unknown-emscripten" => None, + "x86_64-unknown-dragonfly" => Some("dragonflybsd-amd64"), + "i686-unknown-freebsd" => Some("freebsd-i386"), + "x86_64-unknown-freebsd" => Some("freebsd-amd64"), + "x86_64-unknown-netbsd" => Some("netbsd-amd64"), + "sparcv9-sun-solaris" => Some("solaris-sparc"), + "x86_64-sun-solaris" => Some("solaris-amd64"), + "thumbv6m-none-eabi" => Some("arm"), + "thumbv7em-none-eabi" => Some("arm"), + "thumbv7em-none-eabihf" => Some("armhf"), + "thumbv7m-none-eabi" => Some("arm"), + _ => None, + } + } + /// Checks if this `(host, target)` pair is supported by `cross` /// /// `target == None` means `target == host` @@ -269,73 +336,6 @@ impl Target { arch_32bit && self.is_android() } - - /// Returns the architecture name according to `dpkg` naming convention - /// - /// # Notes - /// - /// Some of these make no sense to use in our standard images - pub fn deb_arch(&self) -> Option<&'static str> { - match self.triple() { - "aarch64-unknown-linux-gnu" => Some("arm64"), - "aarch64-unknown-linux-musl" => Some("musl-linux-arm64"), - "aarch64-linux-android" => None, - "x86_64-unknown-linux-gnu" => Some("amd64"), - "x86_64-apple-darwin" => Some("darwin-amd64"), - "x86_64-unknown-linux-musl" => Some("musl-linux-amd64"), - - "x86_64-pc-windows-msvc" => None, - "arm-unknown-linux-gnueabi" => Some("armel"), - "arm-unknown-linux-gnueabihf" => Some("armhf"), - "armv7-unknown-linux-gnueabi" => Some("armel"), - "armv7-unknown-linux-gnueabihf" => Some("armhf"), - "thumbv7neon-unknown-linux-gnueabihf" => Some("armhf"), - "i586-unknown-linux-gnu" => Some("i386"), - "i686-unknown-linux-gnu" => Some("i386"), - "mips-unknown-linux-gnu" => Some("mips"), - "mipsel-unknown-linux-gnu" => Some("mipsel"), - "mips64-unknown-linux-gnuabi64" => Some("mips64"), - "mips64el-unknown-linux-gnuabi64" => Some("mips64el"), - "mips64-unknown-linux-muslabi64" => Some("musl-linux-mips64"), - "mips64el-unknown-linux-muslabi64" => Some("musl-linux-mips64el"), - "powerpc-unknown-linux-gnu" => Some("powerpc"), - "powerpc64-unknown-linux-gnu" => Some("ppc64"), - "powerpc64le-unknown-linux-gnu" => Some("ppc64el"), - "riscv64gc-unknown-linux-gnu" => Some("riscv64"), - "s390x-unknown-linux-gnu" => Some("s390x"), - "sparc64-unknown-linux-gnu" => Some("sparc64"), - "arm-unknown-linux-musleabihf" => Some("musl-linux-armhf"), - "arm-unknown-linux-musleabi" => Some("musl-linux-arm"), - "armv5te-unknown-linux-gnueabi" => None, - "armv5te-unknown-linux-musleabi" => None, - "armv7-unknown-linux-musleabi" => Some("musl-linux-arm"), - "armv7-unknown-linux-musleabihf" => Some("musl-linux-armhf"), - "i586-unknown-linux-musl" => Some("musl-linux-i386"), - "i686-unknown-linux-musl" => Some("musl-linux-i386"), - "mips-unknown-linux-musl" => Some("musl-linux-mips"), - "mipsel-unknown-linux-musl" => Some("musl-linux-mipsel"), - "arm-linux-androideabi" => None, - "armv7-linux-androideabi" => None, - "thumbv7neon-linux-androideabi" => None, - "i686-linux-android" => None, - "x86_64-linux-android" => None, - "x86_64-pc-windows-gnu" => None, - "i686-pc-windows-gnu" => None, - "asmjs-unknown-emscripten" => None, - "wasm32-unknown-emscripten" => None, - "x86_64-unknown-dragonfly" => Some("dragonflybsd-amd64"), - "i686-unknown-freebsd" => Some("freebsd-i386"), - "x86_64-unknown-freebsd" => Some("freebsd-amd64"), - "x86_64-unknown-netbsd" => Some("netbsd-amd64"), - "sparcv9-sun-solaris" => Some("solaris-sparc"), - "x86_64-sun-solaris" => Some("solaris-amd64"), - "thumbv6m-none-eabi" => Some("arm"), - "thumbv7em-none-eabi" => Some("arm"), - "thumbv7em-none-eabihf" => Some("armhf"), - "thumbv7m-none-eabi" => Some("arm"), - _ => None, - } - } } impl std::fmt::Display for Target { @@ -396,14 +396,23 @@ pub fn run( target_list: TargetList, msg_info: MessageInfo, ) -> Result> { - if args.all.iter().any(|a| a == "--version" || a == "-V") && args.subcommand.is_none() { - println!( - concat!("cross ", env!("CARGO_PKG_VERSION"), "{}"), - include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) - ); + if args.version && args.subcommand.is_none() { + let commit_info = include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")); + shell::print( + format!( + concat!("cross ", env!("CARGO_PKG_VERSION"), "{}"), + commit_info + ), + args.msg_info, + )?; } - let host_version_meta = rustc_version::version_meta()?; + let host_version_meta = rustc::version_meta()?; + let host_platform = host_version_meta + .host + .parse() + .wrap_err("could not parse host information")?; + let cwd = std::env::current_dir()?; if let Some(metadata) = cargo_metadata_with_args(None, Some(&args), args.msg_info)? { let host = host_version_meta.host(); @@ -417,7 +426,7 @@ pub fn run( // Get the image we're supposed to base all our next actions on. // The image we actually run in might get changed with `target.{{TARGET}}.dockerfile` or `target.{{TARGET}}.pre-build` - let image = match docker::get_image(&config, &target) { + let image = match docker::get_image(&config, &target, host_platform, msg_info) { Ok(i) => i, Err(err) => { shell::warn(err, args.msg_info)?; @@ -456,15 +465,17 @@ To override the toolchain mounted in the image, set `target.{}.image.toolchain = let image = image.to_definite_with(toolchain.host()); - // if &image.toolchain_triple != toolchain.host() { - // eprintln!("Warning: toolchain `{toolchain}` may not run on image `{image}`") - // } - - toolchain.replace_host(&image.toolchain_triple); + toolchain.replace_host(&image.platform); let sysroot = toolchain.get_sysroot(); - if image.toolchain_triple.target.is_supported(Some(&target)) { + if image.platform.target.is_supported(Some(&target)) { + if &image.platform != toolchain.host() { + shell::warn( + format_args!("toolchain `{toolchain}` may not run on image `{image}`"), + msg_info, + )?; + } // set the sysroot explicitly to the toolchain let mut is_nightly = toolchain.channel.contains("nightly"); @@ -596,7 +607,7 @@ To override the toolchain mounted in the image, set `target.{}.image.toolchain = &metadata, &config, uses_xargo, - &sysroot, + &toolchain, args.msg_info, args.docker_in_docker, &cwd, @@ -636,7 +647,7 @@ pub(crate) fn warn_host_version_mismatch( .split_once(' ') .and_then(|x| x.1.strip_suffix(')')); - // This should only hit on non Host::X86_64UnknownLinuxGnu hosts + // This should only hit on non TargetTriple::X86_64UnknownLinuxGnu hosts if rustc_version != &host_version_meta.semver || (Some(rustc_commit) != host_commit) { let versions = rustc_version.cmp(&host_version_meta.semver); let dates = rustc_commit_date.cmp(&host_version_meta.commit_date.as_deref()); diff --git a/src/rustc.rs b/src/rustc.rs index 120860b4f..5db78515f 100644 --- a/src/rustc.rs +++ b/src/rustc.rs @@ -4,7 +4,7 @@ use std::process::Command; use rustc_version::{Version, VersionMeta}; use serde::Deserialize; -use crate::docker::ImageArchitecture; +use crate::docker::ImagePlatform; use crate::errors::*; use crate::extensions::{env_program, CommandExt}; use crate::shell::MessageInfo; @@ -83,19 +83,14 @@ pub fn hash_from_version_string(version: &str, index: usize) -> String { pub struct QualifiedToolchain { pub channel: String, pub date: Option, - pub(self) host: ImageArchitecture, + pub(self) host: ImagePlatform, pub is_custom: bool, pub full: String, pub(self) sysroot: PathBuf, } impl QualifiedToolchain { - pub fn new( - channel: &str, - date: &Option, - host: &ImageArchitecture, - sysroot: &Path, - ) -> Self { + pub fn new(channel: &str, date: &Option, host: &ImagePlatform, sysroot: &Path) -> Self { let mut this = Self { channel: channel.to_string(), date: date.clone(), @@ -113,7 +108,7 @@ impl QualifiedToolchain { } /// Replace the host, does nothing if ran on a custom toolchain - pub fn replace_host(&mut self, host: &ImageArchitecture) -> &mut Self { + pub fn replace_host(&mut self, host: &ImagePlatform) -> &mut Self { if !self.is_custom { *self = Self::new(&self.channel, &self.date, host, &self.sysroot); self.sysroot.set_file_name(&self.full); @@ -166,7 +161,7 @@ impl QualifiedToolchain { rustc_version::Channel::Stable => "stable", }, &build_date, - &ImageArchitecture::from_target(host.into()), + &ImagePlatform::from_target(host.into())?, sysroot, ); toolchain.is_custom = true; @@ -179,7 +174,7 @@ impl QualifiedToolchain { .suggestion("set `CROSS_CUSTOM_TOOLCHAIN_COMPAT` to a fully qualified toolchain name: i.e `nightly-aarch64-unknown-linux-musl`") } - pub fn host(&self) -> &ImageArchitecture { + pub fn host(&self) -> &ImagePlatform { &self.host } @@ -204,14 +199,14 @@ impl QualifiedToolchain { } } - /// Grab the current default toolchain + /// Merge a "picked" toolchain, overriding set fields. pub fn with_picked(self, picked: Toolchain, msg_info: MessageInfo) -> Result { let toolchain = Self::default(msg_info)?; let date = picked.date.or(self.date); let host = picked .host - .map(ImageArchitecture::from_target) - .unwrap_or(self.host); + .map(ImagePlatform::from_target) + .unwrap_or(Ok(self.host))?; let channel = picked.channel; Ok(QualifiedToolchain::new( @@ -241,7 +236,7 @@ impl QualifiedToolchain { }) => Ok(QualifiedToolchain { channel, date, - host: ImageArchitecture::from_target(host), + host: ImagePlatform::from_target(host)?, is_custom, full, sysroot, @@ -255,16 +250,6 @@ impl QualifiedToolchain { } } -#[test] -fn bisect() { - QualifiedToolchain::custom( - "bisector-nightly-2022-04-26-x86_64-unknown-linux-gnu", - "/tmp/cross/sysroot".as_ref(), - MessageInfo::create(true, false, None).unwrap(), - ) - .unwrap(); -} - #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] pub struct Toolchain { pub channel: String, @@ -327,10 +312,6 @@ impl std::str::FromStr for Toolchain { } } -#[derive(thiserror::Error, Debug, Clone)] -#[error("`{0}` is not a valid toolchain")] -pub struct ToolchainParseError(String); - pub fn rustc_command() -> Command { Command::new(env_program("RUSTC", "rustc")) } @@ -361,6 +342,16 @@ pub fn version_meta() -> Result { mod tests { use super::*; + #[test] + fn bisect() { + QualifiedToolchain::custom( + "bisector-nightly-2022-04-26-x86_64-unknown-linux-gnu", + "/tmp/cross/sysroot".as_ref(), + MessageInfo::create(true, false, None).unwrap(), + ) + .unwrap(); + } + #[test] fn hash_from_rustc() { assert_eq!( diff --git a/src/tests.rs b/src/tests.rs index 9a30325fe..9e872b833 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -8,7 +8,7 @@ use std::{ use once_cell::sync::OnceCell; use rustc_version::VersionMeta; -use crate::{docker::ImageArchitecture, rustc::QualifiedToolchain, TargetTriple}; +use crate::{docker::ImagePlatform, rustc::QualifiedToolchain, TargetTriple}; static WORKSPACE: OnceCell = OnceCell::new(); @@ -82,7 +82,7 @@ release: {version} &QualifiedToolchain::new( "xxxx", &None, - &ImageArchitecture::from_target(TargetTriple::X86_64UnknownLinuxGnu), + &ImagePlatform::from_const_target(TargetTriple::X86_64UnknownLinuxGnu), Path::new("/toolchains/xxxx-x86_64-unknown-linux-gnu"), ), &target_meta.0, diff --git a/xtask/src/build_docker_image.rs b/xtask/src/build_docker_image.rs index 04a0cbac1..0de640421 100644 --- a/xtask/src/build_docker_image.rs +++ b/xtask/src/build_docker_image.rs @@ -3,7 +3,7 @@ use std::path::Path; use crate::util::{cargo_metadata, gha_error, gha_output, gha_print}; use clap::Args; -use cross::docker::ImageArchitecture; +use cross::docker::ImagePlatform; use cross::shell::{self, MessageInfo}; use cross::{docker, CommandExt, ToUtf8}; @@ -69,7 +69,7 @@ pub struct BuildDockerImage { pub build_arg: Vec, // [os/arch[/variant]=]toolchain #[clap(long, short = 'a', action = clap::builder::ArgAction::Append)] - pub platform: Vec, + pub platform: Vec, /// Targets to build for #[clap()] pub targets: Vec, @@ -157,9 +157,7 @@ pub fn build_docker_image( .collect::>>()?; let platforms = if platform.is_empty() { - vec![ImageArchitecture::from_target( - cross::TargetTriple::X86_64UnknownLinuxGnu, - )] + vec![ImagePlatform::DEFAULT] } else { platform }; @@ -172,7 +170,10 @@ pub fn build_docker_image( if gha && targets.len() > 1 { gha_print("::group::Build {target}"); } else { - eprintln!("Build {target} for {}", platform.target); + shell::note( + format_args!("Build {target} for {}", platform.target), + msg_info, + )?; } let mut docker_build = docker::command(engine); docker_build.args(&["buildx", "build"]); diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 81918f610..b28d997c8 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -1,7 +1,6 @@ use clap::Args; use eyre::Context; use std::fmt::Write; -use std::io; use crate::util::{get_cargo_workspace, get_matrix}; @@ -21,17 +20,12 @@ pub fn codegen(Codegen { .. }: Codegen) -> cross::Result<()> { pub fn docker_images() -> String { let mut images = String::from( r##"#![doc = "*** AUTO-GENERATED, do not touch. Run `cargo xtask codegen` to update ***"] -use super::{ImageArchitecture, ProvidedImage}; +use super::{ImagePlatform, ProvidedImage}; #[rustfmt::skip] pub static PROVIDED_IMAGES: &[ProvidedImage] = &["##, ); - let mut dir = crate::util::get_cargo_workspace().to_owned(); - dir.push("docker"); - let dir = dir.read_dir().unwrap(); - let mut paths = dir.collect::>>().unwrap(); - paths.sort_by_key(|e| e.path()); for image_target in get_matrix() { write!( &mut images, @@ -47,7 +41,7 @@ pub static PROVIDED_IMAGES: &[ProvidedImage] = &["##, .iter() .map(|p| { format!( - "ImageArchitecture::{}", + "ImagePlatform::{}", p.replace('-', "_").to_ascii_uppercase() ) }) @@ -55,7 +49,7 @@ pub static PROVIDED_IMAGES: &[ProvidedImage] = &["##, .as_slice() .join(", ") } else { - "ImageArchitecture::X86_64_UNKNOWN_LINUX_GNU".to_string() + "ImagePlatform::DEFAULT".to_string() }, if let Some(sub) = &image_target.sub { format!(r#"Some("{}")"#, sub) @@ -70,6 +64,7 @@ pub static PROVIDED_IMAGES: &[ProvidedImage] = &["##, images } +#[cfg(test)] #[test] pub fn ensure_correct_codegen() -> cross::Result<()> { let provided_images = crate::util::get_cargo_workspace().join("src/docker/provided_images.rs"); diff --git a/xtask/src/util.rs b/xtask/src/util.rs index d0c9b2cce..e8954bc64 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -125,11 +125,7 @@ pub struct ImageTarget { impl ImageTarget { pub fn image_name(&self, repository: &str, tag: &str) -> String { - if let Some(sub) = &self.sub { - format!("{repository}/{}:{tag}-{sub}", self.triplet) - } else { - format!("{repository}/{}:{tag}", self.triplet) - } + cross::docker::image_name(&self.triplet, self.sub.as_deref(), repository, tag) } pub fn alt(&self) -> String {