Skip to content

Commit

Permalink
Add AArch64 tests to CI
Browse files Browse the repository at this point in the history
This commit enhances our CI with an AArch64 builder. Currently we have
no physical hardware to run on so for now we run all tests in an
emulator. The AArch64 build is cross-compiled from x86_64 from Linux.
Tests all happen in release mode with a recent version of QEMU (recent
version because it's so much faster, and in release mode because debug
mode tests take quite a long time in an emulator).

The goal here was not to get all tests passing on CI, but rather to get
AArch64 running on CI and get it green at the same time. To achieve that
goal many tests are now ignored on aarch64 platforms. Many tests fail
due to unimplemented functionality in the aarch64 backend (#1521), and
all wasmtime tests involving compilation are also disabled due to
panicking attempting to generate generate instruction offset information
for trap symbolication (#1523).

Despite this, though, all Cranelift tests and other wasmtime tests
should be runnin on AArch64 through QEMU with this PR. Additionally
we'll have an AArch64 binary release of Wasmtime for Linux, although it
won't be too useful just yet since it will panic on almost all wasm
modules.
  • Loading branch information
alexcrichton committed Apr 16, 2020
1 parent 7d88384 commit b376724
Show file tree
Hide file tree
Showing 30 changed files with 194 additions and 22 deletions.
76 changes: 62 additions & 14 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,52 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- build: x86_64-linux
os: ubuntu-latest
- build: x86_64-macos
os: macos-latest
- build: x86_64-windows
os: windows-latest
- build: aarch64-linux
os: ubuntu-latest
rust: stable
target: aarch64-unknown-linux-gnu
gcc_package: gcc-aarch64-linux-gnu
gcc: aarch64-linux-gnu-gcc
qemu: qemu-aarch64 -L /usr/aarch64-linux-gnu
qemu_target: aarch64-linux-user
steps:
- uses: actions/checkout@v1
with:
submodules: true
- uses: ./.github/actions/install-rust
- uses: ./.github/actions/binary-compatible-builds
if: matrix.target == ''

- name: Install cross-compilation tools
run: |
set -ex
sudo apt-get update
sudo apt-get install -y ${{ matrix.gcc_package }}
# Download and build qemu from source since the most recent release is
# way faster at arm emulation than the current version github actions'
# ubuntu image uses. Disable as much as we can to get it to build
# quickly.
curl https://download.qemu.org/qemu-4.2.0.tar.xz | tar xJf -
cd qemu-4.2.0
./configure --target-list=${{ matrix.qemu_target }} --prefix=$HOME/qemu --disable-tools --disable-slirp --disable-fdt --disable-capstone --disable-docs
make -j$(nproc) install
# Configure Cargo for cross compilation and tell it how it can run
# cross executables
upcase=$(echo ${{ matrix.target }} | awk '{ print toupper($0) }' | sed 's/-/_/g')
echo ::set-env name=CARGO_TARGET_${upcase}_RUNNER::$HOME/qemu/bin/${{ matrix.qemu }}
echo ::set-env name=CARGO_TARGET_${upcase}_LINKER::${{ matrix.gcc }}
echo ::set-env name=CARGO_BUILD_TARGET::${{ matrix.target }}
rustup target add ${{ matrix.target }}
if: matrix.target != ''

# Install wasm32-wasi target in order to build wasi-common's integration
# tests
Expand All @@ -287,7 +326,7 @@ jobs:
- run: $CENTOS cargo build --release --manifest-path crates/c-api/Cargo.toml
shell: bash
# Test what we just built
- run: $CENTOS cargo test --features test-programs/test_programs --release --all --exclude lightbeam --exclude wasmtime --exclude wasmtime-c-api --exclude wasmtime-fuzzing
- run: $CENTOS cargo test --features test-programs/test_programs --release --all --exclude lightbeam
shell: bash
env:
RUST_BACKTRACE: 1
Expand All @@ -306,14 +345,18 @@ jobs:

# Move binaries to dist folder
- run: cp target/release/wasmtime dist
if: matrix.os != 'windows-latest'
if: matrix.os != 'windows-latest' && matrix.target == ''
- run: cp target/${{ matrix.target }}/release/wasmtime dist
if: matrix.os != 'windows-latest' && matrix.target != ''
- run: cp target/release/wasmtime.exe dist
shell: bash
if: matrix.os == 'windows-latest'

# Move libwasmtime dylib to dist folder
- run: cp target/release/libwasmtime.{so,a} dist
if: matrix.os == 'ubuntu-latest'
if: matrix.os == 'ubuntu-latest' && matrix.target == ''
- run: cp target/${{ matrix.target }}/release/libwasmtime.{so,a} dist
if: matrix.os == 'ubuntu-latest' && matrix.target != ''
- run: cp target/release/libwasmtime.{dylib,a} dist
if: matrix.os == 'macos-latest'
- run: cp target/release/wasmtime.{dll,lib,dll.lib} dist
Expand All @@ -331,7 +374,7 @@ jobs:
- uses: actions/upload-artifact@v1
with:
name: bins-${{ matrix.os }}
name: bins-${{ matrix.build }}
path: dist

# Consumes all published artifacts from all the previous build steps, creates
Expand Down Expand Up @@ -359,18 +402,22 @@ jobs:
uses: actions/download-artifact@v1
with:
name: doc-api
- name: Download macOS binaries
- name: Download x86_64 macOS binaries
uses: actions/download-artifact@v1
with:
name: bins-x86_64-macos
- name: Download x86_64 Linux binaries
uses: actions/download-artifact@v1
with:
name: bins-macos-latest
- name: Download Linux binaries
name: bins-x86_64-linux
- name: Download AArch64 Linux binaries
uses: actions/download-artifact@v1
with:
name: bins-ubuntu-latest
- name: Download Windows binaries
name: bins-aarch64-linux
- name: Download x86_64 Windows binaries
uses: actions/download-artifact@v1
with:
name: bins-windows-latest
name: bins-x86_64-windows

- name: Assemble gh-pages
run: |
Expand Down Expand Up @@ -402,9 +449,10 @@ jobs:
# Assemble all the build artifacts into tarballs and zip archives.
- name: Assemble tarballs
run: |
./ci/build-tarballs.sh x86_64-linux ubuntu-latest
./ci/build-tarballs.sh x86_64-windows windows-latest .exe
./ci/build-tarballs.sh x86_64-macos macos-latest
./ci/build-tarballs.sh x86_64-linux
./ci/build-tarballs.sh x86_64-windows .exe
./ci/build-tarballs.sh x86_64-macos
./ci/build-tarballs.sh aarch64-linux
# Upload all assembled tarballs as an artifact of the github action run, so
# that way even PRs can inspect the output.
Expand Down
32 changes: 30 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,13 @@ fn write_testsuite_tests(
if ignore(testsuite, &testname, strategy) {
writeln!(out, "#[ignore]")?;
}
writeln!(out, "fn r#{}() -> anyhow::Result<()> {{", &testname)?;
if should_panic(testsuite, &testname) {
writeln!(out, "#[should_panic]")?;
}
writeln!(out, "fn r#{}() {{", &testname)?;
writeln!(
out,
"crate::run_wast(r#\"{}\"#, crate::Strategy::{})",
"crate::run_wast(r#\"{}\"#, crate::Strategy::{}).unwrap();",
path.display(),
strategy
)?;
Expand Down Expand Up @@ -212,3 +215,28 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {

false
}

fn should_panic(testsuite: &str, testname: &str) -> bool {
let target = env::var("TARGET").unwrap();
if !target.contains("aarch64") {
return false;
}
// FIXME(#1521)
match (testsuite, testname) {
("bulk_memory_operations", "data")
| ("bulk_memory_operations", "elem_ref_null")
| ("misc_testsuite", "threads")
| ("multi_value", "type")
| ("spec_testsuite", "comments")
| ("spec_testsuite", "data")
| ("spec_testsuite", "type")
| ("spec_testsuite", "token")
| ("spec_testsuite", "typecheck")
| ("spec_testsuite", "unreached_invalid")
| ("spec_testsuite", "utf8_custom_section_id")
| ("spec_testsuite", "utf8_import_field")
| ("spec_testsuite", "utf8_import_module")
| ("spec_testsuite", "utf8_invalid_encoding") => false,
_ => true,
}
}
4 changes: 2 additions & 2 deletions ci/build-tarballs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
set -ex

platform=$1
src=$2
exe=$3
src=$1
exe=$2

rm -rf tmp
mkdir tmp
Expand Down
1 change: 1 addition & 0 deletions cranelift/filetests/filetests/isa/x86/run-const.clif
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
test run
target x86_64

function %test_compare_i32() -> b1 {
block0:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
test run
set enable_simd
target x86_64

function %icmp_eq_i8x16() -> b8 {
block0:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
test run
set enable_simd
target x86_64

function %fcvt_from_sint() -> b1 {
block0:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
test run
set enable_simd
target x86_64

function %shuffle_different_ssa_values() -> b1 {
block0:
Expand Down
1 change: 1 addition & 0 deletions cranelift/filetests/filetests/isa/x86/simd-vconst-run.clif
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
test run
set enable_simd
target x86_64

function %vconst_syntax() -> b1 {
block0:
Expand Down
1 change: 1 addition & 0 deletions cranelift/filetests/src/function_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ mod test {
use cranelift_reader::{parse_test, ParseOptions};

#[test]
#[cfg_attr(target_arch = "aarch64", should_panic)] // FIXME(#1521)
fn nop() {
let code = String::from(
"
Expand Down
20 changes: 17 additions & 3 deletions cranelift/filetests/src/test_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

use crate::function_runner::FunctionRunner;
use crate::subtest::{Context, SubTest, SubtestResult};
use cranelift_codegen;
use cranelift_codegen::ir;
use cranelift_reader::parse_run_command;
use cranelift_reader::TestCommand;
use log::trace;
use std::borrow::Cow;
use target_lexicon::Architecture;

struct TestRun;

Expand All @@ -32,7 +32,7 @@ impl SubTest for TestRun {
}

fn needs_isa(&self) -> bool {
false
true
}

fn run(&self, func: Cow<ir::Function>, context: &Context) -> SubtestResult<()> {
Expand All @@ -42,8 +42,22 @@ impl SubTest for TestRun {
let command = parse_run_command(trimmed_comment, &func.signature)
.map_err(|e| format!("{}", e))?;
trace!("Parsed run command: {}", command);
// TODO in following changes we will use the parsed command to alter FunctionRunner's behavior.

// If this test requests to run on a completely different
// architecture than the host platform then we skip it entirely,
// since we won't be able to natively execute machine code.
let requested_arch = context.isa.unwrap().triple().architecture;
if requested_arch != Architecture::host() {
return Ok(());
}

// TODO in following changes we will use the parsed command to alter FunctionRunner's behavior.
//
// Note that here we're also explicitly ignoring `context.isa`,
// regardless of what's requested. We want to use the native
// host ISA no matter what here, so the ISA listed in the file
// is only used as a filter to not run into situations like
// running x86_64 code on aarch64 platforms.
let runner =
FunctionRunner::with_host_isa(func.clone().into_owned(), context.flags.clone());
runner.run()?
Expand Down
1 change: 1 addition & 0 deletions cranelift/simplejit/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ fn switch_error() {
}

#[test]
#[cfg_attr(target_arch = "aarch64", should_panic)] // FIXME(#1521)
fn libcall_function() {
let mut module: Module<SimpleJITBackend> =
Module::new(SimpleJITBuilder::new(default_libcall_names()));
Expand Down
1 change: 1 addition & 0 deletions cranelift/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ mod test {
use super::*;

#[test]
#[cfg_attr(target_arch = "aarch64", should_panic)] // FIXME(#1521)
fn nop() {
let code = String::from(
"
Expand Down
1 change: 1 addition & 0 deletions crates/api/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ mod tests {
use tempfile::TempDir;

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn cache_accounts_for_opt_level() -> Result<()> {
let td = TempDir::new()?;
let config_path = td.path().join("config.toml");
Expand Down
5 changes: 5 additions & 0 deletions crates/api/tests/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ fn signatures_match() {
}

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn import_works() -> Result<()> {
static HITS: AtomicUsize = AtomicUsize::new(0);

Expand Down Expand Up @@ -237,6 +238,7 @@ fn get_from_wrapper() {
}

#[test]
#[cfg_attr(target_arch = "aarch64", should_panic)] // FIXME(#1521)
fn get_from_signature() {
let store = Store::default();
let ty = FuncType::new(Box::new([]), Box::new([]));
Expand All @@ -254,6 +256,7 @@ fn get_from_signature() {
}

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn get_from_module() -> anyhow::Result<()> {
let store = Store::default();
let module = Module::new(
Expand Down Expand Up @@ -323,6 +326,7 @@ fn call_wrapped_func() -> Result<()> {
}

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn caller_memory() -> anyhow::Result<()> {
let store = Store::default();
let f = Func::wrap(&store, |c: Caller<'_>| {
Expand Down Expand Up @@ -388,6 +392,7 @@ fn caller_memory() -> anyhow::Result<()> {
}

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn func_write_nothing() -> anyhow::Result<()> {
let store = Store::default();
let ty = FuncType::new(Box::new([]), Box::new([ValType::I32]));
Expand Down
11 changes: 11 additions & 0 deletions crates/api/tests/host-segfault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ fn segfault() -> ! {
}

fn main() {
// Skip this tests if it looks like we're in a cross-compiled situation and
// we're emulating this test for a different platform. In that scenario
// emulators (like QEMU) tend to not report signals the same way and such.
if std::env::vars()
.filter(|(k, _v)| k.starts_with("CARGO_TARGET") && k.ends_with("RUNNER"))
.count()
> 0
{
return;
}

let tests: &[(&str, fn())] = &[
("normal segfault", || segfault()),
("make instance then segfault", || {
Expand Down
1 change: 1 addition & 0 deletions crates/api/tests/import-indexes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use wasmtime::*;

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn same_import_names_still_distinct() -> anyhow::Result<()> {
const WAT: &str = r#"
(module
Expand Down
2 changes: 2 additions & 0 deletions crates/api/tests/import_calling_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::rc::Rc;
use wasmtime::*;

#[test]
#[cfg_attr(target_arch = "aarch64", should_panic)] // FIXME(#1521)
fn test_import_calling_export() {
const WAT: &str = r#"
(module
Expand Down Expand Up @@ -58,6 +59,7 @@ fn test_import_calling_export() {
}

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn test_returns_incorrect_type() -> Result<()> {
const WAT: &str = r#"
(module
Expand Down
1 change: 1 addition & 0 deletions crates/api/tests/invoke_func_via_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use anyhow::{Context as _, Result};
use wasmtime::*;

#[test]
#[cfg_attr(target_arch = "aarch64", ignore)] // FIXME(#1521)
fn test_invoke_func_via_table() -> Result<()> {
let store = Store::default();

Expand Down
Loading

0 comments on commit b376724

Please sign in to comment.