mirror of
https://github.com/rust-lang/cargo
synced 2024-09-20 08:11:50 +00:00
handle cross-compilation test failure more gracefully
The current cross-compilation test module fails every test if an appropriate cross standard library is not found. This behavior is unhelpful, because the failures are verbose, unexpected, and there's no obvious way to make them go away. Instead, it would be better to check once before all the tests that an appropriate cross-compilation setup is available. Once that check has been done, a single test can fail with an appropriate `panic!` message while the other tests silently pass. The `panic!` message can inform the user about their options, either setting an appropriate environment variable, or using rustup to install the necessary cross standard library. Assuming the user has rustup installed, the single failure now looks something like: ``` thread 'plugin_deps' panicked at 'Cannot cross compile to i686-unknown-linux-gnu. This failure can be safely ignored. If you would prefer to not see this failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to "1". Alternatively, you can install the necessary libraries for cross-compilation with rustup toolchain install stable-i686-unknown-linux-gnu You may need to install runtime libraries for your Linux distribution as well. ', tests/cross-compile.rs:87 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` Fixes #3086.
This commit is contained in:
parent
508d66bca7
commit
bbc1079877
|
@ -3,10 +3,13 @@ extern crate cargotest;
|
|||
extern crate hamcrest;
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
|
||||
|
||||
use cargo::util::process;
|
||||
use cargotest::{is_nightly, rustc_host};
|
||||
use cargotest::support::{project, execs, basic_bin_manifest};
|
||||
use cargotest::support::{project, execs, main_file, basic_bin_manifest};
|
||||
use hamcrest::{assert_that, existing_file};
|
||||
|
||||
fn disabled() -> bool {
|
||||
|
@ -19,9 +22,82 @@ fn disabled() -> bool {
|
|||
// Right now the windows bots cannot cross compile due to the mingw setup,
|
||||
// so we disable ourselves on all but macos/linux setups where the rustc
|
||||
// install script ensures we have both architectures
|
||||
!(cfg!(target_os = "macos") ||
|
||||
cfg!(target_os = "linux") ||
|
||||
cfg!(target_env = "msvc"))
|
||||
if !(cfg!(target_os = "macos") ||
|
||||
cfg!(target_os = "linux") ||
|
||||
cfg!(target_env = "msvc")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// It's not particularly common to have a cross-compilation setup, so
|
||||
// try to detect that before we fail a bunch of tests through no fault
|
||||
// of the user.
|
||||
static mut CAN_RUN_CROSS_TESTS: bool = false;
|
||||
static CHECK: Once = ONCE_INIT;
|
||||
|
||||
let cross_target = alternate();
|
||||
|
||||
CHECK.call_once(|| {
|
||||
let p = project("cross_test")
|
||||
.file("Cargo.toml", &basic_bin_manifest("cross_test"))
|
||||
.file("src/cross_test.rs", &main_file(r#""testing!""#, &[]));
|
||||
|
||||
let result = p.cargo_process("build")
|
||||
.arg("--target").arg(&cross_target)
|
||||
.exec_with_output();
|
||||
|
||||
if result.is_ok() {
|
||||
unsafe {
|
||||
CAN_RUN_CROSS_TESTS = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if unsafe { CAN_RUN_CROSS_TESTS } {
|
||||
// We were able to compile a simple project, so the user has the
|
||||
// necessary std:: bits installed. Therefore, tests should not
|
||||
// be disabled.
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can't compile a simple cross project. We want to warn the user
|
||||
// by failing a single test and having the remainder of the cross tests
|
||||
// pass. We don't use std::sync::Once here because panicing inside its
|
||||
// call_once method would poison the Once instance, which is not what
|
||||
// we want.
|
||||
static HAVE_WARNED: AtomicBool = ATOMIC_BOOL_INIT;
|
||||
|
||||
if HAVE_WARNED.swap(true, Ordering::SeqCst) {
|
||||
// We are some other test and somebody else is handling the warning.
|
||||
// Just disable the current test.
|
||||
return true;
|
||||
}
|
||||
|
||||
// We are responsible for warning the user, which we do by panicing.
|
||||
let rustup_available = Command::new("rustup").output().is_ok();
|
||||
|
||||
let linux_help = if cfg!(target_os = "linux") {
|
||||
"
|
||||
|
||||
You may need to install runtime libraries for your Linux distribution as well.".to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let rustup_help = if rustup_available {
|
||||
format!("
|
||||
|
||||
Alternatively, you can install the necessary libraries for cross-compilation with
|
||||
|
||||
rustup target add {}{}", cross_target, linux_help)
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
panic!("Cannot cross compile to {}.
|
||||
|
||||
This failure can be safely ignored. If you would prefer to not see this
|
||||
failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to \"1\".{}
|
||||
", cross_target, rustup_help);
|
||||
}
|
||||
|
||||
fn alternate() -> String {
|
||||
|
|
Loading…
Reference in a new issue