Skip to content

Commit

Permalink
Merge #1916
Browse files Browse the repository at this point in the history
1916: feat(c-api) Add the `WASMER_VERSION*` constants, and the `wasmer_version*` functions r=Hywan a=Hywan

Fix #1534.

# Description

~This PR adds the `wasmer_version`. It compute a string based on the `CARGO_PKG_VERSION` environment variable value at compile-time. I know an enum could be better, but it's a start.~

This PR adds 4 C constants:

```c
#define WASMER_VERSION "1.0.0-beta1"
#define WASMER_VERSION_MAJOR 1
#define WASMER_VERSION_MINOR 0
#define WASMER_VERSION_PATCH 0
#define WASMER_VERSION_PRE "beta1"
```

Thay way, the user can query the version of Wasmer more easily.

In addition, it adds 4 functions (when the header files aren't accessible):

```c
const char* wasmer_version(void);
uint8_t wasmer_version_major(void);
uint8_t wasmer_version_minor(void);
uint8_t wasmer_version_patch(void);
const char* wasmer_version_pre(void);
```

# 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 Dec 14, 2020
2 parents 17752cd + 110c6aa commit 35e0021
Show file tree
Hide file tree
Showing 7 changed files with 564 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

### Added

* [#1916](https://github.com/wasmerio/wasmer/pull/1916) Add the `WASMER_VERSION*` constants with the `wasmer_version*` functions in the Wasmer C API
* [#1867](https://github.com/wasmerio/wasmer/pull/1867) Added `Metering::get_remaining_points` and `Metering::set_remaining_points`
* [#1881](https://github.com/wasmerio/wasmer/pull/1881) Added `UnsupportedTarget` error to `CompileError`
* [#1908](https://github.com/wasmerio/wasmer/pull/1908) Implemented `TryFrom<Value<T>>` for `i32`/`u32`/`i64`/`u64`/`f32`/`f64`
Expand Down
35 changes: 29 additions & 6 deletions lib/c-api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) {
r#"// The Wasmer C/C++ header file compatible with the `wasm-c-api` standard API.
// This file is generated by lib/c-api/build.rs.
#if !defined(WASMER_WASM_H_MACROS)
#if !defined(WASMER_WASM_H_PRELUDE)
#define WASMER_WASM_H_MACROS
#define WASMER_WASM_H_PRELUDE
{pre_header}"#,
pre_header = PRE_HEADER
);
Expand All @@ -88,10 +88,12 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) {
map_feature_as_c_define!("wasi", WASI_FEATURE_AS_C_DEFINE, pre_header);
map_feature_as_c_define!("emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE, pre_header);

add_wasmer_version(&mut pre_header);

// Close pre header.
pre_header.push_str(
r#"
#endif // WASMER_WASM_H_MACROS
#endif // WASMER_WASM_H_PRELUDE
//
Expand Down Expand Up @@ -134,19 +136,22 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) {
let mut pre_header = format!(
r#"// The Wasmer C/C++ header file.
#if !defined(WASMER_H_MACROS)
#if !defined(WASMER_H_PRELUDE)
#define WASMER_H_MACROS
#define WASMER_H_PRELUDE
{pre_header}"#,
pre_header = PRE_HEADER
);

map_feature_as_c_define!("wasi", WASI_FEATURE_AS_C_DEFINE, pre_header);
map_feature_as_c_define!("emscritpen", EMSCRIPTEN_FEATURE_AS_C_DEFINE, pre_header);

add_wasmer_version(&mut pre_header);

// Close pre header.
pre_header.push_str(
r#"#endif // WASMER_H_MACROS
r#"
#endif // WASMER_H_PRELUDE
//
Expand Down Expand Up @@ -196,6 +201,24 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) {
}
}

fn add_wasmer_version(pre_header: &mut String) {
pre_header.push_str(&format!(
r#"
// This file corresponds to the following Wasmer version.
#define WASMER_VERSION "{full}"
#define WASMER_VERSION_MAJOR {major}
#define WASMER_VERSION_MINOR {minor}
#define WASMER_VERSION_PATCH {patch}
#define WASMER_VERSION_PRE "{pre}"
"#,
full = env!("CARGO_PKG_VERSION"),
major = env!("CARGO_PKG_VERSION_MAJOR"),
minor = env!("CARGO_PKG_VERSION_MINOR"),
patch = env!("CARGO_PKG_VERSION_PATCH"),
pre = env!("CARGO_PKG_VERSION_PRE"),
));
}

/// Create a fresh new `Builder`, already pre-configured.
fn new_builder(language: Language, crate_dir: &str, include_guard: &str, header: &str) -> Builder {
Builder::new()
Expand Down
2 changes: 2 additions & 0 deletions lib/c-api/src/wasm_c_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub mod types;
/// cbindgen:ignore
pub mod value;

pub mod version;

#[cfg(feature = "wasi")]
pub mod wasi;

Expand Down
144 changes: 144 additions & 0 deletions lib/c-api/src/wasm_c_api/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
use lazy_static::lazy_static;
use std::os::raw::c_char;

const VERSION: &'static str = concat!(env!("CARGO_PKG_VERSION"), "\0");
const VERSION_PRE: &'static str = concat!(env!("CARGO_PKG_VERSION_PRE"), "\0");

lazy_static! {
static ref VERSION_MAJOR: u8 = env!("CARGO_PKG_VERSION_MAJOR")
.parse()
.expect("Failed to parse value for `VERSION_MAJOR` from `CARGO_PKG_VERSION_MAJOR`");
static ref VERSION_MINOR: u8 = env!("CARGO_PKG_VERSION_MINOR")
.parse()
.expect("Failed to parse value for `VERSION_MINOR` from `CARGO_PKG_VERSION_MINOR`");
static ref VERSION_PATCH: u8 = env!("CARGO_PKG_VERSION_PATCH")
.parse()
.expect("Failed to parse value for `VERSION_PATCH` from `CARGO_PKG_VERSION_PATCH`");
}

/// Get the version of the Wasmer C API.
///
/// The `.h` files already define variables like `WASMER_VERSION*`,
/// but if this file is unreachable, one can use this function to
/// retrieve the full semver version of the Wasmer C API.
///
/// The returned string is statically allocated. It must _not_ be
/// freed!
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Get and print the version.
/// const char* version = wasmer_version();
/// printf("%s", version);
///
/// // No need to free the string. It's statically allocated on
/// // the Rust side.
///
/// return 0;
/// }
/// # })
/// # .success()
/// # .stdout(env!("CARGO_PKG_VERSION"));
/// # }
/// ```
#[no_mangle]
pub unsafe extern "C" fn wasmer_version() -> *const c_char {
VERSION.as_ptr() as *const _
}

/// Get the major version of the Wasmer C API.
///
/// See `wasmer_version` to learn more.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Get and print the version components.
/// uint8_t version_major = wasmer_version_major();
/// uint8_t version_minor = wasmer_version_minor();
/// uint8_t version_patch = wasmer_version_patch();
///
/// printf("%d.%d.%d", version_major, version_minor, version_patch);
///
/// return 0;
/// }
/// # })
/// # .success()
/// # .stdout(
/// # format!(
/// # "{}.{}.{}",
/// # env!("CARGO_PKG_VERSION_MAJOR"),
/// # env!("CARGO_PKG_VERSION_MINOR"),
/// # env!("CARGO_PKG_VERSION_PATCH")
/// # )
/// # );
/// # }
/// ```
#[no_mangle]
pub unsafe extern "C" fn wasmer_version_major() -> u8 {
*VERSION_MAJOR
}

/// Get the minor version of the Wasmer C API.
///
/// See `wasmer_version_major` to learn more and get an example.
#[no_mangle]
pub unsafe extern "C" fn wasmer_version_minor() -> u8 {
*VERSION_MINOR
}

/// Get the patch version of the Wasmer C API.
///
/// See `wasmer_version_major` to learn more and get an example.
#[no_mangle]
pub unsafe extern "C" fn wasmer_version_patch() -> u8 {
*VERSION_PATCH
}

/// Get the minor version of the Wasmer C API.
///
/// See `wasmer_version_major` to learn more.
///
/// The returned string is statically allocated. It must _not_ be
/// freed!
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Get and print the pre version.
/// const char* version_pre = wasmer_version_pre();
/// printf("%s", version_pre);
///
/// // No need to free the string. It's statically allocated on
/// // the Rust side.
///
/// return 0;
/// }
/// # })
/// # .success()
/// # .stdout(env!("CARGO_PKG_VERSION_PRE"));
/// # }
/// ```
#[no_mangle]
pub unsafe extern "C" fn wasmer_version_pre() -> *const c_char {
VERSION_PRE.as_ptr() as *const _
}
136 changes: 133 additions & 3 deletions lib/c-api/wasmer.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// The Wasmer C/C++ header file.

#if !defined(WASMER_H_MACROS)
#if !defined(WASMER_H_PRELUDE)

#define WASMER_H_MACROS
#define WASMER_H_PRELUDE

// Define the `ARCH_X86_X64` constant.
#if defined(MSVC) && defined(_M_AMD64)
Expand Down Expand Up @@ -30,7 +30,15 @@

// The `wasi` feature has been enabled for this build.
#define WASMER_WASI_ENABLED
#endif // WASMER_H_MACROS

// This file corresponds to the following Wasmer version.
#define WASMER_VERSION "1.0.0-beta1"
#define WASMER_VERSION_MAJOR 1
#define WASMER_VERSION_MINOR 0
#define WASMER_VERSION_PATCH 0
#define WASMER_VERSION_PRE "beta1"

#endif // WASMER_H_PRELUDE


//
Expand Down Expand Up @@ -1415,6 +1423,128 @@ wasmer_result_t wasmer_trap(const wasmer_instance_context_t *_ctx, const char *e
*/
bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len);

/**
* Get the version of the Wasmer C API.
*
* The `.h` files already define variables like `WASMER_VERSION*`,
* but if this file is unreachable, one can use this function to
* retrieve the full semver version of the Wasmer C API.
*
* The returned string is statically allocated. It must _not_ be
* freed!
*
* # Example
*
* ```rust
* # use inline_c::assert_c;
* # fn main() {
* # (assert_c! {
* # #include "tests/wasmer_wasm.h"
* #
* int main() {
* // Get and print the version.
* const char* version = wasmer_version();
* printf("%s", version);
*
* // No need to free the string. It's statically allocated on
* // the Rust side.
*
* return 0;
* }
* # })
* # .success()
* # .stdout(env!("CARGO_PKG_VERSION"));
* # }
* ```
*/
const char *wasmer_version(void);

/**
* Get the major version of the Wasmer C API.
*
* See `wasmer_version` to learn more.
*
* # Example
*
* ```rust
* # use inline_c::assert_c;
* # fn main() {
* # (assert_c! {
* # #include "tests/wasmer_wasm.h"
* #
* int main() {
* // Get and print the version components.
* uint8_t version_major = wasmer_version_major();
* uint8_t version_minor = wasmer_version_minor();
* uint8_t version_patch = wasmer_version_patch();
*
* printf("%d.%d.%d", version_major, version_minor, version_patch);
*
* return 0;
* }
* # })
* # .success()
* # .stdout(
* # format!(
* # "{}.{}.{}",
* # env!("CARGO_PKG_VERSION_MAJOR"),
* # env!("CARGO_PKG_VERSION_MINOR"),
* # env!("CARGO_PKG_VERSION_PATCH")
* # )
* # );
* # }
* ```
*/
uint8_t wasmer_version_major(void);

/**
* Get the minor version of the Wasmer C API.
*
* See `wasmer_version_major` to learn more and get an example.
*/
uint8_t wasmer_version_minor(void);

/**
* Get the patch version of the Wasmer C API.
*
* See `wasmer_version_major` to learn more and get an example.
*/
uint8_t wasmer_version_patch(void);

/**
* Get the minor version of the Wasmer C API.
*
* See `wasmer_version_major` to learn more.
*
* The returned string is statically allocated. It must _not_ be
* freed!
*
* # Example
*
* ```rust
* # use inline_c::assert_c;
* # fn main() {
* # (assert_c! {
* # #include "tests/wasmer_wasm.h"
* #
* int main() {
* // Get and print the pre version.
* const char* version_pre = wasmer_version_pre();
* printf("%s", version_pre);
*
* // No need to free the string. It's statically allocated on
* // the Rust side.
*
* return 0;
* }
* # })
* # .success()
* # .stdout(env!("CARGO_PKG_VERSION_PRE"));
* # }
* ```
*/
const char *wasmer_version_pre(void);

#if defined(WASMER_WASI_ENABLED)
/**
* Convenience function that creates a WASI import object with no arguments,
Expand Down
Loading

0 comments on commit 35e0021

Please sign in to comment.