Add cmake compatibility to c-api (#4369)

* Add cmake compatibility to c-api

* Add CMake documentation to wasmtime.h

* Add CMake instructions in examples

* Modify CI for CMake support

* Use correct rust in CI

* Trigger build

* Refactor run-examples

* Reintroduce example_to_run in run-examples

* Replace run-examples crate with cmake

* Fix markdown formatting in examples readme

* Fix cmake test quotes

* Build rust wasm before cmake tests

* Pass CTEST_OUTPUT_ON_FAILURE

* Another cmake test

* Handle os differences in cmake test

* Fix bugs in memory and multimemory examples
This commit is contained in:
TheGreatRambler
2022-07-22 11:22:36 -06:00
committed by GitHub
parent 35b750ab9a
commit 2ba3025e67
25 changed files with 244 additions and 161 deletions

View File

@@ -273,11 +273,21 @@ jobs:
touch ${{ runner.tool_cache }}/qemu/built touch ${{ runner.tool_cache }}/qemu/built
if: matrix.gcc != '' if: matrix.gcc != ''
# Ensure all our examples build and execute # Prepare tests in CMake
- run: cargo run -p run-examples - run: cmake -Sexamples -Bexamples/build -DBUILD_SHARED_LIBS=OFF
if: matrix.target == ''
# Build tests
- run: cmake --build examples/build --config Debug
if: matrix.target == ''
# Run tests
- run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target RUN_TESTS
env: env:
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
if: matrix.target == '' if: matrix.target == '' && matrix.os == 'windows-2019'
- run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target test
env:
RUST_BACKTRACE: 1
if: matrix.target == '' && matrix.os != 'windows-2019'
# Build and test all features # Build and test all features
- run: ./ci/run-tests.sh --locked - run: ./ci/run-tests.sh --locked

1
.gitignore vendored
View File

@@ -19,3 +19,4 @@ foo
.cargo .cargo
publish publish
vendor vendor
examples/build

8
Cargo.lock generated
View File

@@ -2439,14 +2439,6 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "run-examples"
version = "0.19.0"
dependencies = [
"anyhow",
"cc",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.21" version = "0.1.21"

View File

@@ -81,7 +81,6 @@ members = [
"crates/bench-api", "crates/bench-api",
"crates/c-api", "crates/c-api",
"crates/cli-flags", "crates/cli-flags",
"crates/misc/run-examples",
"examples/fib-debug/wasm", "examples/fib-debug/wasm",
"examples/wasi/wasm", "examples/wasi/wasm",
"examples/tokio/wasm", "examples/tokio/wasm",

View File

@@ -111,7 +111,7 @@ You can use Wasmtime from a variety of different languages through embeddings of
the implementation: the implementation:
* **[Rust]** - the [`wasmtime` crate] * **[Rust]** - the [`wasmtime` crate]
* **[C]** - the [`wasm.h`, `wasi.h`, and `wasmtime.h` headers][c-headers] or use [`wasmtime` Conan package] * **[C]** - the [`wasm.h`, `wasi.h`, and `wasmtime.h` headers][c-headers], [CMake](crates/c-api/CMakeLists.txt) or [`wasmtime` Conan package]
* **C++** - the [`wasmtime-cpp` repository][wasmtime-cpp] or use [`wasmtime-cpp` Conan package] * **C++** - the [`wasmtime-cpp` repository][wasmtime-cpp] or use [`wasmtime-cpp` Conan package]
* **[Python]** - the [`wasmtime` PyPI package] * **[Python]** - the [`wasmtime` PyPI package]
* **[.NET]** - the [`Wasmtime` NuGet package] * **[.NET]** - the [`Wasmtime` NuGet package]

View File

@@ -0,0 +1,64 @@
cmake_minimum_required(VERSION 3.10)
option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(WASMTIME_BUILD_TYPE_FLAG "--release")
set(WASMTIME_BUILD_TYPE "release")
else()
set(WASMTIME_BUILD_TYPE "debug")
endif()
if (BUILD_SHARED_LIBS)
# Copy shared library into build directory
if(WIN32)
set(WASMTIME_INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/wasmtime.dll
${CMAKE_BINARY_DIR})
elseif(APPLE)
set(WASMTIME_INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/libwasmtime.dylib
${CMAKE_BINARY_DIR})
else()
set(WASMTIME_INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/libwasmtime.so
${CMAKE_BINARY_DIR})
endif()
endif()
include(ExternalProject)
ExternalProject_Add(
wasmtime-crate
DOWNLOAD_COMMAND ""
CONFIGURE_COMMAND ""
INSTALL_COMMAND "${WASMTIME_INSTALL_COMMAND}"
BUILD_COMMAND cargo build ${WASMTIME_BUILD_TYPE_FLAG}
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}
BUILD_ALWAYS ON)
add_library(wasmtime INTERFACE)
add_dependencies(wasmtime wasmtime-crate)
if (BUILD_SHARED_LIBS)
if(WIN32)
target_link_libraries(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/wasmtime.dll.lib)
elseif(APPLE)
target_link_libraries(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/libwasmtime.dylib)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
else()
target_link_libraries(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/libwasmtime.so)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
endif()
else()
if(WIN32)
target_compile_options(wasmtime INTERFACE -DWASM_API_EXTERN= -DWASI_API_EXTERN=)
target_link_libraries(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/wasmtime.lib
ws2_32 advapi32 userenv ntdll shell32 ole32 bcrypt)
elseif(APPLE)
target_link_libraries(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/libwasmtime.a)
else()
target_link_libraries(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_BUILD_TYPE}/libwasmtime.a
pthread dl m)
endif()
endif()
target_include_directories(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/include)

View File

@@ -28,6 +28,22 @@
* as a `lib` directory with both a static archive and a dynamic library of * as a `lib` directory with both a static archive and a dynamic library of
* Wasmtime. You can link to either of them as you see fit. * Wasmtime. You can link to either of them as you see fit.
* *
* ## Installing the C API through CMake
*
* CMake can be used to make the process of linking and compiling easier. An
* example of this if you have wasmtime as a git submodule at
* `third_party/wasmtime`:
* ```
* add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/wasmtime/crates/c-api
* ${CMAKE_CURRENT_BINARY_DIR}/wasmtime)
* ...
* target_include_directories(YourProject PUBLIC wasmtime)
* target_link_libraries(YourProject PUBLIC wasmtime)
* ```
* `BUILD_SHARED_LIBS` is provided as a define if you would like to build a
* shared library instead. You must distribute the appropriate shared library
* for your platform if you do this.
*
* ## Linking against the C API * ## Linking against the C API
* *
* You'll want to arrange the `include` directory of the C API to be in your * You'll want to arrange the `include` directory of the C API to be in your
@@ -166,8 +182,8 @@
#include <wasi.h> #include <wasi.h>
#include <wasmtime/config.h> #include <wasmtime/config.h>
#include <wasmtime/error.h>
#include <wasmtime/engine.h> #include <wasmtime/engine.h>
#include <wasmtime/error.h>
#include <wasmtime/extern.h> #include <wasmtime/extern.h>
#include <wasmtime/func.h> #include <wasmtime/func.h>
#include <wasmtime/global.h> #include <wasmtime/global.h>

View File

@@ -1,10 +0,0 @@
[package]
name = "run-examples"
version = "0.19.0"
authors = ["The Wasmtime Project Developers"]
edition = "2021"
publish = false
[dependencies]
anyhow = "1.0.31"
cc = "1.0"

View File

@@ -1,7 +0,0 @@
fn main() {
println!(
"cargo:rustc-env=TARGET={}",
std::env::var("TARGET").unwrap()
);
println!("cargo:rerun-if-changed=build.rs");
}

View File

@@ -1,121 +0,0 @@
use anyhow::Context;
use std::collections::BTreeSet;
use std::process::Command;
fn main() -> anyhow::Result<()> {
let example_to_run = std::env::args().nth(1);
let mut examples = BTreeSet::new();
for e in std::fs::read_dir("examples")? {
let e = e?;
let path = e.path();
let dir = e.metadata()?.is_dir();
if let Some("wat") = path.extension().and_then(|s| s.to_str()) {
continue;
}
examples.insert((path.file_stem().unwrap().to_str().unwrap().to_owned(), dir));
}
println!("======== Building libwasmtime.a ===========");
run(Command::new("cargo")
.args(&["build"])
.current_dir("crates/c-api"))?;
for (example, is_dir) in examples {
if example == "README" {
continue;
}
if let Some(example_to_run) = &example_to_run {
if !example.contains(&example_to_run[..]) {
continue;
}
}
if is_dir {
println!("======== Rust wasm file `{}` ============", example);
let target = if example == "fib-debug" {
"wasm32-unknown-unknown"
} else {
"wasm32-wasi"
};
run(Command::new("cargo")
.arg("build")
.arg("-p")
.arg(format!("example-{}-wasm", example))
.arg("--target")
.arg(target))?;
}
println!("======== Rust example `{}` ============", example);
let mut cargo_cmd = Command::new("cargo");
cargo_cmd.arg("run").arg("--example").arg(&example);
if example.contains("tokio") {
cargo_cmd.arg("--features").arg("wasmtime-wasi/tokio");
}
run(&mut cargo_cmd)?;
println!("======== C/C++ example `{}` ============", example);
for extension in ["c", "cc"].iter() {
let mut cmd = cc::Build::new()
.opt_level(0)
.cargo_metadata(false)
.target(env!("TARGET"))
.host(env!("TARGET"))
.include("crates/c-api/include")
.include("crates/c-api/wasm-c-api/include")
.define("WASM_API_EXTERN", Some("")) // static linkage, not dynamic
.warnings(false)
.get_compiler()
.to_command();
let file = if is_dir {
format!("examples/{}/main.{}", example, extension)
} else {
format!("examples/{}.{}", example, extension)
};
if !std::path::Path::new(&file).exists() {
// C and C++ files are optional so we can skip them.
continue;
}
cmd.arg(file);
let exe = if cfg!(windows) {
cmd.arg("target/debug/wasmtime.lib")
.arg("ws2_32.lib")
.arg("advapi32.lib")
.arg("userenv.lib")
.arg("ntdll.lib")
.arg("shell32.lib")
.arg("ole32.lib")
.arg("bcrypt.lib");
if is_dir {
"./main.exe".to_string()
} else {
format!("./{}.exe", example)
}
} else {
cmd.arg("target/debug/libwasmtime.a").arg("-o").arg("foo");
"./foo".to_string()
};
if cfg!(target_os = "linux") {
cmd.arg("-lpthread").arg("-ldl").arg("-lm");
}
run(&mut cmd)?;
run(&mut Command::new(exe))?;
}
}
Ok(())
}
fn run(cmd: &mut Command) -> anyhow::Result<()> {
(|| -> anyhow::Result<()> {
let s = cmd.status()?;
if !s.success() {
anyhow::bail!("Exited with failure status: {}", s);
}
Ok(())
})()
.with_context(|| format!("failed to run `{:?}`", cmd))
}

73
examples/CMakeLists.txt Normal file
View File

@@ -0,0 +1,73 @@
cmake_minimum_required(VERSION 3.10)
project(wasmtime-examples)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../crates/c-api ${CMAKE_CURRENT_BINARY_DIR}/wasmtime)
function(CREATE_TARGET TARGET TARGET_PATH)
add_executable(wasmtime-${TARGET} ${TARGET_PATH})
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(wasmtime-${TARGET} PRIVATE -Wall -Wextra -Wno-deprecated-declarations)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(wasmtime-${TARGET} PRIVATE /W3)
endif()
set_target_properties(wasmtime-${TARGET} PROPERTIES
OUTPUT_NAME wasmtime-${TARGET}
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/$<0:>
CXX_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE ON)
target_include_directories(wasmtime-${TARGET} PUBLIC wasmtime)
target_link_libraries(wasmtime-${TARGET} PUBLIC wasmtime)
add_test(NAME ${TARGET}-c COMMAND $<TARGET_FILE:wasmtime-${TARGET}> WORKING_DIRECTORY ../..)
endfunction()
function(CREATE_RUST_TEST EXAMPLE)
if(ARGC GREATER 1)
add_test(NAME ${EXAMPLE}-rust COMMAND cargo run --example ${EXAMPLE} --features ${ARGV1} WORKING_DIRECTORY ../..)
else()
add_test(NAME ${EXAMPLE}-rust COMMAND cargo run --example ${EXAMPLE} WORKING_DIRECTORY ../..)
endif()
endfunction()
function(CREATE_RUST_WASM EXAMPLE TARGET)
execute_process(COMMAND cargo build -p example-${EXAMPLE}-wasm --target ${TARGET})
endfunction()
# Enable testing
enable_testing()
# Add all examples
create_target(externref externref.c)
create_target(fib-debug fib-debug/main.c)
create_target(fuel fuel.c)
create_target(gcd gcd.c)
create_target(hello hello.c)
create_target(interrupt interrupt.c)
create_target(linking linking.c)
create_target(memory memory.c)
create_target(multi multi.c)
create_target(multimemory multimemory.c)
create_target(serialize serialize.c)
create_target(threads threads.c)
create_target(wasi wasi/main.c)
# Add rust tests
create_rust_wasm(fib-debug wasm32-unknown-unknown)
create_rust_wasm(tokio wasm32-wasi)
create_rust_wasm(wasi wasm32-wasi)
create_rust_test(epochs)
create_rust_test(externref)
create_rust_test(fib-debug)
create_rust_test(fuel)
create_rust_test(gcd)
create_rust_test(hello)
create_rust_test(interrupt)
create_rust_test(linking)
create_rust_test(memory)
create_rust_test(multi)
create_rust_test(multimemory)
create_rust_test(serialize)
create_rust_test(threads)
create_rust_test(wasi)
create_rust_test(tokio wasmtime-wasi/tokio)

View File

@@ -8,7 +8,10 @@ Each example is available in both C and in Rust. Examples are accompanied with a
`*.wat` file which is the wasm input, or a Rust project in a `wasm` folder which `*.wat` file which is the wasm input, or a Rust project in a `wasm` folder which
is the source code for the original wasm file. is the source code for the original wasm file.
Rust examples can be executed with `cargo run --example $name`, and C examples Rust examples can be executed with `cargo run --example $name`. C examples can
need to be compiled using your system compiler and appropriate header files. be built with `mkdir build && cd build && cmake ..`. You can run
`cmake --build .` to build all examples or
`cmake --build . --target wasmtime-$name`, replacing the name as you wish. They
can also be [built manually](https://docs.wasmtime.dev/c-api/).
For more information see the examples themselves! For more information see the examples themselves!

View File

@@ -15,6 +15,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations as well as the name of the to tweak the `-lpthread` and such annotations as well as the name of the
`libwasmtime.a` file on Windows. `libwasmtime.a` file on Windows.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-externref
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -15,6 +15,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-fuel
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -15,6 +15,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-gcd
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -16,6 +16,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations as well as the name of the to tweak the `-lpthread` and such annotations as well as the name of the
`libwasmtime.a` file on Windows. `libwasmtime.a` file on Windows.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-hello
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -16,6 +16,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations as well as the name of the to tweak the `-lpthread` and such annotations as well as the name of the
`libwasmtime.a` file on Windows. `libwasmtime.a` file on Windows.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-interrupt
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -15,6 +15,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-linking
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -16,6 +16,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-memory
Also note that this example was taken from Also note that this example was taken from
https://github.com/WebAssembly/wasm-c-api/blob/master/example/memory.c https://github.com/WebAssembly/wasm-c-api/blob/master/example/memory.c
originally originally
@@ -220,7 +224,7 @@ int main(int argc, const char* argv[]) {
// Grow memory. // Grow memory.
printf("Growing memory...\n"); printf("Growing memory...\n");
uint32_t old_size; uint64_t old_size;
error = wasmtime_memory_grow(context, &memory, 1, &old_size); error = wasmtime_memory_grow(context, &memory, 1, &old_size);
if (error != NULL) if (error != NULL)
exit_with_error("failed to grow memory", error, trap); exit_with_error("failed to grow memory", error, trap);

View File

@@ -16,6 +16,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-multi
Also note that this example was taken from Also note that this example was taken from
https://github.com/WebAssembly/wasm-c-api/blob/master/example/multi.c https://github.com/WebAssembly/wasm-c-api/blob/master/example/multi.c
originally originally

View File

@@ -14,6 +14,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-multimemory
*/ */
#include <inttypes.h> #include <inttypes.h>
@@ -264,7 +268,7 @@ int main(int argc, const char* argv[]) {
// Grow memory. // Grow memory.
printf("Growing memory...\n"); printf("Growing memory...\n");
uint32_t old_size; uint64_t old_size;
error = wasmtime_memory_grow(context, &memory0, 1, &old_size); error = wasmtime_memory_grow(context, &memory0, 1, &old_size);
if (error != NULL) if (error != NULL)
exit_with_error("failed to grow memory", error, trap); exit_with_error("failed to grow memory", error, trap);

View File

@@ -16,6 +16,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations as well as the name of the to tweak the `-lpthread` and such annotations as well as the name of the
`libwasmtime.a` file on Windows. `libwasmtime.a` file on Windows.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-serialize
*/ */
#include <assert.h> #include <assert.h>

View File

@@ -1,3 +1,27 @@
/*
Example of instantiating of the WebAssembly module and invoking its exported
function in a separate thread.
You can compile and run this example on Linux with:
cargo build --release -p wasmtime-c-api
cc examples/threads.c \
-I crates/c-api/include \
-I crates/c-api/wasm-c-api/include \
target/release/libwasmtime.a \
-lpthread -ldl -lm \
-o threads
./threads
Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations as well as the name of the
`libwasmtime.a` file on Windows.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-threads
*/
#ifndef _WIN32 #ifndef _WIN32
#include <inttypes.h> #include <inttypes.h>

View File

@@ -1,5 +0,0 @@
int main(int argc, char *argv[]) {
// This example is specific to integrating with Rust's tokio ecosystem, so
// it isnt applicable to C/C++.
return 0;
}

View File

@@ -14,6 +14,10 @@ You can compile and run this example on Linux with:
Note that on Windows and macOS the command will be similar, but you'll need Note that on Windows and macOS the command will be similar, but you'll need
to tweak the `-lpthread` and such annotations. to tweak the `-lpthread` and such annotations.
You can also build using cmake:
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-wasi
*/ */
#include <assert.h> #include <assert.h>