#
cargo_test_support/
cross_compile.rs

    1//! Support for cross-compile tests with the `--target` flag.
    2//!
    3//! Note that cross-testing is very limited. You need to install the
    4//! "alternate" target to the host (32-bit for 64-bit hosts or vice-versa).
    5//!
    6//! Set `CFG_DISABLE_CROSS_TESTS=1` environment variable to disable these tests
    7//! if you are unable to use the alternate target. Unfortunately 32-bit
    8//! support on macOS is going away, so macOS users are out of luck.
    9//!
    10//! These tests are all disabled on rust-lang/rust's CI, but run in Cargo's CI.
    11
    12use std::env;
    13
    14/// The arch triple of the test-running host.
    15pub fn native() -> &'static str {
    16    env!("NATIVE_ARCH")
    17}
    18
    19pub fn native_arch() -> &'static str {
    20    match native()
    21        .split("-")
    22        .next()
    23        .expect("Target triple has unexpected format")
    24    {
    25        "x86_64" => "x86_64",
    26        "aarch64" => "aarch64",
    27        "i686" => "x86",
    28        _ => panic!("This test should be gated on cross_compile::disabled."),
    29    }
    30}
    31
    32/// The alternate target-triple to build with.
    33///
    34/// Only use this function on tests that check `cross_compile::disabled`.
    35pub fn alternate() -> &'static str {
    36    try_alternate().expect("This test should be gated on cross_compile::disabled.")
    37}
    38
    39/// A possible alternate target-triple to build with.
    40pub(crate) fn try_alternate() -> Option<&'static str> {
    41    if cfg!(target_os = "macos") {
    42        Some("x86_64-apple-darwin")
    43    } else if cfg!(target_os = "linux") {
    44        Some("i686-unknown-linux-gnu")
    45    } else if cfg!(all(target_os = "windows", target_env = "msvc")) {
    46        Some("i686-pc-windows-msvc")
    47    } else if cfg!(all(target_os = "windows", target_env = "gnu")) {
    48        Some("i686-pc-windows-gnu")
    49    } else {
    50        None
    51    }
    52}
    53
    54pub fn alternate_arch() -> &'static str {
    55    if cfg!(target_os = "macos") {
    56        "x86_64"
    57    } else {
    58        "x86"
    59    }
    60}
    61
    62/// A target-triple that is neither the host nor the target.
    63///
    64/// Rustc may not work with it and it's alright, apart from being a
    65/// valid target triple it is supposed to be used only as a
    66/// placeholder for targets that should not be considered.
    67pub fn unused() -> &'static str {
    68    "wasm32-unknown-unknown"
    69}
    70
    71/// Check if the given target has been installed.
    72///
    73/// Generally `testsuite::utils::cross_compile::disabled` should be used to check if cross-compilation is allowed.
    74/// And [`alternate`] to get the cross target.
    75///
    76/// You should only use this as a last resort to skip tests,
    77/// because it doesn't report skipped tests as ignored.
    78pub fn requires_target_installed(target: &str) -> bool {
    79    let has_target = std::process::Command::new("rustup")
    80        .args(["target", "list", "--installed"])
    81        .output()
    82        .ok()
    83        .map(|output| {
    84            String::from_utf8(output.stdout)
    85                .map(|stdout| stdout.contains(target))
    86                .unwrap_or_default()
    87        })
    88        .unwrap_or_default();
    89    if !has_target {
    90        let msg =
    91            format!("to run this test, run `rustup target add {target} --toolchain <toolchain>`",);
    92        if cargo_util::is_ci() {
    93            panic!("{msg}");
    94        } else {
    95            eprintln!("{msg}");
    96        }
    97    }
    98    has_target
    99}