cargo_mobile2/util/
cargo.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::{collections::HashMap, ffi::OsString, path::PathBuf};

use crate::{env::ExplicitEnv, DuctExpressionExt};

#[derive(Debug)]
pub struct CargoCommand<'a> {
    subcommand: &'a str,
    verbose: bool,
    package: Option<&'a str>,
    manifest_path: Option<PathBuf>,
    target: Option<&'a str>,
    no_default_features: bool,
    features: Option<&'a [String]>,
    args: Option<&'a [String]>,
    release: bool,
}

impl<'a> CargoCommand<'a> {
    pub fn new(subcommand: &'a str) -> Self {
        Self {
            subcommand,
            verbose: Default::default(),
            package: Default::default(),
            manifest_path: Default::default(),
            target: Default::default(),
            no_default_features: Default::default(),
            features: Default::default(),
            args: Default::default(),
            release: Default::default(),
        }
    }

    pub fn with_verbose(mut self, verbose: bool) -> Self {
        self.verbose = verbose;
        self
    }

    pub fn with_package(mut self, package: Option<&'a str>) -> Self {
        self.package = package;
        self
    }

    pub fn with_manifest_path(mut self, manifest_path: Option<PathBuf>) -> Self {
        self.manifest_path = manifest_path.map(|manifest_path| {
            dunce::canonicalize(manifest_path).expect("Failed to canonicalize manifest path")
        });
        self
    }

    pub fn with_target(mut self, target: Option<&'a str>) -> Self {
        self.target = target;
        self
    }

    pub fn with_no_default_features(mut self, no_default_features: bool) -> Self {
        self.no_default_features = no_default_features;
        self
    }

    pub fn with_features(mut self, features: Option<&'a [String]>) -> Self {
        self.features = features;
        self
    }

    pub fn with_args(mut self, args: Option<&'a [String]>) -> Self {
        self.args = args;
        self
    }

    pub fn with_release(mut self, release: bool) -> Self {
        self.release = release;
        self
    }

    pub fn build(self, env: &impl ExplicitEnv) -> duct::Expression {
        let mut args = vec![self.subcommand.to_owned()];
        if self.verbose {
            args.push("-vv".into());
        }
        if let Some(package) = self.package {
            args.extend_from_slice(&["--package".into(), package.to_owned()]);
        }
        if let Some(manifest_path) = self.manifest_path {
            if !manifest_path.exists() {
                log::error!("manifest path {:?} doesn't exist!", manifest_path);
            }
            args.extend_from_slice(&[
                "--manifest-path".into(),
                manifest_path.to_string_lossy().to_string(),
            ]);
        }
        if let Some(target) = self.target {
            // We used to use `util::host_target_triple` to avoid explicitly
            // specifying the default target triple here, since specifying it
            // results in a different `target` subdir being used... however,
            // for reasons noted in `crate::init::exec`, we now favor explicitly
            // specifying `--target` when possible. Though, due to the
            // solution described in the aforementioned function, omitting the
            // default target here wouldn't actually have any negative effect,
            // but it wouldn't accomplish anything either.
            args.extend_from_slice(&["--target".into(), target.to_owned()]);
        }
        if self.no_default_features {
            args.push("--no-default-features".into());
        }
        if let Some(features) = self.features {
            let features = features.join(" ");
            args.extend_from_slice(&["--features".into(), features.as_str().to_string()]);
        }
        if let Some(a) = self.args {
            args.extend_from_slice(a);
        }
        if self.release {
            args.push("--release".into());
        }

        duct::cmd("cargo", args)
            .vars(env.explicit_env())
            .vars(explicit_cargo_env())
            .dup_stdio()
    }
}

fn explicit_cargo_env() -> HashMap<String, OsString> {
    let mut vars = HashMap::new();
    if let Some(target_dir) = std::env::var_os("CARGO_TARGET_DIR") {
        vars.insert("CARGO_TARGET_DIR".into(), target_dir);
    }
    if let Some(target_dir) = std::env::var_os("CARGO_BUILD_TARGET_DIR") {
        vars.insert("CARGO_BUILD_TARGET_DIR".into(), target_dir);
    }
    vars
}