cargo_mobile2/util/
cargo.rs1use std::{collections::HashMap, ffi::OsString, path::PathBuf};
2
3use crate::{env::ExplicitEnv, DuctExpressionExt};
4
5#[derive(Debug)]
6pub struct CargoCommand<'a> {
7 subcommand: &'a str,
8 verbose: bool,
9 package: Option<&'a str>,
10 manifest_path: Option<PathBuf>,
11 target: Option<&'a str>,
12 no_default_features: bool,
13 features: Option<&'a [String]>,
14 args: Option<&'a [String]>,
15 release: bool,
16}
17
18impl<'a> CargoCommand<'a> {
19 pub fn new(subcommand: &'a str) -> Self {
20 Self {
21 subcommand,
22 verbose: Default::default(),
23 package: Default::default(),
24 manifest_path: Default::default(),
25 target: Default::default(),
26 no_default_features: Default::default(),
27 features: Default::default(),
28 args: Default::default(),
29 release: Default::default(),
30 }
31 }
32
33 pub fn with_verbose(mut self, verbose: bool) -> Self {
34 self.verbose = verbose;
35 self
36 }
37
38 pub fn with_package(mut self, package: Option<&'a str>) -> Self {
39 self.package = package;
40 self
41 }
42
43 pub fn with_manifest_path(mut self, manifest_path: Option<PathBuf>) -> Self {
44 self.manifest_path = manifest_path.map(|manifest_path| {
45 dunce::canonicalize(manifest_path).expect("Failed to canonicalize manifest path")
46 });
47 self
48 }
49
50 pub fn with_target(mut self, target: Option<&'a str>) -> Self {
51 self.target = target;
52 self
53 }
54
55 pub fn with_no_default_features(mut self, no_default_features: bool) -> Self {
56 self.no_default_features = no_default_features;
57 self
58 }
59
60 pub fn with_features(mut self, features: Option<&'a [String]>) -> Self {
61 self.features = features;
62 self
63 }
64
65 pub fn with_args(mut self, args: Option<&'a [String]>) -> Self {
66 self.args = args;
67 self
68 }
69
70 pub fn with_release(mut self, release: bool) -> Self {
71 self.release = release;
72 self
73 }
74
75 pub fn build(self, env: &impl ExplicitEnv) -> duct::Expression {
76 let mut args = vec![self.subcommand.to_owned()];
77 if self.verbose {
78 args.push("-vv".into());
79 }
80 if let Some(package) = self.package {
81 args.extend_from_slice(&["--package".into(), package.to_owned()]);
82 }
83 if let Some(manifest_path) = self.manifest_path {
84 if !manifest_path.exists() {
85 log::error!("manifest path {:?} doesn't exist!", manifest_path);
86 }
87 args.extend_from_slice(&[
88 "--manifest-path".into(),
89 manifest_path.to_string_lossy().to_string(),
90 ]);
91 }
92 if let Some(target) = self.target {
93 args.extend_from_slice(&["--target".into(), target.to_owned()]);
102 }
103 if self.no_default_features {
104 args.push("--no-default-features".into());
105 }
106 if let Some(features) = self.features {
107 let features = features.join(" ");
108 args.extend_from_slice(&["--features".into(), features.as_str().to_string()]);
109 }
110 if let Some(a) = self.args {
111 args.extend_from_slice(a);
112 }
113 if self.release {
114 args.push("--release".into());
115 }
116
117 duct::cmd("cargo", args)
118 .vars(env.explicit_env())
119 .vars(explicit_cargo_env())
120 .dup_stdio()
121 }
122}
123
124fn explicit_cargo_env() -> HashMap<String, OsString> {
125 let mut vars = HashMap::new();
126 if let Some(target_dir) = std::env::var_os("CARGO_TARGET_DIR") {
127 vars.insert("CARGO_TARGET_DIR".into(), target_dir);
128 }
129 if let Some(target_dir) = std::env::var_os("CARGO_BUILD_TARGET_DIR") {
130 vars.insert("CARGO_BUILD_TARGET_DIR".into(), target_dir);
131 }
132 vars
133}