diff --git a/Cargo.lock b/Cargo.lock index b8f67300..5b77925c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -383,6 +383,19 @@ dependencies = [ "wit_parser", ] +[[package]] +name = "fce_cli" +version = "0.1.0" +dependencies = [ + "clap", + "exitfailure", + "failure", + "serde", + "serde_json", + "wit", + "wit_parser", +] + [[package]] name = "fce_wit_interfaces" version = "0.1.0" @@ -724,6 +737,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "ppv-lite86" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" + [[package]] name = "proc-macro2" version = "1.0.18" @@ -753,6 +772,47 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + [[package]] name = "raw-cpuid" version = "7.0.3" @@ -1036,6 +1096,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "uuid" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" +dependencies = [ + "rand", +] + [[package]] name = "vec_map" version = "0.8.2" @@ -1269,6 +1338,30 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "wit" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "walrus", + "wasmer-interface-types", + "wit-support", + "wit_parser", +] + +[[package]] +name = "wit-support" +version = "0.2.0" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "uuid", +] + [[package]] name = "wit_embedder" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index c64655e8..74afbb43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "examples/ipfs_node/wasm/ipfs_rpc", "examples/simple_greeting", "fluence-faas", + "tools/fce_cli", "tools/wit_embedder", ] diff --git a/crates/wit_parser/src/embedder.rs b/crates/wit_parser/src/embedder.rs index bf1e29e4..744738bd 100644 --- a/crates/wit_parser/src/embedder.rs +++ b/crates/wit_parser/src/embedder.rs @@ -19,6 +19,7 @@ use super::errors::WITParserError; use walrus::ModuleConfig; use wasmer_wit::{ + ast::Interfaces, decoders::wat::{parse, Buffer}, encoders::binary::ToBytes, }; @@ -48,3 +49,24 @@ pub fn embed_text_wit( Ok(()) } + +pub fn embed_wit( + in_wasm_path: PathBuf, + out_wasm_path: PathBuf, + interfaces: &Interfaces<'_>, +) -> Result<(), WITParserError> { + let mut module = ModuleConfig::new() + .parse_file(&in_wasm_path) + .map_err(WITParserError::CorruptedWasmFile)?; + + let mut bytes = vec![]; + interfaces.to_bytes(&mut bytes)?; + + let custom = WITCustom(bytes); + module.customs.add(custom); + module + .emit_wasm_file(&out_wasm_path) + .map_err(WITParserError::WasmEmitError)?; + + Ok(()) +} diff --git a/crates/wit_parser/src/lib.rs b/crates/wit_parser/src/lib.rs index 5aa4d944..ea51295b 100644 --- a/crates/wit_parser/src/lib.rs +++ b/crates/wit_parser/src/lib.rs @@ -33,6 +33,7 @@ mod extractor; pub use errors::WITParserError; pub use embedder::embed_text_wit; +pub use embedder::embed_wit; pub use deleter::delete_wit_section; pub use extractor::extract_wit; pub use extractor::extract_text_wit; diff --git a/engine/src/module/wit_function.rs b/engine/src/module/wit_function.rs index 0be60a1f..27453ed5 100644 --- a/engine/src/module/wit_function.rs +++ b/engine/src/module/wit_function.rs @@ -113,7 +113,6 @@ impl wasm::structures::LocalImport for WITFunction { fn call(&self, arguments: &[IValue]) -> Result, ()> { use super::type_converters::{ival_to_wval, wval_to_ival}; - // println!("wit_function called with {:?}", arguments); match &self.inner { WITFunctionInner::Export { func, .. } => func diff --git a/tools/fce_cli/Cargo.toml b/tools/fce_cli/Cargo.toml new file mode 100644 index 00000000..13e44505 --- /dev/null +++ b/tools/fce_cli/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "fce_cli" +version = "0.1.0" +authors = ["Fluence Labs"] +edition = "2018" + +[[bin]] +name = "fce_cli" +path = "src/main.rs" + +[dependencies] +wit_parser = { path = "../../crates/wit_parser" } +clap = "2.33.1" +exitfailure = "0.5.1" +failure = "0.1.5" +wit = { path = "/Users/mike/dev/work/fluence/wasm/rust-sdk/crates/wit" } +serde = "1.0.114" +serde_json = "1.0.56" diff --git a/tools/fce_cli/src/args.rs b/tools/fce_cli/src/args.rs new file mode 100644 index 00000000..c68f941b --- /dev/null +++ b/tools/fce_cli/src/args.rs @@ -0,0 +1,27 @@ +use clap::{App, Arg, SubCommand}; + +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); +pub const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); + +pub const IN_WASM_PATH: &str = "in-wasm-path"; + +pub fn build<'a, 'b>() -> App<'a, 'b> { + SubCommand::with_name("build") + .about("build provided Rust project to Wasm") + .args(&[Arg::with_name(IN_WASM_PATH) + .required(true) + .takes_value(true) + .short("i") + .help("path to the wasm file")]) +} + +pub fn validate<'a, 'b>() -> App<'a, 'b> { + SubCommand::with_name("validate") + .about("validates provided Wasm file to suite Fluence network requirements") + .args(&[Arg::with_name(IN_WASM_PATH) + .required(true) + .takes_value(true) + .short("i") + .help("path to the wasm file")]) +} diff --git a/tools/fce_cli/src/main.rs b/tools/fce_cli/src/main.rs new file mode 100644 index 00000000..545bb6b0 --- /dev/null +++ b/tools/fce_cli/src/main.rs @@ -0,0 +1,108 @@ +/* + * Copyright 2020 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#![warn(rust_2018_idioms)] +#![deny( + // dead_code, + nonstandard_style, + unused_imports, + unused_mut, + unused_variables, + unused_unsafe, + unreachable_patterns +)] + +mod args; + +use args::*; + +use clap::{App, AppSettings}; +// use std::path::PathBuf; +use std::process::Command; + +#[derive(serde::Deserialize)] +#[serde(tag = "reason", rename_all = "kebab-case")] +enum DiagnosticMessage { + BuildScriptExecuted, + BuildFinished, + CompilerArtifact { + executable: String, + /* + filenames: Vec, + profile: Profile, + fresh: bool, + */ + }, + RunWithArgs { + // args: Vec, + }, +} + +pub fn main() -> Result<(), exitfailure::ExitFailure> { + let app = App::new("CLI tool for embedding WIT to provided Wasm file") + .version(VERSION) + .author(AUTHORS) + .about(DESCRIPTION) + .setting(AppSettings::ArgRequiredElseHelp) + .subcommand(build()) + .subcommand(validate()); + + match app.get_matches().subcommand() { + ("build", Some(arg)) => { + use std::io::Read; + + let wasm_path = arg.value_of(IN_WASM_PATH).unwrap(); + // wit_embedder::delete_wit_section(wasm_path.clone(), wasm_path.clone()); + + let mut cargo = Command::new("cargo"); + cargo.arg("build").arg("--target").arg("wasm32-wasi"); + cargo.arg("--message-format").arg("json-render-diagnostics"); + cargo.arg("--manifest-path").arg(wasm_path); + + let mut process = cargo.stdout(std::process::Stdio::piped()).spawn().unwrap(); + + let mut output = String::new(); + + process + .stdout + .take() + .unwrap() + .read_to_string(&mut output) + .unwrap(); + let _status = process.wait().unwrap(); + + let mut wasms = Vec::new(); + for line in output.lines() { + match serde_json::from_str(line) { + Ok(DiagnosticMessage::CompilerArtifact { executable }) => { + wasms.push(executable) + } + _ => {} + } + } + + let wasm_path = std::path::PathBuf::from(wasms.first().unwrap()); + wit::embed_wit(wasm_path); + + Ok(()) + } + ("validate", Some(arg)) => { + let _wasm_path = arg.value_of(IN_WASM_PATH).unwrap(); + + Ok(()) + } + c => Err(failure::err_msg(format!("Unexpected command: {}", c.0)).into()), + } +}