Skip to main content

cargo_elfpak/
lib.rs

1//! Cargo project adapter for `elfpak`.
2
3mod build;
4mod cli;
5mod metadata;
6
7use crate::{
8    build::BuildRequest,
9    cli::{CargoCommand, Cli, Command},
10    metadata::SelectionContext,
11};
12use anyhow::Result;
13use clap::Parser;
14use std::{ffi::OsString, path::PathBuf};
15
16/// Run the Cargo subcommand and return a process exit code.
17pub fn run() -> std::process::ExitCode {
18    let mut args: Vec<OsString> = std::env::args_os().collect();
19    if args.get(1).is_none_or(|argument| argument != "elfpak") {
20        args.insert(1, OsString::from("elfpak"));
21    }
22    let cli = match Cli::try_parse_from(args) {
23        Ok(cli) => cli,
24        Err(error) => error.exit(),
25    };
26
27    match try_run(cli) {
28        Ok(status) => status,
29        Err(error) => {
30            eprintln!("error:\n  {error:#}");
31            std::process::ExitCode::FAILURE
32        }
33    }
34}
35
36fn try_run(cli: Cli) -> Result<std::process::ExitCode> {
37    let CargoCommand::Elfpak(elfpak) = cli.command;
38    let Command::Bundle(args) = elfpak.command;
39    let current_dir = std::env::current_dir()?;
40    let metadata = metadata::load(
41        &current_dir,
42        args.manifest_path.as_deref(),
43        args.locked,
44        args.offline,
45        args.frozen,
46    )?;
47    let selections = metadata::select_many(
48        &metadata,
49        &SelectionContext {
50            package: args.package,
51            binary: args.bin,
52            binaries: args.bins,
53            all_bins: args.all_bins,
54            all: args.all,
55            manifest_path: args.manifest_path.clone(),
56            current_dir: PathBuf::from(&current_dir),
57        },
58    )?;
59    let artifacts = build::run(&BuildRequest {
60        selections: &selections,
61        current_dir: &current_dir,
62        manifest_path: args.manifest_path.as_deref(),
63        release: args.release,
64        profile: args.profile.as_deref(),
65        target: args.target.as_deref(),
66        target_dir: args.target_dir.as_deref(),
67        features: &args.features,
68        all_features: args.all_features,
69        no_default_features: args.no_default_features,
70        locked: args.locked,
71        offline: args.offline,
72        frozen: args.frozen,
73        quiet: cli.quiet,
74    })?;
75
76    if !cli.quiet {
77        for artifact in &artifacts {
78            let state = if artifact.fresh { "fresh" } else { "built" };
79            println!("{state} Cargo binary: {}", artifact.executable.display());
80        }
81    }
82    Ok(elfpak::run_bundle_many(
83        args.bundle,
84        artifacts
85            .into_iter()
86            .map(|artifact| artifact.executable)
87            .collect(),
88        cli.quiet,
89        cli.verbose,
90    ))
91}