Skip to content

Commit

Permalink
cargo check
Browse files Browse the repository at this point in the history
Adds a new mode - check - which only checks code, rather than generating machine code. It takes into account that proc macros and build scripts will still require generated code.

Implemented by adding a check profile and setting this on each Unit, unless the unit is required to be built (i.e., is a proc macro, build script, or dep of one).
  • Loading branch information
nrc committed Dec 9, 2016
1 parent fec03d3 commit 4b82fdc
Show file tree
Hide file tree
Showing 12 changed files with 348 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/bin/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Options:
Some common cargo commands are (see all commands with --list):
build Compile the current project
check Analyze the current project and report errors, but don't build object files
clean Remove the target directory
doc Build this project's and its dependencies' documentation
new Create a new cargo project
Expand All @@ -75,6 +76,7 @@ macro_rules! each_subcommand{
($mac:ident) => {
$mac!(bench);
$mac!(build);
$mac!(check);
$mac!(clean);
$mac!(doc);
$mac!(fetch);
Expand Down
103 changes: 103 additions & 0 deletions src/bin/check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::env;

use cargo::core::Workspace;
use cargo::ops::{self, CompileOptions, MessageFormat};
use cargo::util::important_paths::{find_root_manifest_for_wd};
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
pub struct Options {
flag_package: Vec<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_lib: bool,
flag_bin: Vec<String>,
flag_example: Vec<String>,
flag_test: Vec<String>,
flag_bench: Vec<String>,
flag_locked: bool,
flag_frozen: bool,
}

pub const USAGE: &'static str = "
Check a local package and all of its dependencies for errors
Usage:
cargo check [options]
Options:
-h, --help Print this message
-p SPEC, --package SPEC ... Package to check
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
--lib Check only this package's library
--bin NAME Check only the specified binary
--example NAME Check only the specified example
--test NAME Check only the specified test target
--bench NAME Check only the specified benchmark target
--release Check artifacts in release mode, with optimizations
--features FEATURES Space-separated list of features to also check
--all-features Check all available features
--no-default-features Do not check the `default` feature
--target TRIPLE Check for the target triple
--manifest-path PATH Path to the manifest to compile
-v, --verbose ... Use verbose 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 the --package argument is given, then SPEC is a package id specification
which indicates which package should be built. If it is not given, then the
current package is built. For more information on SPEC and its format, see the
`cargo help pkgid` command.
Compilation can be configured via the use of profiles which are configured in
the manifest. The default profile for this command is `dev`, but passing
the --release flag will use the `release` profile instead.
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
debug!("executing; cmd=cargo-check; args={:?}",
env::args().collect::<Vec<_>>());
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 opts = 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: &options.flag_package,
mode: ops::CompileMode::Check,
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,
&options.flag_bin,
&options.flag_test,
&options.flag_example,
&options.flag_bench),
message_format: options.flag_message_format,
target_rustdoc_args: None,
target_rustc_args: None,
};

let ws = Workspace::new(&root, config)?;
ops::compile(&ws, &opts)?;
Ok(None)
}
14 changes: 13 additions & 1 deletion src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl LibKind {
"lib" => LibKind::Lib,
"rlib" => LibKind::Rlib,
"dylib" => LibKind::Dylib,
"procc-macro" => LibKind::ProcMacro,
"proc-macro" => LibKind::ProcMacro,
s => LibKind::Other(s.to_string()),
}
}
Expand Down Expand Up @@ -136,6 +136,7 @@ pub struct Profile {
pub test: bool,
pub doc: bool,
pub run_custom_build: bool,
pub check: bool,
pub panic: Option<String>,
}

Expand Down Expand Up @@ -168,6 +169,7 @@ pub struct Profiles {
pub bench_deps: Profile,
pub doc: Profile,
pub custom_build: Profile,
pub check: Profile,
}

/// Information about a binary, a library, an example, etc. that is part of the
Expand Down Expand Up @@ -531,6 +533,13 @@ impl Profile {
..Profile::default_dev()
}
}

pub fn default_check() -> Profile {
Profile {
check: true,
..Profile::default_dev()
}
}
}

impl Default for Profile {
Expand All @@ -547,6 +556,7 @@ impl Default for Profile {
test: false,
doc: false,
run_custom_build: false,
check: false,
panic: None,
}
}
Expand All @@ -560,6 +570,8 @@ impl fmt::Display for Profile {
write!(f, "Profile(doc)")
} else if self.run_custom_build {
write!(f, "Profile(run)")
} else if self.check {
write!(f, "Profile(check)")
} else {
write!(f, "Profile(build)")
}
Expand Down
1 change: 1 addition & 0 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ impl<'cfg> Workspace<'cfg> {
bench_deps: Profile::default_release(),
doc: Profile::default_doc(),
custom_build: Profile::default_custom_build(),
check: Profile::default_check(),
};

for pkg in self.members().filter(|p| p.manifest_path() != root_manifest) {
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/ops/cargo_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
for kind in [Kind::Host, Kind::Target].iter() {
let Profiles {
ref release, ref dev, ref test, ref bench, ref doc,
ref custom_build, ref test_deps, ref bench_deps,
ref custom_build, ref test_deps, ref bench_deps, ref check
} = *profiles;
let profiles = [release, dev, test, bench, doc, custom_build,
test_deps, bench_deps];
test_deps, bench_deps, check];
for profile in profiles.iter() {
units.push(Unit {
pkg: &pkg,
Expand Down
18 changes: 10 additions & 8 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub struct CompileOptions<'a> {
pub enum CompileMode {
Test,
Build,
Check,
Bench,
Doc { deps: bool },
}
Expand Down Expand Up @@ -188,13 +189,13 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,

let profiles = ws.profiles();

let resolve = resolve_dependencies(ws,
source,
features,
all_features,
no_default_features,
&spec)?;
let (spec, packages, resolve_with_overrides) = resolve;
let pair = resolve_dependencies(ws,
source,
features,
all_features,
no_default_features,
&specs)?;
let (packages, resolve_with_overrides) = pair;

let mut pkgids = Vec::new();
if spec.len() > 0 {
Expand Down Expand Up @@ -335,6 +336,7 @@ fn generate_targets<'a>(pkg: &'a Package,
CompileMode::Test => test,
CompileMode::Bench => &profiles.bench,
CompileMode::Build => build,
CompileMode::Check => &profiles.check,
CompileMode::Doc { .. } => &profiles.doc,
};
match *filter {
Expand Down Expand Up @@ -366,7 +368,7 @@ fn generate_targets<'a>(pkg: &'a Package,
}
Ok(base)
}
CompileMode::Build => {
CompileMode::Build | CompileMode::Check => {
Ok(pkg.targets().iter().filter(|t| {
t.is_bin() || t.is_lib()
}).map(|t| (t, profile)).collect())
Expand Down
68 changes: 43 additions & 25 deletions src/cargo/ops/cargo_rustc/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::layout::Layout;
use super::links::Links;
use super::{Kind, Compilation, BuildConfig};

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub struct Unit<'a> {
pub pkg: &'a Package,
pub target: &'a Target,
Expand Down Expand Up @@ -70,9 +70,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
let dest = if build_config.release { "release" } else { "debug" };
let host_layout = Layout::new(ws, None, &dest)?;
let target_layout = match build_config.requested_target.as_ref() {
Some(target) => {
Some(Layout::new(ws, Some(&target), &dest)?)
}
Some(target) => Some(Layout::new(ws, Some(&target), dest)?),
None => None,
};

Expand Down Expand Up @@ -148,6 +146,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
unit: &Unit<'a>,
crate_types: &mut BTreeSet<String>)
-> CargoResult<()> {
if unit.profile.check {
crate_types.insert("metadata".to_string());
}
for target in unit.pkg.manifest().targets() {
crate_types.extend(target.rustc_crate_types().iter().map(|s| {
if *s == "lib" {
Expand Down Expand Up @@ -207,6 +208,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
line.contains(crate_type)
});
if not_supported {
if crate_type == "metadata" {
bail!("compiler does not support `--crate-type metadata`, \
cannot run `cargo check`.");
}
map.insert(crate_type.to_string(), None);
continue
}
Expand Down Expand Up @@ -251,8 +256,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
let mut visited = HashSet::new();
for unit in units {
self.walk_used_in_plugin_map(unit,
unit.target.for_host(),
&mut visited)?;
unit.target.for_host(),
&mut visited)?;
}
Ok(())
}
Expand All @@ -270,8 +275,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
}
for unit in self.dep_targets(unit)? {
self.walk_used_in_plugin_map(&unit,
is_plugin || unit.target.for_host(),
visited)?;
is_plugin || unit.target.for_host(),
visited)?;
}
Ok(())
}
Expand Down Expand Up @@ -509,20 +514,25 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
}
}
};
match *unit.target.kind() {
TargetKind::Example |
TargetKind::Bin |
TargetKind::CustomBuild |
TargetKind::Bench |
TargetKind::Test => {
add("bin", false)?;
}
TargetKind::Lib(..) if unit.profile.test => {
add("bin", false)?;
}
TargetKind::Lib(ref libs) => {
for lib in libs {
add(lib.crate_type(), lib.linkable())?;

if unit.profile.check {
add("metadata", true)?;
} else {
match *unit.target.kind() {
TargetKind::Example |
TargetKind::Bin |
TargetKind::CustomBuild |
TargetKind::Bench |
TargetKind::Test => {
add("bin", false)?;
}
TargetKind::Lib(..) if unit.profile.test => {
add("bin", false)?;
}
TargetKind::Lib(ref libs) => {
for lib in libs {
add(lib.crate_type(), lib.linkable())?;
}
}
}
}
Expand Down Expand Up @@ -593,12 +603,20 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
match self.get_package(id) {
Ok(pkg) => {
pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
Ok(Unit {
let profile = if unit.profile.check &&
!t.is_custom_build()
&& !t.for_host() {
&self.profiles.check
} else {
self.lib_profile()
};
let unit = Unit {
pkg: pkg,
target: t,
profile: self.lib_profile(),
profile: profile,
kind: unit.kind.for_target(t),
})
};
Ok(unit)
})
}
Err(e) => Some(Err(e))
Expand Down
Loading

0 comments on commit 4b82fdc

Please sign in to comment.