Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc subcommand #1568

Merged
merged 12 commits into from
May 7, 2015
1 change: 1 addition & 0 deletions src/bin/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
&options.flag_test,
&options.flag_example,
&options.flag_bench),
target_rustc_args: None,
},
};

Expand Down
1 change: 1 addition & 0 deletions src/bin/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
&options.flag_test,
&options.flag_example,
&options.flag_bench),
target_rustc_args: None,
};

ops::compile(&root, &opts).map(|_| None).map_err(|err| {
Expand Down
1 change: 1 addition & 0 deletions src/bin/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ macro_rules! each_subcommand{ ($mac:ident) => ({
$mac!(publish);
$mac!(read_manifest);
$mac!(run);
$mac!(rustc);
$mac!(search);
$mac!(test);
$mac!(update);
Expand Down
1 change: 1 addition & 0 deletions src/bin/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
mode: ops::CompileMode::Doc {
deps: !options.flag_no_deps,
},
target_rustc_args: None,
},
};

Expand Down
1 change: 1 addition & 0 deletions src/bin/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
bins: &bins, examples: &examples,
}
},
target_rustc_args: None,
};

let err = try!(ops::run(&root,
Expand Down
94 changes: 94 additions & 0 deletions src/bin/rustc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::env;

use cargo::ops::CompileOptions;
use cargo::ops;
use cargo::util::important_paths::{find_root_manifest_for_cwd};
use cargo::util::{CliResult, CliError, Config};

#[derive(RustcDecodable)]
struct Options {
arg_opts: Option<Vec<String>>,
flag_package: Option<String>,
flag_jobs: Option<u32>,
flag_features: Vec<String>,
flag_no_default_features: bool,
flag_target: Option<String>,
flag_manifest_path: Option<String>,
flag_verbose: bool,
flag_release: bool,
flag_lib: bool,
flag_bin: Vec<String>,
flag_example: Vec<String>,
flag_test: Vec<String>,
flag_bench: Vec<String>,
}

pub const USAGE: &'static str = "
Compile a package and all of its dependencies

Usage:
cargo rustc [options] [--] [<opts>...]

Options:
-h, --help Print this message
-p SPEC, --package SPEC The profile to compile for
-j N, --jobs N The number of jobs to run in parallel
--lib Build only this package's library
--bin NAME Build only the specified binary
--example NAME Build only the specified example
--test NAME Build only the specified test
--bench NAME Build only the specified benchmark
--release Build artifacts in release mode, with optimizations
--features FEATURES Features to compile for the package
--no-default-features Do not compile default features for the package
--target TRIPLE Target triple which compiles will be for
--manifest-path PATH Path to the manifest to fetch depednencies for
-v, --verbose Use verbose output

The <pkgid> specified (defaults to the current package) will have all of its
dependencies compiled, and then the package itself will be compiled. This
command requires that a lockfile is available and dependencies have been
fetched.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this documentation may want to be touched up a bit, perhaps something along the lines of:

The specified target for the current package (or package specified by SPEC if provided) will be compiled along with all of its dependencies. The specified <opts>... will all be passed to the final compiler invocation, not any of the dependencies. Note that the compiler will still unconditionally receive arguments such as -L, --extern, and --crate-type, and the specified <opts>... will simply be added to the compiler invocation.

This command requires that only one target is being compiled. If more than one target is available for the current package the filters of --lib, --bin, etc, must be used to select which target is compiled.


All of the trailing arguments are passed through to the *final* rustc
invocation, not any of the dependencies.

Dependencies will not be recompiled if they do not need to be, but the package
specified will always be compiled. The compiler will receive a number of
arguments unconditionally such as --extern, -L, etc. Note that dependencies are
recompiled when the flags they're compiled with change, so it is not allowed to
manually compile a package's dependencies and then compile the package against
the artifacts just generated.
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
debug!("executing; cmd=cargo-rustc; args={:?}",
env::args().collect::<Vec<_>>());
config.shell().set_verbose(options.flag_verbose);

let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));

let opts = CompileOptions {
config: config,
jobs: options.flag_jobs,
target: options.flag_target.as_ref().map(|t| &t[..]),
features: &options.flag_features,
no_default_features: options.flag_no_default_features,
spec: options.flag_package.as_ref().map(|s| &s[..]),
exec_engine: None,
mode: ops::CompileMode::Build,
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,
&options.flag_bin,
&options.flag_test,
&options.flag_example,
&options.flag_bench),
target_rustc_args: options.arg_opts.as_ref().map(|a| &a[..]),
};

ops::compile(&root, &opts).map(|_| None).map_err(|err| {
CliError::from_boxed(err, 101)
})
}


1 change: 1 addition & 0 deletions src/bin/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
&options.flag_test,
&options.flag_example,
&options.flag_bench),
target_rustc_args: None,
},
};

Expand Down
2 changes: 2 additions & 0 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ pub struct Profile {
pub opt_level: u32,
pub lto: bool,
pub codegen_units: Option<u32>, // None = use rustc default
pub rustc_args: Option<Vec<String>>,
pub debuginfo: bool,
pub debug_assertions: bool,
pub rpath: bool,
Expand Down Expand Up @@ -464,6 +465,7 @@ impl Default for Profile {
opt_level: 0,
lto: false,
codegen_units: None,
rustc_args: None,
debuginfo: false,
debug_assertions: false,
rpath: false,
Expand Down
23 changes: 22 additions & 1 deletion src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ pub struct CompileOptions<'a, 'b: 'a> {
pub release: bool,
/// Mode for this compile.
pub mode: CompileMode,
/// The specified target will be compiled with all the available arguments,
/// note that this only accounts for the *final* invocation of rustc
pub target_rustc_args: Option<&'a [String]>,
}

#[derive(Clone, Copy, PartialEq)]
Expand Down Expand Up @@ -102,7 +105,8 @@ pub fn compile_pkg(package: &Package, options: &CompileOptions)
-> CargoResult<ops::Compilation> {
let CompileOptions { config, jobs, target, spec, features,
no_default_features, release, mode,
ref filter, ref exec_engine } = *options;
ref filter, ref exec_engine,
ref target_rustc_args } = *options;

let target = target.map(|s| s.to_string());
let features = features.iter().flat_map(|s| {
Expand Down Expand Up @@ -163,6 +167,23 @@ pub fn compile_pkg(package: &Package, options: &CompileOptions)
let to_build = packages.iter().find(|p| p.package_id() == pkgid).unwrap();
let targets = try!(generate_targets(to_build, mode, filter, release));

let target_with_args = match target_rustc_args {
&Some(args) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typically instead of matching &T we use match *target_rustc_args to dereference sooner. You may also be able to compress this a bit via:

match *target_rustc_args {
    Some(args) if args.len() > 1 => return Err(...),
    Some(args) => { ... }
    // ...
}

if targets.len() > 1 {
return Err(human("extra arguments to `rustc` can only be \
invoked for one target"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree that it would be nice to improve this error message a bit. It would be nice for it to mention the filtering utilities (e.g. --lib and --bin) and then also perhaps provide a suggestion along the lines of "consider passing --lib" (or something like that)

}
let (target, profile) = targets[0];
let mut profile = profile.clone();
profile.rustc_args = Some(args.to_vec());
Some((target, profile))
},
&None => None,
};

let targets = target_with_args.as_ref().map(|&(t, ref p)| vec!((t, p)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typically we use vec![...] instead of vec!(...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, could this as_ref().map() be inlined into the above match? I think the two branches should match up to be the same.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I'm not exactly sure how this would be done since I'm already cloning the Profile inside the match.
Maybe there's a better way of doing this that does not require the extra clone()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right it needs to be rooted somewhere, nevermind!

.unwrap_or(targets);

let ret = {
let _p = profile::start("compiling");
let mut build_config = try!(scrape_build_config(config, jobs, target));
Expand Down
1 change: 1 addition & 0 deletions src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ fn run_verify(config: &Config, pkg: &Package, tar: &Path)
exec_engine: None,
release: false,
mode: ops::CompileMode::Build,
target_rustc_args: None,
}));

Ok(())
Expand Down
8 changes: 6 additions & 2 deletions src/cargo/ops/cargo_rustc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,8 @@ fn build_base_args(cx: &Context,
profile: &Profile,
crate_types: &[&str]) {
let Profile {
opt_level, lto, codegen_units, debuginfo, debug_assertions, rpath, test,
doc: _doc,
opt_level, lto, codegen_units, ref rustc_args, debuginfo, debug_assertions,
rpath, test, doc: _doc,
} = *profile;

// Move to cwd so the root_path() passed below is actually correct
Expand Down Expand Up @@ -664,6 +664,10 @@ fn build_base_args(cx: &Context,
cmd.arg("-g");
}

if let &Some(ref args) = rustc_args {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if let Some(ref args) = *rustc_args { (minor nit)

cmd.args(args);
}

if debug_assertions && opt_level > 0 {
cmd.args(&["-C", "debug-assertions=on"]);
} else if !debug_assertions && opt_level == 0 {
Expand Down
1 change: 1 addition & 0 deletions src/cargo/util/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
opt_level: opt_level.unwrap_or(profile.opt_level),
lto: lto.unwrap_or(profile.lto),
codegen_units: codegen_units,
rustc_args: None,
debuginfo: debug.unwrap_or(profile.debuginfo),
debug_assertions: debug_assertions.unwrap_or(profile.debug_assertions),
rpath: rpath.unwrap_or(profile.rpath),
Expand Down
Loading