|
| 1 | +use clap::Args; |
| 2 | +use cross::{docker, rustc, shell::MessageInfo}; |
| 3 | +use eyre::Context; |
| 4 | + |
| 5 | +#[derive(Args, Debug)] |
| 6 | +pub struct Install { |
| 7 | + #[clap(long)] |
| 8 | + target: Option<String>, |
| 9 | + /// Provide verbose diagnostic output. |
| 10 | + #[clap(short, long)] |
| 11 | + pub verbose: bool, |
| 12 | + /// Do not print |
| 13 | + #[clap(short, long)] |
| 14 | + pub quiet: bool, |
| 15 | + /// Coloring: auto, always, never |
| 16 | + #[clap(long)] |
| 17 | + pub color: Option<String>, |
| 18 | + /// Container engine (such as docker or podman). |
| 19 | + #[clap(long)] |
| 20 | + pub engine: Option<String>, |
| 21 | + /// Path to crate |
| 22 | + #[clap(long)] |
| 23 | + pub path: Option<String>, |
| 24 | + /// Path to Cross.toml |
| 25 | + #[clap(long)] |
| 26 | + pub config: Option<std::path::PathBuf>, |
| 27 | + #[clap(name = "crate")] |
| 28 | + krate: String, |
| 29 | +} |
| 30 | + |
| 31 | +impl Install { |
| 32 | + pub fn verbose(&self) -> bool { |
| 33 | + self.verbose |
| 34 | + } |
| 35 | + |
| 36 | + pub fn quiet(&self) -> bool { |
| 37 | + self.quiet |
| 38 | + } |
| 39 | + |
| 40 | + pub fn color(&self) -> Option<&str> { |
| 41 | + self.color.as_deref() |
| 42 | + } |
| 43 | + |
| 44 | + pub fn run(self, msg_info: &mut MessageInfo) -> cross::Result<std::process::ExitStatus> { |
| 45 | + let target_list = rustc::target_list(&mut cross::shell::Verbosity::Quiet.into())?; |
| 46 | + |
| 47 | + let host_version_meta = rustc::version_meta()?; |
| 48 | + let mut command = vec!["install".to_owned(), self.krate]; |
| 49 | + |
| 50 | + if let Some(target) = self.target { |
| 51 | + command.push(format!("--target={target}")); |
| 52 | + } |
| 53 | + if let Some(engine) = self.engine { |
| 54 | + std::env::set_var(docker::CROSS_CONTAINER_ENGINE_VAR, engine); |
| 55 | + } |
| 56 | + |
| 57 | + let args = cross::cli::parse(command, &target_list)?; |
| 58 | + let Some(cross::CrossSetup { |
| 59 | + config, |
| 60 | + target, |
| 61 | + uses_xargo, |
| 62 | + uses_zig, |
| 63 | + uses_build_std, |
| 64 | + zig_version, |
| 65 | + toolchain, |
| 66 | + is_remote, |
| 67 | + engine, |
| 68 | + image, |
| 69 | + }) = cross::setup(&host_version_meta, None, &args, target_list, msg_info)? else { |
| 70 | + eyre::bail!("couldn't setup context for cross (see warning)") |
| 71 | + }; |
| 72 | + |
| 73 | + let mut is_nightly = toolchain.channel.contains("nightly"); |
| 74 | + let mut rustc_version = None; |
| 75 | + if let Some((version, channel, _)) = toolchain.rustc_version()? { |
| 76 | + is_nightly = channel == rustc_version::Channel::Nightly; |
| 77 | + rustc_version = Some(version); |
| 78 | + } |
| 79 | + |
| 80 | + let available_targets = cross::rustup::setup_rustup(&toolchain, msg_info)?; |
| 81 | + |
| 82 | + cross::rustup::setup_components( |
| 83 | + &target, |
| 84 | + uses_xargo, |
| 85 | + uses_build_std, |
| 86 | + &toolchain, |
| 87 | + is_nightly, |
| 88 | + available_targets, |
| 89 | + &args, |
| 90 | + msg_info, |
| 91 | + )?; |
| 92 | + |
| 93 | + let filtered_args = cross::get_filtered_args( |
| 94 | + zig_version, |
| 95 | + &args, |
| 96 | + &target, |
| 97 | + &config, |
| 98 | + is_nightly, |
| 99 | + uses_build_std, |
| 100 | + ); |
| 101 | + |
| 102 | + let cwd = std::env::current_dir()?; |
| 103 | + |
| 104 | + let paths = |
| 105 | + docker::DockerPaths::create(&engine, todo!(), cwd, toolchain.clone(), msg_info)?; |
| 106 | + let options = docker::DockerOptions::new( |
| 107 | + engine, |
| 108 | + target.clone(), |
| 109 | + config, |
| 110 | + image, |
| 111 | + cross::CargoVariant::create(uses_zig, uses_xargo)?, |
| 112 | + rustc_version, |
| 113 | + ); |
| 114 | + |
| 115 | + cross::install_interpreter_if_needed( |
| 116 | + &args, |
| 117 | + host_version_meta, |
| 118 | + &target, |
| 119 | + &options, |
| 120 | + msg_info, |
| 121 | + )?; |
| 122 | + |
| 123 | + let status = docker::run(options, paths, &filtered_args, msg_info) |
| 124 | + .wrap_err("could not run container")?; |
| 125 | + let needs_host = args.subcommand.map_or(false, |sc| sc.needs_host(is_remote)); |
| 126 | + if !status.success() { |
| 127 | + cross::warn_on_failure(&target, &toolchain, msg_info)?; |
| 128 | + } |
| 129 | + Ok(status) |
| 130 | + } |
| 131 | +} |
0 commit comments