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

Fix error E0460 when compiled on Rustc repo #5145

Merged
merged 1 commit into from
Feb 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 14 additions & 60 deletions tests/cargo/mod.rs
Original file line number Diff line number Diff line change
@@ -1,75 +1,29 @@
use cargo_metadata::{Message::CompilerArtifact, MetadataCommand};
use lazy_static::lazy_static;
use std::env;
use std::ffi::OsStr;
use std::mem;
use std::path::PathBuf;
use std::process::Command;

pub struct BuildInfo {
cargo_target_dir: PathBuf,
}

impl BuildInfo {
pub fn new() -> Self {
let data = MetadataCommand::new().exec().unwrap();
Self {
cargo_target_dir: data.target_directory,
lazy_static! {
pub static ref CARGO_TARGET_DIR: PathBuf = {
match env::var_os("CARGO_TARGET_DIR") {
Some(v) => v.into(),
None => "target".into(),
}
}

pub fn host_lib(&self) -> PathBuf {
if let Some(path) = option_env!("HOST_LIBS") {
PathBuf::from(path)
} else {
self.cargo_target_dir.join(env!("PROFILE"))
}
}

pub fn target_lib(&self) -> PathBuf {
};
pub static ref TARGET_LIB: PathBuf = {
if let Some(path) = option_env!("TARGET_LIBS") {
path.into()
} else {
let mut dir = self.cargo_target_dir.clone();
let mut dir = CARGO_TARGET_DIR.clone();
if let Some(target) = env::var_os("CARGO_BUILD_TARGET") {
dir.push(target);
}
dir.push(env!("PROFILE"));
dir
}
}

pub fn clippy_driver_path(&self) -> PathBuf {
if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
PathBuf::from(path)
} else {
self.target_lib().join("clippy-driver")
}
}

// When we'll want to use `extern crate ..` for a dependency that is used
// both by the crate and the compiler itself, we can't simply pass -L flags
// as we'll get a duplicate matching versions. Instead, disambiguate with
// `--extern dep=path`.
// See https://github.com/rust-lang/rust-clippy/issues/4015.
pub fn third_party_crates() -> Vec<(&'static str, PathBuf)> {
const THIRD_PARTY_CRATES: [&str; 4] = ["serde", "serde_derive", "regex", "clippy_lints"];
let cargo = env::var_os("CARGO");
let cargo = cargo.as_deref().unwrap_or_else(|| OsStr::new("cargo"));
let output = Command::new(cargo)
.arg("build")
.arg("--test=compile-test")
.arg("--message-format=json")
.output()
.unwrap();
};
}

let mut crates = Vec::with_capacity(THIRD_PARTY_CRATES.len());
for message in cargo_metadata::parse_messages(output.stdout.as_slice()) {
if let CompilerArtifact(mut artifact) = message.unwrap() {
if let Some(&krate) = THIRD_PARTY_CRATES.iter().find(|&&krate| krate == artifact.target.name) {
crates.push((krate, mem::take(&mut artifact.filenames[0])));
}
}
}
crates
}
#[must_use]
pub fn is_rustc_test_suite() -> bool {
option_env!("RUSTC_TEST_SUITE").is_some()
}
80 changes: 58 additions & 22 deletions tests/compile-test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(test)]
#![feature(test)] // compiletest_rs requires this attribute

use compiletest_rs as compiletest;
use compiletest_rs::common::Mode as TestMode;
Expand All @@ -11,51 +11,87 @@ use std::path::{Path, PathBuf};

mod cargo;

#[must_use]
fn rustc_test_suite() -> Option<PathBuf> {
option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
fn host_lib() -> PathBuf {
if let Some(path) = option_env!("HOST_LIBS") {
PathBuf::from(path)
} else {
cargo::CARGO_TARGET_DIR.join(env!("PROFILE"))
}
}

#[must_use]
fn rustc_lib_path() -> PathBuf {
option_env!("RUSTC_LIB_PATH").unwrap().into()
fn clippy_driver_path() -> PathBuf {
if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
PathBuf::from(path)
} else {
cargo::TARGET_LIB.join("clippy-driver")
}
}

// When we'll want to use `extern crate ..` for a dependency that is used
// both by the crate and the compiler itself, we can't simply pass -L flags
// as we'll get a duplicate matching versions. Instead, disambiguate with
// `--extern dep=path`.
// See https://github.com/rust-lang/rust-clippy/issues/4015.
//
// FIXME: We cannot use `cargo build --message-format=json` to resolve to dependency files.
// Because it would force-rebuild if the options passed to `build` command is not the same
// as what we manually pass to `cargo` invocation
fn third_party_crates() -> String {
use std::collections::HashMap;
static CRATES: &[&str] = &["serde", "serde_derive", "regex", "clippy_lints"];
let dep_dir = cargo::TARGET_LIB.join("deps");
let mut crates: HashMap<&str, PathBuf> = HashMap::with_capacity(CRATES.len());
for entry in fs::read_dir(dep_dir).unwrap() {
let path = match entry {
Ok(entry) => entry.path(),
_ => continue,
};
if let Some(name) = path.file_name().and_then(OsStr::to_str) {
for dep in CRATES {
if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") {
crates.entry(dep).or_insert(path);
break;
}
}
}
}

let v: Vec<_> = crates
.into_iter()
.map(|(dep, path)| format!("--extern {}={}", dep, path.display()))
.collect();
v.join(" ")
}

fn default_config() -> compiletest::Config {
let build_info = cargo::BuildInfo::new();
let mut config = compiletest::Config::default();

if let Ok(name) = env::var("TESTNAME") {
config.filter = Some(name);
}

if rustc_test_suite().is_some() {
let path = rustc_lib_path();
if let Some(path) = option_env!("RUSTC_LIB_PATH") {
let path = PathBuf::from(path);
config.run_lib_path = path.clone();
config.compile_lib_path = path;
}

let disambiguated: Vec<_> = cargo::BuildInfo::third_party_crates()
.iter()
.map(|(krate, path)| format!("--extern {}={}", krate, path.display()))
.collect();

config.target_rustcflags = Some(format!(
"-L {0} -L {1} -Dwarnings -Zui-testing {2}",
build_info.host_lib().join("deps").display(),
build_info.target_lib().join("deps").display(),
disambiguated.join(" ")
host_lib().join("deps").display(),
cargo::TARGET_LIB.join("deps").display(),
third_party_crates(),
));

config.build_base = if rustc_test_suite().is_some() {
// we don't need access to the stderr files on travis
config.build_base = if cargo::is_rustc_test_suite() {
// This make the stderr files go to clippy OUT_DIR on rustc repo build dir
let mut path = PathBuf::from(env!("OUT_DIR"));
path.push("test_build_base");
path
} else {
build_info.host_lib().join("test_build_base")
host_lib().join("test_build_base")
};
config.rustc_path = build_info.clippy_driver_path();
config.rustc_path = clippy_driver_path();
config
}

Expand Down
13 changes: 6 additions & 7 deletions tests/dogfood.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
// Dogfood cannot run on Windows
#![cfg(not(windows))]

use lazy_static::lazy_static;
use std::path::PathBuf;
use std::process::Command;

#[allow(dead_code)]
mod cargo;

lazy_static! {
static ref CLIPPY_PATH: PathBuf = {
let build_info = cargo::BuildInfo::new();
build_info.target_lib().join("cargo-clippy")
};
static ref CLIPPY_PATH: PathBuf = cargo::TARGET_LIB.join("cargo-clippy");
}

#[test]
fn dogfood_clippy() {
// run clippy on itself and fail the test if lint warnings are reported
if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
if cargo::is_rustc_test_suite() {
return;
}
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
Expand Down Expand Up @@ -44,7 +43,7 @@ fn dogfood_clippy() {
#[test]
fn dogfood_subprojects() {
// run clippy on remaining subprojects and fail the test if lint warnings are reported
if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
if cargo::is_rustc_test_suite() {
return;
}
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
Expand Down