* Add AArch64 tests to CI 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. * Review comments
149 lines
4.3 KiB
Rust
149 lines
4.3 KiB
Rust
use std::env;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
use std::process::Command;
|
|
use std::sync::Once;
|
|
|
|
fn run_c_example(name: &'static str, expected_out: &str) {
|
|
// Windows requires different `cc` flags and I'm not sure what they
|
|
// are. Also we need a way to shepherd the current host target to the `cc`
|
|
// invocation but `cargo` only defines the `TARGET` environment variable for
|
|
// build scripts, not tests. Therefore, we just make these tests specific to
|
|
// bog standard x64 linux. This should run in CI, at least!
|
|
if cfg!(not(all(
|
|
target_arch = "x86_64",
|
|
target_os = "linux",
|
|
target_env = "gnu"
|
|
))) {
|
|
eprintln!("This test is only enabled for the `x86_64-unknown-linux-gnu` target");
|
|
return;
|
|
}
|
|
|
|
let pkg_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
|
|
|
// Make sure we've built `libwasmtime.a` with the `wat` feature enabled
|
|
// so that we have the `wasmtime_wat2wasm` function.
|
|
static BUILD_LIBWASMTIME: Once = Once::new();
|
|
BUILD_LIBWASMTIME.call_once(|| {
|
|
let status = Command::new("cargo")
|
|
.args(&["build", "-p", "wasmtime-c-api", "--features", "wat"])
|
|
.current_dir(pkg_dir)
|
|
.status()
|
|
.expect("should run `cargo build` OK");
|
|
assert!(status.success());
|
|
});
|
|
|
|
let examples_dir = pkg_dir
|
|
// Pop `c-api`.
|
|
.join("..")
|
|
// Pop `crates`.
|
|
.join("..")
|
|
.join("examples");
|
|
let include_dir = pkg_dir.join("include");
|
|
let wasm_c_api_include_dir = pkg_dir.join("wasm-c-api").join("include");
|
|
let out_dir = pkg_dir.join("..").join("..").join("target").join("debug");
|
|
let c_examples_dir = out_dir.join("c-examples");
|
|
fs::create_dir_all(&c_examples_dir).unwrap();
|
|
let libwasmtime = out_dir.join("libwasmtime.a");
|
|
assert!(libwasmtime.exists());
|
|
|
|
let status = Command::new(env::var("CC").unwrap_or("gcc".into()))
|
|
.arg(examples_dir.join(name).with_extension("c"))
|
|
.arg(libwasmtime)
|
|
.arg(format!("-I{}", include_dir.display()))
|
|
.arg(format!("-I{}", wasm_c_api_include_dir.display()))
|
|
.arg("-lpthread")
|
|
.arg("-ldl")
|
|
.arg("-lm")
|
|
.arg("-lrt")
|
|
.current_dir(&examples_dir)
|
|
.arg("-o")
|
|
.arg(c_examples_dir.join(name))
|
|
.status()
|
|
.expect("should spawn CC ok");
|
|
assert!(status.success());
|
|
assert!(c_examples_dir.join(name).exists());
|
|
|
|
let output = Command::new(c_examples_dir.join(name))
|
|
.current_dir(pkg_dir.join("..").join(".."))
|
|
.output()
|
|
.expect("should spawn C example OK");
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"failed to execute the C example '{}': {}",
|
|
name,
|
|
String::from_utf8_lossy(&output.stderr),
|
|
);
|
|
|
|
let actual_stdout =
|
|
String::from_utf8(output.stdout).expect("C example's output should be utf-8");
|
|
assert_eq!(
|
|
actual_stdout, expected_out,
|
|
"unexpected stdout from example",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_hello_example() {
|
|
run_c_example(
|
|
"hello",
|
|
"Initializing...\n\
|
|
Compiling module...\n\
|
|
Creating callback...\n\
|
|
Instantiating module...\n\
|
|
Extracting export...\n\
|
|
Calling export...\n\
|
|
Calling back...\n\
|
|
> Hello World!\n\
|
|
All finished!\n",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_memory_example() {
|
|
run_c_example(
|
|
"memory",
|
|
"Initializing...\n\
|
|
Compiling module...\n\
|
|
Instantiating module...\n\
|
|
Extracting exports...\n\
|
|
Checking memory...\n\
|
|
Mutating memory...\n\
|
|
Growing memory...\n\
|
|
Creating stand-alone memory...\n\
|
|
Shutting down...\n\
|
|
Done.\n",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_linking_example() {
|
|
run_c_example("linking", "Hello, world!\n");
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_multi_example() {
|
|
run_c_example(
|
|
"multi",
|
|
"Initializing...\n\
|
|
Compiling module...\n\
|
|
Creating callback...\n\
|
|
Instantiating module...\n\
|
|
Extracting export...\n\
|
|
Calling export...\n\
|
|
Calling back...\n\
|
|
> 1 2\n\
|
|
\n\
|
|
Printing result...\n\
|
|
> 2 1\n\
|
|
Shutting down...\n\
|
|
Done.\n",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_gcd_example() {
|
|
run_c_example("gcd", "gcd(6, 27) = 3\n");
|
|
}
|