Skip to content

Commit 4b82fdc

Browse files
committed
cargo check
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).
1 parent fec03d3 commit 4b82fdc

File tree

12 files changed

+348
-44
lines changed

12 files changed

+348
-44
lines changed

src/bin/cargo.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Options:
5151
5252
Some common cargo commands are (see all commands with --list):
5353
build Compile the current project
54+
check Analyze the current project and report errors, but don't build object files
5455
clean Remove the target directory
5556
doc Build this project's and its dependencies' documentation
5657
new Create a new cargo project
@@ -75,6 +76,7 @@ macro_rules! each_subcommand{
7576
($mac:ident) => {
7677
$mac!(bench);
7778
$mac!(build);
79+
$mac!(check);
7880
$mac!(clean);
7981
$mac!(doc);
8082
$mac!(fetch);

src/bin/check.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use std::env;
2+
3+
use cargo::core::Workspace;
4+
use cargo::ops::{self, CompileOptions, MessageFormat};
5+
use cargo::util::important_paths::{find_root_manifest_for_wd};
6+
use cargo::util::{CliResult, Config};
7+
8+
#[derive(RustcDecodable)]
9+
pub struct Options {
10+
flag_package: Vec<String>,
11+
flag_jobs: Option<u32>,
12+
flag_features: Vec<String>,
13+
flag_all_features: bool,
14+
flag_no_default_features: bool,
15+
flag_target: Option<String>,
16+
flag_manifest_path: Option<String>,
17+
flag_verbose: u32,
18+
flag_quiet: Option<bool>,
19+
flag_color: Option<String>,
20+
flag_message_format: MessageFormat,
21+
flag_release: bool,
22+
flag_lib: bool,
23+
flag_bin: Vec<String>,
24+
flag_example: Vec<String>,
25+
flag_test: Vec<String>,
26+
flag_bench: Vec<String>,
27+
flag_locked: bool,
28+
flag_frozen: bool,
29+
}
30+
31+
pub const USAGE: &'static str = "
32+
Check a local package and all of its dependencies for errors
33+
34+
Usage:
35+
cargo check [options]
36+
37+
Options:
38+
-h, --help Print this message
39+
-p SPEC, --package SPEC ... Package to check
40+
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
41+
--lib Check only this package's library
42+
--bin NAME Check only the specified binary
43+
--example NAME Check only the specified example
44+
--test NAME Check only the specified test target
45+
--bench NAME Check only the specified benchmark target
46+
--release Check artifacts in release mode, with optimizations
47+
--features FEATURES Space-separated list of features to also check
48+
--all-features Check all available features
49+
--no-default-features Do not check the `default` feature
50+
--target TRIPLE Check for the target triple
51+
--manifest-path PATH Path to the manifest to compile
52+
-v, --verbose ... Use verbose output
53+
-q, --quiet No output printed to stdout
54+
--color WHEN Coloring: auto, always, never
55+
--message-format FMT Error format: human, json [default: human]
56+
--frozen Require Cargo.lock and cache are up to date
57+
--locked Require Cargo.lock is up to date
58+
59+
If the --package argument is given, then SPEC is a package id specification
60+
which indicates which package should be built. If it is not given, then the
61+
current package is built. For more information on SPEC and its format, see the
62+
`cargo help pkgid` command.
63+
64+
Compilation can be configured via the use of profiles which are configured in
65+
the manifest. The default profile for this command is `dev`, but passing
66+
the --release flag will use the `release` profile instead.
67+
";
68+
69+
pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
70+
debug!("executing; cmd=cargo-check; args={:?}",
71+
env::args().collect::<Vec<_>>());
72+
config.configure(options.flag_verbose,
73+
options.flag_quiet,
74+
&options.flag_color,
75+
options.flag_frozen,
76+
options.flag_locked)?;
77+
78+
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
79+
80+
let opts = CompileOptions {
81+
config: config,
82+
jobs: options.flag_jobs,
83+
target: options.flag_target.as_ref().map(|t| &t[..]),
84+
features: &options.flag_features,
85+
all_features: options.flag_all_features,
86+
no_default_features: options.flag_no_default_features,
87+
spec: &options.flag_package,
88+
mode: ops::CompileMode::Check,
89+
release: options.flag_release,
90+
filter: ops::CompileFilter::new(options.flag_lib,
91+
&options.flag_bin,
92+
&options.flag_test,
93+
&options.flag_example,
94+
&options.flag_bench),
95+
message_format: options.flag_message_format,
96+
target_rustdoc_args: None,
97+
target_rustc_args: None,
98+
};
99+
100+
let ws = Workspace::new(&root, config)?;
101+
ops::compile(&ws, &opts)?;
102+
Ok(None)
103+
}

src/cargo/core/manifest.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl LibKind {
7171
"lib" => LibKind::Lib,
7272
"rlib" => LibKind::Rlib,
7373
"dylib" => LibKind::Dylib,
74-
"procc-macro" => LibKind::ProcMacro,
74+
"proc-macro" => LibKind::ProcMacro,
7575
s => LibKind::Other(s.to_string()),
7676
}
7777
}
@@ -136,6 +136,7 @@ pub struct Profile {
136136
pub test: bool,
137137
pub doc: bool,
138138
pub run_custom_build: bool,
139+
pub check: bool,
139140
pub panic: Option<String>,
140141
}
141142

@@ -168,6 +169,7 @@ pub struct Profiles {
168169
pub bench_deps: Profile,
169170
pub doc: Profile,
170171
pub custom_build: Profile,
172+
pub check: Profile,
171173
}
172174

173175
/// Information about a binary, a library, an example, etc. that is part of the
@@ -531,6 +533,13 @@ impl Profile {
531533
..Profile::default_dev()
532534
}
533535
}
536+
537+
pub fn default_check() -> Profile {
538+
Profile {
539+
check: true,
540+
..Profile::default_dev()
541+
}
542+
}
534543
}
535544

536545
impl Default for Profile {
@@ -547,6 +556,7 @@ impl Default for Profile {
547556
test: false,
548557
doc: false,
549558
run_custom_build: false,
559+
check: false,
550560
panic: None,
551561
}
552562
}
@@ -560,6 +570,8 @@ impl fmt::Display for Profile {
560570
write!(f, "Profile(doc)")
561571
} else if self.run_custom_build {
562572
write!(f, "Profile(run)")
573+
} else if self.check {
574+
write!(f, "Profile(check)")
563575
} else {
564576
write!(f, "Profile(build)")
565577
}

src/cargo/core/workspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ impl<'cfg> Workspace<'cfg> {
450450
bench_deps: Profile::default_release(),
451451
doc: Profile::default_doc(),
452452
custom_build: Profile::default_custom_build(),
453+
check: Profile::default_check(),
453454
};
454455

455456
for pkg in self.members().filter(|p| p.manifest_path() != root_manifest) {

src/cargo/ops/cargo_clean.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
5454
for kind in [Kind::Host, Kind::Target].iter() {
5555
let Profiles {
5656
ref release, ref dev, ref test, ref bench, ref doc,
57-
ref custom_build, ref test_deps, ref bench_deps,
57+
ref custom_build, ref test_deps, ref bench_deps, ref check
5858
} = *profiles;
5959
let profiles = [release, dev, test, bench, doc, custom_build,
60-
test_deps, bench_deps];
60+
test_deps, bench_deps, check];
6161
for profile in profiles.iter() {
6262
units.push(Unit {
6363
pkg: &pkg,

src/cargo/ops/cargo_compile.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub struct CompileOptions<'a> {
6969
pub enum CompileMode {
7070
Test,
7171
Build,
72+
Check,
7273
Bench,
7374
Doc { deps: bool },
7475
}
@@ -188,13 +189,13 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
188189

189190
let profiles = ws.profiles();
190191

191-
let resolve = resolve_dependencies(ws,
192-
source,
193-
features,
194-
all_features,
195-
no_default_features,
196-
&spec)?;
197-
let (spec, packages, resolve_with_overrides) = resolve;
192+
let pair = resolve_dependencies(ws,
193+
source,
194+
features,
195+
all_features,
196+
no_default_features,
197+
&specs)?;
198+
let (packages, resolve_with_overrides) = pair;
198199

199200
let mut pkgids = Vec::new();
200201
if spec.len() > 0 {
@@ -335,6 +336,7 @@ fn generate_targets<'a>(pkg: &'a Package,
335336
CompileMode::Test => test,
336337
CompileMode::Bench => &profiles.bench,
337338
CompileMode::Build => build,
339+
CompileMode::Check => &profiles.check,
338340
CompileMode::Doc { .. } => &profiles.doc,
339341
};
340342
match *filter {
@@ -366,7 +368,7 @@ fn generate_targets<'a>(pkg: &'a Package,
366368
}
367369
Ok(base)
368370
}
369-
CompileMode::Build => {
371+
CompileMode::Build | CompileMode::Check => {
370372
Ok(pkg.targets().iter().filter(|t| {
371373
t.is_bin() || t.is_lib()
372374
}).map(|t| (t, profile)).collect())

src/cargo/ops/cargo_rustc/context.rs

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use super::layout::Layout;
2020
use super::links::Links;
2121
use super::{Kind, Compilation, BuildConfig};
2222

23-
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
23+
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
2424
pub struct Unit<'a> {
2525
pub pkg: &'a Package,
2626
pub target: &'a Target,
@@ -70,9 +70,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
7070
let dest = if build_config.release { "release" } else { "debug" };
7171
let host_layout = Layout::new(ws, None, &dest)?;
7272
let target_layout = match build_config.requested_target.as_ref() {
73-
Some(target) => {
74-
Some(Layout::new(ws, Some(&target), &dest)?)
75-
}
73+
Some(target) => Some(Layout::new(ws, Some(&target), dest)?),
7674
None => None,
7775
};
7876

@@ -148,6 +146,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
148146
unit: &Unit<'a>,
149147
crate_types: &mut BTreeSet<String>)
150148
-> CargoResult<()> {
149+
if unit.profile.check {
150+
crate_types.insert("metadata".to_string());
151+
}
151152
for target in unit.pkg.manifest().targets() {
152153
crate_types.extend(target.rustc_crate_types().iter().map(|s| {
153154
if *s == "lib" {
@@ -207,6 +208,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
207208
line.contains(crate_type)
208209
});
209210
if not_supported {
211+
if crate_type == "metadata" {
212+
bail!("compiler does not support `--crate-type metadata`, \
213+
cannot run `cargo check`.");
214+
}
210215
map.insert(crate_type.to_string(), None);
211216
continue
212217
}
@@ -251,8 +256,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
251256
let mut visited = HashSet::new();
252257
for unit in units {
253258
self.walk_used_in_plugin_map(unit,
254-
unit.target.for_host(),
255-
&mut visited)?;
259+
unit.target.for_host(),
260+
&mut visited)?;
256261
}
257262
Ok(())
258263
}
@@ -270,8 +275,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
270275
}
271276
for unit in self.dep_targets(unit)? {
272277
self.walk_used_in_plugin_map(&unit,
273-
is_plugin || unit.target.for_host(),
274-
visited)?;
278+
is_plugin || unit.target.for_host(),
279+
visited)?;
275280
}
276281
Ok(())
277282
}
@@ -509,20 +514,25 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
509514
}
510515
}
511516
};
512-
match *unit.target.kind() {
513-
TargetKind::Example |
514-
TargetKind::Bin |
515-
TargetKind::CustomBuild |
516-
TargetKind::Bench |
517-
TargetKind::Test => {
518-
add("bin", false)?;
519-
}
520-
TargetKind::Lib(..) if unit.profile.test => {
521-
add("bin", false)?;
522-
}
523-
TargetKind::Lib(ref libs) => {
524-
for lib in libs {
525-
add(lib.crate_type(), lib.linkable())?;
517+
518+
if unit.profile.check {
519+
add("metadata", true)?;
520+
} else {
521+
match *unit.target.kind() {
522+
TargetKind::Example |
523+
TargetKind::Bin |
524+
TargetKind::CustomBuild |
525+
TargetKind::Bench |
526+
TargetKind::Test => {
527+
add("bin", false)?;
528+
}
529+
TargetKind::Lib(..) if unit.profile.test => {
530+
add("bin", false)?;
531+
}
532+
TargetKind::Lib(ref libs) => {
533+
for lib in libs {
534+
add(lib.crate_type(), lib.linkable())?;
535+
}
526536
}
527537
}
528538
}
@@ -593,12 +603,20 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
593603
match self.get_package(id) {
594604
Ok(pkg) => {
595605
pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
596-
Ok(Unit {
606+
let profile = if unit.profile.check &&
607+
!t.is_custom_build()
608+
&& !t.for_host() {
609+
&self.profiles.check
610+
} else {
611+
self.lib_profile()
612+
};
613+
let unit = Unit {
597614
pkg: pkg,
598615
target: t,
599-
profile: self.lib_profile(),
616+
profile: profile,
600617
kind: unit.kind.for_target(t),
601-
})
618+
};
619+
Ok(unit)
602620
})
603621
}
604622
Err(e) => Some(Err(e))

0 commit comments

Comments
 (0)