beet_cli/commands/
cargo_build_cmd.rs

1use anyhow::Result;
2use beet::prelude::*;
3use clap::Parser;
4use std::path::PathBuf;
5use std::process::Command;
6
7/// Verbatim clone of cargo run args
8#[derive(Debug, Clone, Parser)]
9pub struct CargoBuildCmd {
10	/// Package with the target to run
11	#[arg(short = 'p', long = "package")]
12	pub package: Option<String>,
13	/// Name of the bin target to run
14	#[arg(long)]
15	pub bin: Option<String>,
16	/// Name of the example target to run
17	#[arg(long)]
18	pub example: Option<String>,
19	/// Build artifacts in release mode, with optimizations
20	#[arg(long)]
21	pub release: bool,
22	/// Any additional arguments passed to cargo
23	#[arg(long)]
24	pub cargo_args: Option<String>,
25	/// used by watcher to also build for wasm
26	pub target: Option<String>,
27}
28
29impl Default for CargoBuildCmd {
30	fn default() -> Self { Self::parse_from(&[""]) }
31}
32
33
34impl BuildStep for CargoBuildCmd {
35	fn run(&self) -> Result<()> {
36		self.spawn()?;
37		Ok(())
38	}
39}
40
41impl CargoBuildCmd {
42	/// Best effort attempt to retrieve the path to the executable.
43	/// In the case of a wasm target, the path will have a `.wasm` extension.
44	pub fn exe_path(&self) -> PathBuf {
45		let target_dir = std::env::var("CARGO_TARGET_DIR")
46			.unwrap_or_else(|_| "target".to_string());
47		let mut path = PathBuf::from(target_dir);
48
49		if let Some(target) = &self.target {
50			path.push(target);
51		}
52
53		if self.release {
54			path.push("release");
55		} else {
56			path.push("debug");
57		}
58
59		if let Some(example) = &self.example {
60			path.push("examples");
61			path.push(example);
62		// package examples are not nested under package name
63		} else if let Some(pkg) = &self.package {
64			path.push(pkg);
65		}
66		if let Some(bin) = &self.bin {
67			path.push(bin);
68		}
69
70		if let Some("wasm32-unknown-unknown") = self.target.as_deref() {
71			path.set_extension("wasm");
72		}
73
74		path
75	}
76
77	/// Blocking spawn of the cargo build command
78	pub fn spawn(&self) -> Result<()> {
79		let CargoBuildCmd {
80			package,
81			bin,
82			example,
83			release,
84			target,
85			cargo_args,
86		} = self;
87		let mut cmd = Command::new("cargo");
88		cmd.arg("build");
89
90		if let Some(pkg) = package {
91			cmd.arg("--package").arg(pkg);
92		}
93
94		if let Some(bin) = bin {
95			cmd.arg("--bin").arg(bin);
96		}
97
98		if let Some(ex) = example {
99			cmd.arg("--example").arg(ex);
100		}
101
102		if *release {
103			cmd.arg("--release");
104		}
105
106		if let Some(target) = target {
107			cmd.arg("--target").arg(target);
108		}
109
110		if let Some(args) = cargo_args {
111			cmd.args(args.split_whitespace());
112		}
113
114
115		cmd.status()?.exit_ok()?;
116		Ok(())
117	}
118}
119
120//cargo build -p beet_site --message-format=json | jq -r 'select(.reason == "compiler-artifact" and .target.kind == ["bin"]) | .filenames[]'