blob: 0bb293d9d4fcfea802bb6285206ed7383c3984e8 [file] [log] [blame]
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Config, Human};
use cargo::util::important_paths::{find_root_manifest_for_wd};
#[derive(RustcDecodable)]
pub struct Options {
flag_bin: Option<String>,
flag_example: Option<String>,
flag_jobs: Option<u32>,
flag_features: Vec<String>,
flag_all_features: bool,
flag_no_default_features: bool,
flag_target: Option<String>,
flag_manifest_path: Option<String>,
flag_verbose: u32,
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_release: bool,
flag_frozen: bool,
flag_locked: bool,
arg_args: Vec<String>,
}
pub const USAGE: &'static str = "
Run the main binary of the local package (src/main.rs)
Usage:
cargo run [options] [--] [<args>...]
Options:
-h, --help Print this message
--bin NAME Name of the bin target to run
--example NAME Name of the example target to run
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
--release Build artifacts in release mode, with optimizations
--features FEATURES Space-separated list of features to also build
--all-features Build all available features
--no-default-features Do not build the `default` feature
--target TRIPLE Build for the target triple
--manifest-path PATH Path to the manifest to execute
-v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
If neither `--bin` nor `--example` are given, then if the project only has one
bin target it will be run. Otherwise `--bin` specifies the bin target to run,
and `--example` specifies the example target to run. At most one of `--bin` or
`--example` can be provided.
All of the trailing arguments are passed to the binary to run. If you're passing
arguments to both Cargo and the binary, the ones after `--` go to the binary,
the ones before go to Cargo.
";
pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
config.configure(options.flag_verbose,
options.flag_quiet,
&options.flag_color,
options.flag_frozen,
options.flag_locked)?;
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
let (mut examples, mut bins) = (Vec::new(), Vec::new());
if let Some(s) = options.flag_bin {
bins.push(s);
}
if let Some(s) = options.flag_example {
examples.push(s);
}
let compile_opts = ops::CompileOptions {
config: config,
jobs: options.flag_jobs,
target: options.flag_target.as_ref().map(|t| &t[..]),
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: Packages::Packages(&[]),
release: options.flag_release,
mode: ops::CompileMode::Build,
filter: if examples.is_empty() && bins.is_empty() {
ops::CompileFilter::Everything
} else {
ops::CompileFilter::Only {
lib: false, tests: &[], benches: &[],
bins: &bins, examples: &examples,
}
},
message_format: options.flag_message_format,
target_rustdoc_args: None,
target_rustc_args: None,
};
let ws = Workspace::new(&root, config)?;
match ops::run(&ws, &compile_opts, &options.arg_args)? {
None => Ok(None),
Some(err) => {
// If we never actually spawned the process then that sounds pretty
// bad and we always want to forward that up.
let exit = match err.exit.clone() {
Some(exit) => exit,
None => return Err(CliError::new(Box::new(Human(err)), 101)),
};
// If `-q` was passed then we suppress extra error information about
// a failed process, we assume the process itself printed out enough
// information about why it failed so we don't do so as well
let exit_code = exit.code().unwrap_or(101);
Err(if options.flag_quiet == Some(true) {
CliError::code(exit_code)
} else {
CliError::new(Box::new(Human(err)), exit_code)
})
}
}
}