Pass --cap-lints=allow instead of -Awarnings

This commit adds support to Cargo to pass `--cap-lints allow` to all upstream
dependencies instead of `-A warings`. This should serve the same purpose of
suppressing warnings in upstream dependencies as well as preventing widespread
breakage whenever a change to a lint is introduced in the compiler.
This commit is contained in:
Alex Crichton 2015-07-24 11:49:19 -07:00
parent fec382d5f2
commit ff96fa159b
11 changed files with 171 additions and 71 deletions

View file

@ -126,7 +126,6 @@ pub fn compile_pkg<'a>(package: &Package,
let override_ids = try!(source_ids_from_config(config, package.root()));
let (packages, resolve_with_overrides, sources) = {
let rustc_host = config.rustc_host().to_string();
let mut registry = PackageRegistry::new(config);
if let Some(source) = source {
registry.preload(package.package_id().source_id(), source);
@ -146,13 +145,14 @@ pub fn compile_pkg<'a>(package: &Package,
try!(registry.add_overrides(override_ids));
let platform = target.as_ref().map(|e| &e[..]).or(Some(&rustc_host[..]));
let platform = target.as_ref().unwrap_or(&config.rustc_info().host);
let method = Method::Required{
let method = Method::Required {
dev_deps: true, // TODO: remove this option?
features: &features,
uses_default_features: !no_default_features,
target_platform: platform};
target_platform: Some(&platform[..]),
};
let resolved_with_overrides =
try!(ops::resolve_with_previous(&mut registry, package, method,
@ -397,7 +397,7 @@ fn scrape_build_config(config: &Config,
requested_target: target.clone(),
..Default::default()
};
base.host = try!(scrape_target_config(config, config.rustc_host()));
base.host = try!(scrape_target_config(config, &config.rustc_info().host));
base.target = match target.as_ref() {
Some(triple) => try!(scrape_target_config(config, &triple)),
None => base.host.clone(),

View file

@ -70,7 +70,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
} else {
try!(Context::filename_parts(None, config))
};
let target_triple = target.unwrap_or(config.rustc_host()).to_string();
let target_triple = target.unwrap_or_else(|| {
&config.rustc_info().host[..]
}).to_string();
let engine = build_config.exec_engine.as_ref().cloned().unwrap_or({
Arc::new(Box::new(ProcessEngine))
});
@ -244,9 +246,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
/// otherwise it corresponds to the target platform.
fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
let (triple, pair) = if kind == Kind::Host {
(self.config.rustc_host(), &self.host_dylib)
(&self.config.rustc_info().host, &self.host_dylib)
} else {
(&self.target_triple[..], &self.target_dylib)
(&self.target_triple, &self.target_dylib)
};
match *pair {
None => return Err(human(format!("dylib outputs are not supported \

View file

@ -63,13 +63,13 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
.env("CARGO_MANIFEST_DIR", pkg.root())
.env("NUM_JOBS", &cx.jobs().to_string())
.env("TARGET", &match kind {
Kind::Host => cx.config.rustc_host(),
Kind::Host => &cx.config.rustc_info().host[..],
Kind::Target => cx.target_triple(),
})
.env("DEBUG", &profile.debuginfo.to_string())
.env("OPT_LEVEL", &profile.opt_level.to_string())
.env("PROFILE", if cx.build_config.release {"release"} else {"debug"})
.env("HOST", &cx.config.rustc_host());
.env("HOST", &cx.config.rustc_info().host);
// Be sure to pass along all enabled features for this package, this is the
// last piece of statically known information that we have.

View file

@ -165,8 +165,8 @@ fn calculate<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
v.sort();
v
});
let extra = util::short_hash(&(cx.config.rustc_version(), target, &features,
profile));
let extra = util::short_hash(&(&cx.config.rustc_info().verbose_version,
target, &features, profile));
debug!("extra {:?} {:?} {:?} = {}", target, profile, features, extra);
// Next, recursively calculate the fingerprint for all of our dependencies.

View file

@ -3,7 +3,7 @@ use std::env;
use std::ffi::OsString;
use std::fs;
use std::io::prelude::*;
use std::path::{self, Path, PathBuf};
use std::path::{self, PathBuf};
use std::sync::Arc;
use core::{SourceMap, Package, PackageId, PackageSet, Target, Resolve};
@ -52,29 +52,6 @@ pub struct TargetConfig {
pub overrides: HashMap<String, BuildOutput>,
}
/// Run `rustc` to figure out what its current version string is.
///
/// The second element of the tuple returned is the target triple that rustc
/// is a host for.
pub fn rustc_version<P: AsRef<Path>>(rustc: P) -> CargoResult<(String, String)> {
let output = try!(try!(util::process(rustc.as_ref()))
.arg("-vV")
.exec_with_output());
let output = try!(String::from_utf8(output.stdout).map_err(|_| {
internal("rustc -v didn't return utf8 output")
}));
let triple = {
let triple = output.lines().filter(|l| {
l.starts_with("host: ")
}).map(|l| &l[6..]).next();
let triple = try!(triple.chain_error(|| {
internal("rustc -v didn't have a line for `host:`")
}));
triple.to_string()
};
Ok((output, triple))
}
// Returns a mapping of the root package plus its immediate dependencies to
// where the compiled libraries are all located.
pub fn compile_targets<'a, 'cfg: 'a>(targets: &[(&'a Target, &'a Profile)],
@ -336,10 +313,14 @@ fn rustc(package: &Package, target: &Target, profile: &Profile,
return rustcs.into_iter().map(|(mut rustc, kind)| {
let name = package.name().to_string();
let is_path_source = package.package_id().source_id().is_path();
let show_warnings = package.package_id() == cx.resolve.root() ||
is_path_source;
if !show_warnings {
rustc.arg("-Awarnings");
let allow_warnings = package.package_id() == cx.resolve.root() ||
is_path_source;
if !allow_warnings {
if cx.config.rustc_info().cap_lints {
rustc.arg("--cap-lints").arg("allow");
} else {
rustc.arg("-Awarnings");
}
}
let has_custom_args = profile.rustc_args.is_some();
let exec_engine = cx.exec_engine.clone();

View file

@ -2,7 +2,7 @@ pub use self::cargo_clean::{clean, CleanOptions};
pub use self::cargo_compile::{compile, compile_pkg, CompileOptions};
pub use self::cargo_compile::{CompileFilter, CompileMode};
pub use self::cargo_read_manifest::{read_manifest,read_package,read_packages};
pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind, rustc_version};
pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind};
pub use self::cargo_rustc::{Context, LayoutProxy};
pub use self::cargo_rustc::Platform;
pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig};

View file

@ -12,8 +12,7 @@ use std::path::{Path, PathBuf};
use rustc_serialize::{Encodable,Encoder};
use toml;
use core::{MultiShell, Package};
use ops;
use util::{CargoResult, ChainError, internal, human};
use util::{CargoResult, ChainError, Rustc, internal, human};
use util::toml as cargo_toml;
@ -22,9 +21,7 @@ use self::ConfigValue as CV;
pub struct Config {
home_path: PathBuf,
shell: RefCell<MultiShell>,
rustc_version: String,
/// The current host and default target of rustc
rustc_host: String,
rustc_info: Rustc,
values: RefCell<HashMap<String, ConfigValue>>,
values_loaded: Cell<bool>,
cwd: PathBuf,
@ -45,8 +42,7 @@ impl Config {
This probably means that $HOME was not set.")
})),
shell: RefCell::new(shell),
rustc_version: String::new(),
rustc_host: String::new(),
rustc_info: Rustc::blank(),
cwd: cwd,
values: RefCell::new(HashMap::new()),
values_loaded: Cell::new(false),
@ -92,11 +88,7 @@ impl Config {
pub fn rustdoc(&self) -> &Path { &self.rustdoc }
/// Return the output of `rustc -v verbose`
pub fn rustc_version(&self) -> &str { &self.rustc_version }
/// Return the host platform and default target of rustc
pub fn rustc_host(&self) -> &str { &self.rustc_host }
pub fn rustc_info(&self) -> &Rustc { &self.rustc_info }
pub fn values(&self) -> CargoResult<Ref<HashMap<String, ConfigValue>>> {
if !self.values_loaded.get() {
@ -219,9 +211,7 @@ impl Config {
}
fn scrape_rustc_version(&mut self) -> CargoResult<()> {
let (rustc_version, rustc_host) = try!(ops::rustc_version(&self.rustc));
self.rustc_version = rustc_version;
self.rustc_host = rustc_host;
self.rustc_info = try!(Rustc::new(&self.rustc));
Ok(())
}

View file

@ -1,20 +1,21 @@
pub use self::config::Config;
pub use self::process_builder::{process, ProcessBuilder};
pub use self::dependency_queue::Dependency;
pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
pub use self::errors::{CargoResult, CargoError, ChainError, CliResult};
pub use self::errors::{CliError, ProcessError};
pub use self::errors::{process_error, internal_error, internal, human};
pub use self::errors::{Human, caused_human};
pub use self::errors::{process_error, internal_error, internal, human};
pub use self::graph::Graph;
pub use self::hex::{to_hex, short_hash};
pub use self::lev_distance::{lev_distance};
pub use self::paths::{join_paths, path2bytes, bytes2path, dylib_path};
pub use self::paths::{normalize_path, dylib_path_envvar, without_prefix};
pub use self::lev_distance::{lev_distance};
pub use self::hex::{to_hex, short_hash};
pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
pub use self::dependency_queue::Dependency;
pub use self::graph::Graph;
pub use self::to_url::ToUrl;
pub use self::to_semver::ToSemver;
pub use self::vcs::{GitRepo, HgRepo};
pub use self::process_builder::{process, ProcessBuilder};
pub use self::rustc::Rustc;
pub use self::sha256::Sha256;
pub use self::to_semver::ToSemver;
pub use self::to_url::ToUrl;
pub use self::vcs::{GitRepo, HgRepo};
pub mod config;
pub mod errors;
@ -32,3 +33,4 @@ mod dependency_queue;
mod sha256;
mod shell_escape;
mod vcs;
mod rustc;

50
src/cargo/util/rustc.rs Normal file
View file

@ -0,0 +1,50 @@
use std::path::Path;
use util::{self, CargoResult, internal, ChainError};
pub struct Rustc {
pub verbose_version: String,
pub host: String,
pub cap_lints: bool,
}
impl Rustc {
/// Run the compiler at `path` to learn varioues pieces of information about
/// it.
///
/// If successful this function returns a description of the compiler along
/// with a list of its capabilities.
pub fn new<P: AsRef<Path>>(path: P) -> CargoResult<Rustc> {
let mut cmd = try!(util::process(path.as_ref()));
cmd.arg("-vV");
let mut ret = Rustc::blank();
let mut first = cmd.clone();
first.arg("--cap-lints").arg("allow");
let output = match first.exec_with_output() {
Ok(output) => { ret.cap_lints = true; output }
Err(..) => try!(cmd.exec_with_output()),
};
ret.verbose_version = try!(String::from_utf8(output.stdout).map_err(|_| {
internal("rustc -v didn't return utf8 output")
}));
ret.host = {
let triple = ret.verbose_version.lines().filter(|l| {
l.starts_with("host: ")
}).map(|l| &l[6..]).next();
let triple = try!(triple.chain_error(|| {
internal("rustc -v didn't have a line for `host:`")
}));
triple.to_string()
};
Ok(ret)
}
pub fn blank() -> Rustc {
Rustc {
verbose_version: String::new(),
host: String::new(),
cap_lints: false,
}
}
}

View file

@ -1654,3 +1654,73 @@ test!(doctest_same_name {
assert_that(p.cargo_process("test").arg("-v"),
execs().with_status(0));
});
test!(lints_are_suppressed {
let a = git::new("a", |p| {
p.file("Cargo.toml", r#"
[project]
name = "a"
version = "0.5.0"
authors = []
"#)
.file("src/lib.rs", "
use std::option;
")
}).unwrap();
let p = project("foo")
.file("Cargo.toml", &format!(r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = {{ git = '{}' }}
"#, a.url()))
.file("src/lib.rs", "");
assert_that(p.cargo_process("build"),
execs().with_status(0).with_stdout(&format!("\
{updating} git repository `[..]`
{compiling} a v0.5.0 ([..])
{compiling} foo v0.0.1 ([..])
", compiling = COMPILING, updating = UPDATING)));
});
test!(denied_lints_are_allowed {
let enabled = super::RUSTC.with(|r| r.cap_lints);
if !enabled { return }
let a = git::new("a", |p| {
p.file("Cargo.toml", r#"
[project]
name = "a"
version = "0.5.0"
authors = []
"#)
.file("src/lib.rs", "
#![deny(warnings)]
use std::option;
")
}).unwrap();
let p = project("foo")
.file("Cargo.toml", &format!(r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = {{ git = '{}' }}
"#, a.url()))
.file("src/lib.rs", "");
assert_that(p.cargo_process("build"),
execs().with_status(0).with_stdout(&format!("\
{updating} git repository `[..]`
{compiling} a v0.5.0 ([..])
{compiling} foo v0.0.1 ([..])
", compiling = COMPILING, updating = UPDATING)));
});

View file

@ -16,6 +16,8 @@ extern crate url;
#[macro_use]
extern crate log;
use cargo::util::Rustc;
mod support;
macro_rules! test {
($name:ident $expr:expr) => (
@ -57,16 +59,19 @@ mod test_cargo_test;
mod test_cargo_version;
mod test_shell;
thread_local!(static RUSTC: Rustc = Rustc::new("rustc").unwrap());
fn rustc_host() -> String {
cargo::ops::rustc_version("rustc").unwrap().1
RUSTC.with(|r| r.host.clone())
}
fn is_nightly() -> bool {
let version_info = cargo::ops::rustc_version("rustc").unwrap().0;
version_info.contains("-nightly") || version_info.contains("-dev")
RUSTC.with(|r| {
r.verbose_version.contains("-nightly") ||
r.verbose_version.contains("-dev")
})
}
fn can_panic() -> bool {
let host = cargo::ops::rustc_version("rustc").unwrap().1;
!host.contains("msvc")
RUSTC.with(|r| !r.host.contains("msvc"))
}