arm_toolchain/cli/
run.rs

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/// Configuration for [`run`].
12#[derive(Debug, clap::Args)]
13pub struct RunArgs {
14    /// Toolchain version override (default: the active version)
15    #[arg(short = 'T', long)]
16    toolchain: Option<ToolchainVersion>,
17    /// Do not set extra environment variables to enable cross-compilation.
18    #[arg(long)]
19    no_cross_env: bool,
20    /// The command to run with the modified environment.
21    command: OsString,
22    /// Arguments to pass to the command.
23    #[arg(
24        trailing_var_arg = true,
25        allow_hyphen_values = true,
26        value_name = "ARGS"
27    )]
28    args: Vec<OsString>,
29}
30
31/// Run a CLI tool with the toolchain in the PATH.
32pub 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}