Skip to content

Commit

Permalink
Merge #2072
Browse files Browse the repository at this point in the history
2072: feat(c-api) Implement cross-compilation API in C r=Hywan a=Hywan

# Description

Depends on #2071 (merged).

This patch implements `wasm_target_t`, `wasm_triple_t`, `wasm_cpu_features_t`.

This patch also implements `wasm_config_set_target` to set… a `wasm_target_t`. The `wasm_config_new_with_engine` function has been updated to handle the new `wasm_target_t`.

# Example

```c
int main() {
    // Create the configuration.
    wasm_config_t* config = wasm_config_new();

    // Set the target.
    {
      // Declare the target triple.
      wasm_triple_t* triple;
  
      {
          wasm_name_t triple_name;
          wasm_name_new_from_string(&triple_name, "x86_64-apple-darwin");
  
          triple = wasm_triple_new(&triple_name);
  
          wasm_name_delete(&triple_name);
      }
  
      assert(triple);
  
      // Declare the target CPU features.
      wasm_cpu_features_t* cpu_features = wasm_cpu_features_new();
  
      {
          wasm_name_t cpu_feature_name;
          wasm_name_new_from_string(&cpu_feature_name, "sse2");
  
          wasm_cpu_features_add(cpu_features, &cpu_feature_name);
  
          wasm_name_delete(&cpu_feature_name);
      }
  
      assert(cpu_features);
  
      // Create the target!
      wasm_target_t* target = wasm_target_new(triple, cpu_features);
      assert(target);
  
      // Set the target onto the configuration!
      wasm_config_set_target(config, target);
    }

    // Create the engine.
    wasm_engine_t* engine = wasm_engine_new_with_config(config);

    // Check we have an engine!
    assert(engine);

    // Free everything.
    wasm_engine_delete(engine);

    return 0;
}
```

# Review

- [x] Add a short description of the the change to the CHANGELOG.md file


Co-authored-by: Ivan Enderlin <[email protected]>
  • Loading branch information
bors[bot] and Hywan authored Feb 2, 2021
2 parents c4c7b2b + 4725a5d commit 63acc46
Show file tree
Hide file tree
Showing 11 changed files with 459 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
## **[Unreleased]**

### Added
- [#2072](https://github.com/wasmerio/wasmer/pull/2072) Add `wasm_config_set_target`, along with `wasm_target_t`, `wasm_triple_t` and `wasm_cpu_features_t` in the unstable C API.
- [#2059](https://github.com/wasmerio/wasmer/pull/2059) Ability to capture `stdout` and `stderr` with WASI in the C API.
- [#2040](https://github.com/wasmerio/wasmer/pull/2040) Add `InstanceHandle::vmoffsets` to expose the offsets of the `vmctx` region.
- [#2026](https://github.com/wasmerio/wasmer/pull/2010) Expose trap code of a `RuntimeError`, if it's a `Trap`.
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/c-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ wasmer-engine-native = { version = "1.0.1", path = "../engine-native", optional
wasmer-engine-object-file = { version = "1.0.1", path = "../engine-object-file", optional = true }
wasmer-wasi = { version = "1.0.1", path = "../wasi", optional = true }
wasmer-types = { version = "1.0.1", path = "../wasmer-types" }
enumset = "1.0"
cfg-if = "1.0"
lazy_static = "1.4"
libc = { version = "^0.2", default-features = false }
Expand Down
12 changes: 12 additions & 0 deletions lib/c-api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,20 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder {
.exclude_item("wasi_version_t")
.exclude_item("wasm_config_set_compiler")
.exclude_item("wasm_config_set_engine")
.exclude_item("wasm_config_set_target")
.exclude_item("wasm_cpu_features_add")
.exclude_item("wasm_cpu_features_delete")
.exclude_item("wasm_cpu_features_new")
.exclude_item("wasm_cpu_features_t")
.exclude_item("wasm_module_name")
.exclude_item("wasm_module_set_name")
.exclude_item("wasm_target_delete")
.exclude_item("wasm_target_new")
.exclude_item("wasm_target_t")
.exclude_item("wasm_triple_delete")
.exclude_item("wasm_triple_new")
.exclude_item("wasm_triple_new_from_host")
.exclude_item("wasm_triple_t")
.exclude_item("wasmer_compiler_t")
.exclude_item("wasmer_engine_t")
.exclude_item("wat2wasm")
Expand Down
57 changes: 49 additions & 8 deletions lib/c-api/src/wasm_c_api/engine.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub use super::unstable::engine::wasm_config_set_target;
use super::unstable::target_lexicon::wasm_target_t;
use crate::error::{update_last_error, CApiError};
use cfg_if::cfg_if;
use std::sync::Arc;
Expand Down Expand Up @@ -93,6 +95,7 @@ pub struct wasm_config_t {
engine: wasmer_engine_t,
#[cfg(feature = "compiler")]
compiler: wasmer_compiler_t,
pub(super) target: Option<Box<wasm_target_t>>,
}

/// Create a new default Wasmer configuration.
Expand Down Expand Up @@ -396,7 +399,7 @@ pub unsafe extern "C" fn wasm_engine_delete(_engine: Option<Box<wasm_engine_t>>)
/// cbindgen:ignore
#[no_mangle]
pub extern "C" fn wasm_engine_new_with_config(
config: Box<wasm_config_t>,
config: Option<Box<wasm_config_t>>,
) -> Option<Box<wasm_engine_t>> {
#[allow(dead_code)]
fn return_with_error<M>(msg: M) -> Option<Box<wasm_engine_t>>
Expand All @@ -408,7 +411,9 @@ pub extern "C" fn wasm_engine_new_with_config(
});

return None;
};
}

let config = config?;

cfg_if! {
if #[cfg(feature = "compiler")] {
Expand Down Expand Up @@ -447,7 +452,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::JIT => {
cfg_if! {
if #[cfg(feature = "jit")] {
Arc::new(JIT::new(compiler_config).engine())
let mut builder = JIT::new(compiler_config);

if let Some(target) = config.target {
builder = builder.target(target.inner);
}

Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `jit` feature.");
}
Expand All @@ -456,7 +467,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::NATIVE => {
cfg_if! {
if #[cfg(feature = "native")] {
Arc::new(Native::new(compiler_config).engine())
let mut builder = Native::new(compiler_config);

if let Some(target) = config.target {
builder = builder.target(target.inner);
}

Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `native` feature.");
}
Expand All @@ -467,7 +484,13 @@ pub extern "C" fn wasm_engine_new_with_config(
// There are currently no uses of the object-file engine + compiler from the C API.
// So we run in headless mode.
if #[cfg(feature = "object-file")] {
Arc::new(ObjectFile::headless().engine())
let mut builder = ObjectFile::headless();

if let Some(target) = config.target {
builder = builder.target(target.inner);
}

Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `object-file` feature.");
}
Expand All @@ -480,7 +503,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::JIT => {
cfg_if! {
if #[cfg(feature = "jit")] {
Arc::new(JIT::headless().engine())
let mut builder = JIT::headless();

if let Some(target) = config.target {
builder = builder.target(target.inner);
}

Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `jit` feature.");
}
Expand All @@ -489,7 +518,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::NATIVE => {
cfg_if! {
if #[cfg(feature = "native")] {
Arc::new(Native::headless().engine())
let mut builder = Native::headless();

if let Some(target) = config.target {
builder = builder.target(target.inner);
}

Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `native` feature.");
}
Expand All @@ -498,7 +533,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::OBJECT_FILE => {
cfg_if! {
if #[cfg(feature = "object-file")] {
Arc::new(ObjectFile::headless().engine())
let mut builder = ObjectFile::headless();

if let Some(target) = config.target {
builder = builder.target(target.inner);
}

Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `object-file` feature.");
}
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/externals/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
struct WrapperEnv {
env: *mut c_void,
finalizer: Arc<Option<wasm_env_finalizer_t>>,
};
}

// Only relevant when using multiple threads in the C API;
// Synchronization will be done via the C API / on the C side.
Expand Down
7 changes: 5 additions & 2 deletions lib/c-api/src/wasm_c_api/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,16 +467,19 @@ macro_rules! wasm_declare_own {

#[macro_export]
macro_rules! c_try {
($expr:expr) => {{
($expr:expr; otherwise $return:expr) => {{
let res: Result<_, _> = $expr;
match res {
Ok(val) => val,
Err(err) => {
crate::error::update_last_error(err);
return None;
return $return;
}
}
}};
($expr:expr) => {{
c_try!($expr; otherwise None)
}};
($expr:expr, $e:expr) => {{
let opt: Option<_> = $expr;
c_try!(opt.ok_or_else(|| $e))
Expand Down
49 changes: 49 additions & 0 deletions lib/c-api/src/wasm_c_api/unstable/engine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Unstable non-standard Wasmer-specific types for the
//! `wasm_engine_t` and siblings.
use super::super::engine::wasm_config_t;
use super::target_lexicon::wasm_target_t;

/// Unstable non-standard Wasmer-specific API to update the
/// configuration to specify a particular target for the engine.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Create the configuration.
/// wasm_config_t* config = wasm_config_new();
///
/// // Set the target.
/// {
/// wasm_triple_t* triple = wasm_triple_new_from_host();
/// wasm_cpu_features_t* cpu_features = wasm_cpu_features_new();
/// wasm_target_t* target = wasm_target_new(triple, cpu_features);
///
/// wasm_config_set_target(config, target);
/// }
///
/// // Create the engine.
/// wasm_engine_t* engine = wasm_engine_new_with_config(config);
///
/// // Check we have an engine!
/// assert(engine);
///
/// // Free everything.
/// wasm_engine_delete(engine);
///
/// return 0;
/// }
/// # })
/// # .success();
/// # }
/// ```
#[no_mangle]
pub extern "C" fn wasm_config_set_target(config: &mut wasm_config_t, target: Box<wasm_target_t>) {
config.target = Some(target);
}
2 changes: 2 additions & 0 deletions lib/c-api/src/wasm_c_api/unstable/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub mod engine;
pub mod module;
pub mod target_lexicon;
Loading

0 comments on commit 63acc46

Please sign in to comment.