From 9eb913a7e227e4c11ca0c2c7d8fd7ca22ed9c466 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 9 Feb 2020 12:00:49 +0700 Subject: [PATCH] Fix error E0460 when compiled on Rustc repo --- tests/cargo/mod.rs | 74 ++++++++------------------------------- tests/compile-test.rs | 80 +++++++++++++++++++++++++++++++------------ tests/dogfood.rs | 13 ++++--- 3 files changed, 78 insertions(+), 89 deletions(-) diff --git a/tests/cargo/mod.rs b/tests/cargo/mod.rs index 5b2de05cb174..9973d5b84434 100644 --- a/tests/cargo/mod.rs +++ b/tests/cargo/mod.rs @@ -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() } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 7cfbfcf16a99..de2cf6d7873f 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -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; @@ -11,51 +11,87 @@ use std::path::{Path, PathBuf}; mod cargo; -#[must_use] -fn rustc_test_suite() -> Option { - 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 } diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 5458143ab1cc..81af3d3033b2 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -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")); @@ -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"));