Skip to content

Commit b44de01

Browse files
committed
Make image struct and rename Host -> TargetTriple
1 parent 48d2b7b commit b44de01

17 files changed

+936
-251
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
### Added
1313

14-
- #803 - added `CROSS_CUSTOM_TOOLCHAIN` to disable automatic installation of components for use with tools like `cargo-bisect-rustc`
14+
- #817 - Toolchain images can now be specified as for a certain toolchain via `target.{target}.image.toolchain`
15+
- #803, #817 - added `CROSS_CUSTOM_TOOLCHAIN` to disable automatic installation of components for use with tools like `cargo-bisect-rustc`
1516
- #795 - added images for additional toolchains maintained by cross-rs.
1617
- #792 - added `CROSS_CONTAINER_IN_CONTAINER` environment variable to replace `CROSS_DOCKER_IN_DOCKER`.
1718
- #785 - added support for remote container engines through data volumes through setting the `CROSS_REMOTE` environment variable. also adds in utility commands to create and remove persistent data volumes.
@@ -54,6 +55,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5455
### Fixed
5556

5657
- #836 - write a `CACHEDIR.TAG` when creating the target directory, similar to `cargo`.
58+
- #817 - made `cross +channel` parsing more compliant to parsing a toolchain
5759
- #804 - allow usage of env `CARGO_BUILD_TARGET` as an alias for `CROSS_BUILD_TARGET`
5860
- #792 - fixed container-in-container support when using podman.
5961
- #781 - ensure `target.$(...)` config options override `build` ones.

src/bin/commands/containers.rs

+31-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use atty::Stream;
22
use clap::{Args, Subcommand};
3-
use cross::{docker, CommandExt};
3+
use cross::{
4+
docker::{self, ImageArchitecture},
5+
rustc::{QualifiedToolchain, Toolchain},
6+
CommandExt,
7+
};
48

59
#[derive(Args, Debug)]
610
pub struct ListVolumes {
@@ -76,7 +80,7 @@ pub struct CreateVolume {
7680
}
7781

7882
impl CreateVolume {
79-
pub fn run(self, engine: docker::Engine, channel: Option<&str>) -> cross::Result<()> {
83+
pub fn run(self, engine: docker::Engine, channel: Option<&Toolchain>) -> cross::Result<()> {
8084
create_persistent_volume(self, &engine, channel)
8185
}
8286
}
@@ -98,7 +102,7 @@ pub struct RemoveVolume {
98102
}
99103

100104
impl RemoveVolume {
101-
pub fn run(self, engine: docker::Engine, channel: Option<&str>) -> cross::Result<()> {
105+
pub fn run(self, engine: docker::Engine, channel: Option<&Toolchain>) -> cross::Result<()> {
102106
remove_persistent_volume(self, &engine, channel)
103107
}
104108
}
@@ -118,7 +122,7 @@ pub enum Volumes {
118122
}
119123

120124
impl Volumes {
121-
pub fn run(self, engine: docker::Engine, toolchain: Option<&str>) -> cross::Result<()> {
125+
pub fn run(self, engine: docker::Engine, toolchain: Option<&Toolchain>) -> cross::Result<()> {
122126
match self {
123127
Volumes::List(args) => args.run(engine),
124128
Volumes::RemoveAll(args) => args.run(engine),
@@ -296,12 +300,18 @@ pub fn create_persistent_volume(
296300
..
297301
}: CreateVolume,
298302
engine: &docker::Engine,
299-
channel: Option<&str>,
303+
channel: Option<&Toolchain>,
300304
) -> cross::Result<()> {
301305
// we only need a triple that needs docker: the actual target doesn't matter.
302-
let triple = cross::Host::X86_64UnknownLinuxGnu.triple();
303-
let (target, metadata, dirs) =
304-
docker::get_package_info(engine, triple, channel, docker_in_docker, verbose)?;
306+
let target = cross::Target::BuiltIn {
307+
triple: cross::TargetTriple::X86_64UnknownLinuxGnu,
308+
};
309+
let mut toolchain = QualifiedToolchain::default(verbose)?;
310+
toolchain.replace_host(&ImageArchitecture::from_target(target.target().clone()));
311+
if let Some(channel) = channel {
312+
toolchain = toolchain.with_picked(channel.clone(), verbose)?;
313+
};
314+
let (metadata, dirs) = docker::get_package_info(engine, &toolchain, docker_in_docker, verbose)?;
305315
let container = docker::remote::unique_container_identifier(&target, &metadata, &dirs)?;
306316
let volume = docker::remote::unique_toolchain_identifier(&dirs.sysroot)?;
307317

@@ -358,7 +368,7 @@ pub fn create_persistent_volume(
358368
engine,
359369
&container,
360370
&dirs.sysroot,
361-
&target,
371+
target.target(),
362372
mount_prefix.as_ref(),
363373
true,
364374
verbose,
@@ -372,16 +382,24 @@ pub fn create_persistent_volume(
372382

373383
pub fn remove_persistent_volume(
374384
RemoveVolume {
375-
target,
385+
target: _,
376386
docker_in_docker,
377387
verbose,
378388
..
379389
}: RemoveVolume,
380390
engine: &docker::Engine,
381-
channel: Option<&str>,
391+
channel: Option<&Toolchain>,
382392
) -> cross::Result<()> {
383-
let (_, _, dirs) =
384-
docker::get_package_info(engine, &target, channel, docker_in_docker, verbose)?;
393+
// we only need a triple that needs docker: the actual target doesn't matter.
394+
let target = cross::Target::BuiltIn {
395+
triple: cross::TargetTriple::X86_64UnknownLinuxGnu,
396+
};
397+
let mut toolchain = QualifiedToolchain::default(verbose)?;
398+
toolchain.replace_host(&ImageArchitecture::from_target(target.target().clone()));
399+
if let Some(channel) = channel {
400+
toolchain = toolchain.with_picked(channel.clone(), verbose)?;
401+
};
402+
let (_, dirs) = docker::get_package_info(engine, &toolchain, docker_in_docker, verbose)?;
385403
let volume = docker::remote::unique_toolchain_identifier(&dirs.sysroot)?;
386404

387405
if !docker::remote::volume_exists(engine, &volume, verbose)? {

src/bin/cross-util.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![deny(missing_debug_implementations, rust_2018_idioms)]
22

33
use clap::{CommandFactory, Parser, Subcommand};
4-
use cross::docker;
4+
use cross::{docker, rustc::Toolchain};
55

66
mod commands;
77

@@ -10,7 +10,7 @@ mod commands;
1010
struct Cli {
1111
/// Toolchain name/version to use (such as stable or 1.59.0).
1212
#[clap(value_parser = is_toolchain)]
13-
toolchain: Option<String>,
13+
toolchain: Option<Toolchain>,
1414
#[clap(subcommand)]
1515
command: Commands,
1616
}
@@ -65,7 +65,7 @@ pub fn main() -> cross::Result<()> {
6565
}
6666
Commands::Volumes(args) => {
6767
let engine = get_container_engine(args.engine(), args.verbose())?;
68-
args.run(engine, cli.toolchain.as_deref())?;
68+
args.run(engine, cli.toolchain.as_ref())?;
6969
}
7070
Commands::Containers(args) => {
7171
let engine = get_container_engine(args.engine(), args.verbose())?;

src/bin/cross.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,47 @@
11
#![deny(missing_debug_implementations, rust_2018_idioms)]
22

3+
use std::{
4+
env,
5+
io::{self, Write},
6+
};
7+
8+
use cross::{cargo, cli, rustc, OutputExt, Subcommand};
9+
310
pub fn main() -> cross::Result<()> {
411
cross::install_panic_hook()?;
512
cross::install_termination_hook()?;
613

7-
let status = cross::run()?;
14+
let target_list = rustc::target_list(false)?;
15+
let args = cli::parse(&target_list)?;
16+
let subcommand = args.subcommand;
17+
let verbose = args
18+
.all
19+
.iter()
20+
.any(|a| a == "--verbose" || a == "-v" || a == "-vv");
21+
let status = match cross::run(args, target_list, verbose)? {
22+
Some(status) => status,
23+
None => {
24+
// if we fallback to the host cargo, use the same invocation that was made to cross
25+
let argv: Vec<String> = env::args().skip(1).collect();
26+
eprintln!("Warning: Falling back to `cargo` on the host.");
27+
match subcommand {
28+
Some(Subcommand::List) => {
29+
// this won't print in order if we have both stdout and stderr.
30+
let out = cargo::run_and_get_output(&argv, verbose)?;
31+
let stdout = out.stdout()?;
32+
if out.status.success() && cli::is_subcommand_list(&stdout) {
33+
cli::fmt_subcommands(&stdout);
34+
} else {
35+
// Not a list subcommand, which can happen with weird edge-cases.
36+
print!("{}", stdout);
37+
io::stdout().flush().unwrap();
38+
}
39+
out.status
40+
}
41+
_ => cargo::run(&argv, verbose)?,
42+
}
43+
}
44+
};
845
let code = status
946
.code()
1047
.ok_or_else(|| eyre::Report::msg("Cargo process terminated by signal"))?;

src/config.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::docker::{ImageArchitecture, PossibleImage};
12
use crate::{CrossToml, Result, Target, TargetList};
23

34
use std::collections::HashMap;
@@ -64,8 +65,18 @@ impl Environment {
6465
self.get_values_for("BUILD_STD", target, bool_from_envvar)
6566
}
6667

67-
fn image(&self, target: &Target) -> Option<String> {
68+
fn image(&self, target: &Target) -> Result<Option<PossibleImage>> {
6869
self.get_target_var(target, "IMAGE")
70+
.map(|i| i.parse().expect("infallible"))
71+
.map(|mut i: PossibleImage| {
72+
if let Some(toolchain) = self.get_target_var(target, "IMAGE_TOOLCHAIN") {
73+
i.toolchain = Some(ImageArchitecture::from_target(toolchain.into()));
74+
Ok(i)
75+
} else {
76+
Ok(i)
77+
}
78+
})
79+
.transpose()
6980
}
7081

7182
fn dockerfile(&self, target: &Target) -> Option<String> {
@@ -178,12 +189,12 @@ impl Config {
178189
None
179190
}
180191

181-
fn string_from_config(
192+
fn get_config<'a, T: 'a>(
182193
&self,
183194
target: &Target,
184-
env: impl Fn(&Environment, &Target) -> Option<String>,
185-
config: impl Fn(&CrossToml, &Target) -> Option<String>,
186-
) -> Result<Option<String>> {
195+
env: impl Fn(&Environment, &Target) -> Option<T>,
196+
config: impl Fn(&CrossToml, &Target) -> Option<T>,
197+
) -> Result<Option<T>> {
187198
let env_value = env(&self.env, target);
188199
if let Some(env_value) = env_value {
189200
return Ok(Some(env_value));
@@ -239,12 +250,13 @@ impl Config {
239250
self.bool_from_config(target, Environment::build_std, CrossToml::build_std)
240251
}
241252

242-
pub fn image(&self, target: &Target) -> Result<Option<String>> {
243-
self.string_from_config(target, Environment::image, CrossToml::image)
253+
pub fn image(&self, target: &Target) -> Result<Option<PossibleImage>> {
254+
let env = self.env.image(target)?;
255+
self.get_config(target, move |_, _| env.clone(), CrossToml::image)
244256
}
245257

246258
pub fn runner(&self, target: &Target) -> Result<Option<String>> {
247-
self.string_from_config(target, Environment::runner, CrossToml::runner)
259+
self.get_config(target, Environment::runner, CrossToml::runner)
248260
}
249261

250262
pub fn env_passthrough(&self, target: &Target) -> Result<Option<Vec<String>>> {
@@ -270,11 +282,11 @@ impl Config {
270282
}
271283

272284
pub fn dockerfile(&self, target: &Target) -> Result<Option<String>> {
273-
self.string_from_config(target, Environment::dockerfile, CrossToml::dockerfile)
285+
self.get_config(target, Environment::dockerfile, CrossToml::dockerfile)
274286
}
275287

276288
pub fn dockerfile_context(&self, target: &Target) -> Result<Option<String>> {
277-
self.string_from_config(
289+
self.get_config(
278290
target,
279291
Environment::dockerfile_context,
280292
CrossToml::dockerfile_context,

src/cross_toml.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![doc = include_str!("../docs/cross_toml.md")]
22

3+
use crate::docker::PossibleImage;
34
use crate::{config, errors::*};
45
use crate::{Target, TargetList};
56
use serde::de::DeserializeOwned;
@@ -34,7 +35,8 @@ pub struct CrossBuildConfig {
3435
pub struct CrossTargetConfig {
3536
xargo: Option<bool>,
3637
build_std: Option<bool>,
37-
image: Option<String>,
38+
#[serde(default, deserialize_with = "opt_string_or_struct")]
39+
image: Option<PossibleImage>,
3840
#[serde(default, deserialize_with = "opt_string_or_struct")]
3941
dockerfile: Option<CrossTargetDockerfileConfig>,
4042
pre_build: Option<Vec<String>>,
@@ -195,7 +197,7 @@ impl CrossToml {
195197
}
196198

197199
/// Returns the `target.{}.image` part of `Cross.toml`
198-
pub fn image(&self, target: &Target) -> Option<String> {
200+
pub fn image(&self, target: &Target) -> Option<PossibleImage> {
199201
self.get_string(target, |_| None, |t| t.image.as_ref())
200202
}
201203

@@ -284,12 +286,12 @@ impl CrossToml {
284286
self.targets.get(target)
285287
}
286288

287-
fn get_string<'a>(
289+
fn get_string<'a, T: Clone + 'a>(
288290
&'a self,
289291
target: &Target,
290-
get_build: impl Fn(&'a CrossBuildConfig) -> Option<&'a String>,
291-
get_target: impl Fn(&'a CrossTargetConfig) -> Option<&'a String>,
292-
) -> Option<String> {
292+
get_build: impl Fn(&'a CrossBuildConfig) -> Option<&'a T>,
293+
get_target: impl Fn(&'a CrossTargetConfig) -> Option<&'a T>,
294+
) -> Option<T> {
293295
self.get_target(target)
294296
.and_then(get_target)
295297
.or_else(|| get_build(&self.build))
@@ -380,6 +382,8 @@ where
380382

381383
#[cfg(test)]
382384
mod tests {
385+
use crate::docker::ImageArchitecture;
386+
383387
use super::*;
384388

385389
#[test]
@@ -435,7 +439,7 @@ mod tests {
435439
let mut target_map = HashMap::new();
436440
target_map.insert(
437441
Target::BuiltIn {
438-
triple: "aarch64-unknown-linux-gnu".to_string(),
442+
triple: "aarch64-unknown-linux-gnu".into(),
439443
},
440444
CrossTargetConfig {
441445
env: CrossEnvConfig {
@@ -444,7 +448,7 @@ mod tests {
444448
},
445449
xargo: Some(false),
446450
build_std: Some(true),
447-
image: Some("test-image".to_string()),
451+
image: Some("test-image".parse().expect("infallible")),
448452
runner: None,
449453
dockerfile: None,
450454
pre_build: Some(vec![]),
@@ -479,12 +483,17 @@ mod tests {
479483
let mut target_map = HashMap::new();
480484
target_map.insert(
481485
Target::BuiltIn {
482-
triple: "aarch64-unknown-linux-gnu".to_string(),
486+
triple: "aarch64-unknown-linux-gnu".into(),
483487
},
484488
CrossTargetConfig {
485489
xargo: Some(false),
486490
build_std: None,
487-
image: None,
491+
image: Some(PossibleImage {
492+
name: "test-image".to_string(),
493+
toolchain: Some(ImageArchitecture::from_target(
494+
"aarch64-unknown-linux-musl".into(),
495+
)),
496+
}),
488497
dockerfile: Some(CrossTargetDockerfileConfig {
489498
file: "Dockerfile.test".to_string(),
490499
context: None,
@@ -526,6 +535,8 @@ mod tests {
526535
xargo = false
527536
dockerfile = "Dockerfile.test"
528537
pre-build = ["echo 'Hello'"]
538+
image.name = "test-image"
539+
image.toolchain = "aarch64-unknown-linux-musl"
529540
530541
[target.aarch64-unknown-linux-gnu.env]
531542
volumes = ["VOL"]

0 commit comments

Comments
 (0)