From 69c9a140b8cda7e41f136820d3ac4643fd40ac79 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 8 May 2022 15:40:09 +0200 Subject: [PATCH 1/2] rust: introduce evmc-loader wrapper --- .bumpversion.cfg | 4 +++ Cargo.toml | 1 + bindings/rust/evmc-loader/.gitignore | 3 +++ bindings/rust/evmc-loader/Cargo.toml | 16 +++++++++++ bindings/rust/evmc-loader/README.md | 5 ++++ bindings/rust/evmc-loader/build.rs | 40 ++++++++++++++++++++++++++++ bindings/rust/evmc-loader/loader.h | 1 + bindings/rust/evmc-loader/src/lib.rs | 37 +++++++++++++++++++++++++ bindings/rust/evmc-loader/src/sys.rs | 31 +++++++++++++++++++++ 9 files changed, 138 insertions(+) create mode 100644 bindings/rust/evmc-loader/.gitignore create mode 100644 bindings/rust/evmc-loader/Cargo.toml create mode 100644 bindings/rust/evmc-loader/README.md create mode 100644 bindings/rust/evmc-loader/build.rs create mode 120000 bindings/rust/evmc-loader/loader.h create mode 100644 bindings/rust/evmc-loader/src/lib.rs create mode 100644 bindings/rust/evmc-loader/src/sys.rs diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b9ce6c6c5..4fe316936 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -57,6 +57,10 @@ replace = version = "{new_version}" search = version = "{current_version}" replace = version = "{new_version}" +[bumpversion:file:bindings/rust/evmc-loader/Cargo.toml] +search = version = "{current_version}" +replace = version = "{new_version}" + [bumpversion:file:examples/example-rust-vm/Cargo.toml] search = version = "{current_version}" replace = version = "{new_version}" diff --git a/Cargo.toml b/Cargo.toml index d265bcdbd..0e0e1b774 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,6 @@ members = [ "bindings/rust/evmc-vm", "bindings/rust/evmc-declare", "bindings/rust/evmc-declare-tests", + "bindings/rust/evmc-loader", "examples/example-rust-vm" ] diff --git a/bindings/rust/evmc-loader/.gitignore b/bindings/rust/evmc-loader/.gitignore new file mode 100644 index 000000000..84c47ed70 --- /dev/null +++ b/bindings/rust/evmc-loader/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +/Cargo.lock diff --git a/bindings/rust/evmc-loader/Cargo.toml b/bindings/rust/evmc-loader/Cargo.toml new file mode 100644 index 000000000..37adc68fa --- /dev/null +++ b/bindings/rust/evmc-loader/Cargo.toml @@ -0,0 +1,16 @@ +# EVMC: Ethereum Client-VM Connector API. +# Copyright 2022 The EVMC Authors. +# Licensed under the Apache License, Version 2.0. + +[package] +name = "evmc-loader" +version = "10.0.0-alpha.5" +authors = ["Alex Beregszaszi "] +license = "Apache-2.0" +repository = "https://github.com/ethereum/evmc" +description = "Bindings to EVMC (Loader bindings)" +edition = "2018" + +[build-dependencies] +bindgen = "0.59" +cmake = "0.1" diff --git a/bindings/rust/evmc-loader/README.md b/bindings/rust/evmc-loader/README.md new file mode 100644 index 000000000..1bb5fcbc8 --- /dev/null +++ b/bindings/rust/evmc-loader/README.md @@ -0,0 +1,5 @@ +# evmc-loader + +This is a Rust interface to [EVMC](https://github.com/ethereum/evmc). + +This crate contains a wrapper for the loader functionality. diff --git a/bindings/rust/evmc-loader/build.rs b/bindings/rust/evmc-loader/build.rs new file mode 100644 index 000000000..75df53887 --- /dev/null +++ b/bindings/rust/evmc-loader/build.rs @@ -0,0 +1,40 @@ +// EVMC: Ethereum Client-VM Connector API. +// Copyright 2022 The EVMC Authors. +// Licensed under the Apache License, Version 2.0. + +extern crate bindgen; +extern crate cmake; + +use cmake::Config; +use std::env; +use std::path::PathBuf; + +fn main() { + let dst = Config::new("../../../").build(); + + println!("cargo:rustc-link-lib=static=evmc-loader"); + println!( + "cargo:rustc-link-search=native={}/build/lib/loader", + dst.display() + ); + + let bindings = bindgen::Builder::default() + .header("loader.h") + .generate_comments(false) + // do not generate an empty enum for EVMC_ABI_VERSION + .constified_enum("") + // generate Rust enums for each evmc enum + .rustified_enum("*") + .allowlist_type("evmc_.*") + .allowlist_function("evmc_.*") + .blocklist_type("evmc_vm") + // TODO: consider removing this + .size_t_is_usize(true) + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Could not write bindings"); +} diff --git a/bindings/rust/evmc-loader/loader.h b/bindings/rust/evmc-loader/loader.h new file mode 120000 index 000000000..8e4511962 --- /dev/null +++ b/bindings/rust/evmc-loader/loader.h @@ -0,0 +1 @@ +../../../include/evmc/loader.h \ No newline at end of file diff --git a/bindings/rust/evmc-loader/src/lib.rs b/bindings/rust/evmc-loader/src/lib.rs new file mode 100644 index 000000000..21b70066a --- /dev/null +++ b/bindings/rust/evmc-loader/src/lib.rs @@ -0,0 +1,37 @@ +// EVMC: Ethereum Client-VM Connector API. +// Copyright 2022 The EVMC Authors. +// Licensed under the Apache License, Version 2.0. + +use std::ffi::{CStr, CString}; + +mod sys; + +pub fn load_and_configure( + config: &str, +) -> Result<*mut sys::evmc_vm, (sys::evmc_loader_error_code, String)> { + let config_cstr = CString::new(config).unwrap(); + let mut error_code = sys::evmc_loader_error_code::EVMC_LOADER_UNSPECIFIED_ERROR; + let instance = unsafe { sys::evmc_load_and_configure(config_cstr.as_ptr(), &mut error_code) }; + + if error_code == sys::evmc_loader_error_code::EVMC_LOADER_SUCCESS { + assert!(!instance.is_null()); + Ok(instance) + } else { + assert!(instance.is_null()); + let error_msg = unsafe { CStr::from_ptr(sys::evmc_last_error_msg()) } + .to_str() + .expect("well formed error message") // TODO free the vm + .to_string(); + Err((error_code, error_msg)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn load_fail() { + println!("{:?}", load_and_configure("test.so")); + } +} diff --git a/bindings/rust/evmc-loader/src/sys.rs b/bindings/rust/evmc-loader/src/sys.rs new file mode 100644 index 000000000..82506f87c --- /dev/null +++ b/bindings/rust/evmc-loader/src/sys.rs @@ -0,0 +1,31 @@ +// EVMC: Ethereum Client-VM Connector API. +// Copyright 2022 The EVMC Authors. +// Licensed under the Apache License, Version 2.0. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +// Defining evmc_vm here, because bindgen cannot create a useful declaration yet. + +pub type evmc_vm = ::std::os::raw::c_void; + +#[cfg(test)] +mod tests { + use std::ffi::CString; + use std::os::raw::c_char; + + use super::*; + + #[test] + fn load_fail() { + let c_str = CString::new("test.so").unwrap(); + unsafe { + let mut error_code = evmc_loader_error_code::EVMC_LOADER_UNSPECIFIED_ERROR; + let instance = evmc_load_and_create(c_str.as_ptr() as *const c_char, &mut error_code); + println!("{:?} {:?}", error_code, instance); + } + } +} From c16008bc02c1eaab4671f62977e1c0cfd1f0d7fd Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 8 May 2022 22:27:03 +0200 Subject: [PATCH 2/2] ci: install cmake for rust --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 5fe5fc67a..10ce39659 100644 --- a/circle.yml +++ b/circle.yml @@ -326,7 +326,7 @@ jobs: name: Update environment command: | apt -qq update - apt -yq install libclang-dev clang --no-install-recommends + apt -yq install cmake libclang-dev clang --no-install-recommends rustup component add rustfmt - run: name: Check formatting @@ -364,7 +364,7 @@ jobs: name: Update environment command: | apt -qq update - apt -yq install llvm-11-dev clang-11 --no-install-recommends + apt -yq install cmake llvm-11-dev clang-11 --no-install-recommends rustup toolchain install nightly-x86_64-unknown-linux-gnu - run: name: Build