1use std::{env, ffi::OsString, process::exit};
2
3use futures::never::Never;
4use tokio::process::Command;
5
6use crate::{
7 cli::CliError,
8 toolchain::{ToolchainClient, ToolchainVersion},
9};
10
11#[derive(Debug, clap::Args)]
13pub struct RunArgs {
14 #[arg(short = 'T', long)]
16 toolchain: Option<ToolchainVersion>,
17 #[arg(long)]
19 no_cross_env: bool,
20 command: OsString,
22 #[arg(
24 trailing_var_arg = true,
25 allow_hyphen_values = true,
26 value_name = "ARGS"
27 )]
28 args: Vec<OsString>,
29}
30
31pub async fn run(args: RunArgs) -> Result<Never, CliError> {
33 let client = ToolchainClient::using_data_dir().await?;
34 let version = args
35 .toolchain
36 .or_else(|| client.active_toolchain())
37 .ok_or(CliError::NoToolchainEnabled)?;
38
39 let toolchain = client.toolchain(&version).await?;
40
41 let mut path = OsString::from(toolchain.host_bin_dir());
42 if let Some(old_path) = env::var_os("PATH") {
43 path.push(":");
44 path.push(old_path);
45 }
46
47 let mut cmd = Command::new(args.command);
48 cmd.args(args.args);
49 cmd.env("PATH", path);
50
51 if !args.no_cross_env {
52 cmd.env("TARGET_CC", "clang");
53 cmd.env("TARGET_AR", "llvm-ar");
54 }
55
56 let code = cmd.status().await?.code();
57 exit(code.unwrap_or(1));
58}