diff --git a/cli/src/cmd/abi.rs b/cli/src/cmd/abi.rs new file mode 100644 index 0000000000000000000000000000000000000000..36eb4a5269dbfb7acd541efda90f22acf138171a --- /dev/null +++ b/cli/src/cmd/abi.rs @@ -0,0 +1,70 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of ink!. +// +// ink! is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ink! is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ink!. If not, see . + +use crate::cmd::{ + Result, +}; +use cargo_metadata::MetadataCommand; +use std::path::PathBuf; + +/// Executes build of the smart-contract which produces a wasm binary that is ready for deploying. +/// +/// It does so by invoking build by cargo and then post processing the final binary. +pub(crate) fn execute_generate_abi(dir: Option<&PathBuf>) -> Result { + println!(" Generating abi"); + + super::exec_cargo("run", &[ + "--package", + "abi-gen", + "--verbose", + ], dir)?; + + let metadata = MetadataCommand::new().exec()?; + let mut abi_path = metadata.target_directory.clone(); + abi_path.push("abi.json"); + + Ok(format!( + "Your abi file is ready.\nYou can find it here:\n{}", + abi_path.display() + )) +} + +#[cfg(test)] +mod tests { + use crate::{ + cmd::{ + execute_new, + execute_generate_abi, + tests::with_tmp_dir, + }, + AbstractionLayer, + }; + + #[test] + fn generate_abi() { + with_tmp_dir(|path| { + execute_new(AbstractionLayer::Lang, "new_project", Some(path)) + .expect("new project creation failed"); + let working_dir = path.join("new_project"); + super::execute_generate_abi(Some(&working_dir)).expect("generate abi failed"); + + let mut abi_file = working_dir.clone(); + abi_file.push("target"); + abi_file.push("abi.json"); + assert!(abi_file.exists()) + }); + } +} diff --git a/cli/src/cmd/build.rs b/cli/src/cmd/build.rs index 2f57f1c3b5c324981221b79fdfeebdf71133a483..fdd27d904d1143b41cbf3992556b27233394b1c0 100644 --- a/cli/src/cmd/build.rs +++ b/cli/src/cmd/build.rs @@ -25,14 +25,7 @@ use parity_wasm::elements::{ Module, Section, }; -use std::{ - io::{ - self, - Write, - }, - path::PathBuf, - process::Command, -}; +use std::path::PathBuf; /// This is the maximum number of pages available for a contract to allocate. const MAX_MEMORY_PAGES: u32 = 16; @@ -96,43 +89,12 @@ pub fn collect_crate_metadata(working_dir: Option<&PathBuf>) -> Result) -> Result<()> { - let mut cmd = Command::new("cargo"); - let mut is_nightly_cmd = Command::new("cargo"); - if let Some(dir) = working_dir { - cmd.current_dir(dir); - is_nightly_cmd.current_dir(dir); - } - - let is_nightly_default = is_nightly_cmd - .arg("--version") - .output() - .map_err(|_| ()) - .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ())) - .unwrap_or_default() - .contains("-nightly"); - - if !is_nightly_default { - cmd.arg("+nightly"); - } - - let output = cmd - .args(&[ - "build", - "--no-default-features", - "--release", - "--target=wasm32-unknown-unknown", - "--verbose", - ]) - .output()?; - - if !output.status.success() { - // Dump the output streams produced by cargo into the stdout/stderr. - io::stdout().write_all(&output.stdout)?; - io::stderr().write_all(&output.stderr)?; - return Err(Error::BuildFailed) - } - - Ok(()) + super::exec_cargo("build", &[ + "--no-default-features", + "--release", + "--target=wasm32-unknown-unknown", + "--verbose", + ], working_dir) } /// Ensures the wasm memory import of a given module has the maximum number of pages. diff --git a/cli/src/cmd/mod.rs b/cli/src/cmd/mod.rs index 690c87eccc0dd85fdcae3c0360fc69c712cb2594..993a8034eac246da275e06a93e3b494b4a398051 100644 --- a/cli/src/cmd/mod.rs +++ b/cli/src/cmd/mod.rs @@ -14,12 +14,23 @@ // You should have received a copy of the GNU General Public License // along with ink!. If not, see . +use std::{ + io::{ + self, + Write, + }, + path::PathBuf, + process::Command, +}; + +mod abi; mod build; mod deploy; mod error; mod new; pub(crate) use self::{ + abi::execute_generate_abi, build::execute_build, deploy::execute_deploy, error::{ @@ -29,6 +40,41 @@ pub(crate) use self::{ new::execute_new, }; +fn exec_cargo(command: &str, args: &[&'static str], working_dir: Option<&PathBuf>) -> Result<()> { + let mut cmd = Command::new("cargo"); + let mut is_nightly_cmd = Command::new("cargo"); + if let Some(dir) = working_dir { + cmd.current_dir(dir); + is_nightly_cmd.current_dir(dir); + } + + let is_nightly_default = is_nightly_cmd + .arg("--version") + .output() + .map_err(|_| ()) + .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ())) + .unwrap_or_default() + .contains("-nightly"); + + if !is_nightly_default { + cmd.arg("+nightly"); + } + + let output = cmd + .arg(command) + .args(args) + .output()?; + + if !output.status.success() { + // Dump the output streams produced by cargo into the stdout/stderr. + io::stdout().write_all(&output.stdout)?; + io::stderr().write_all(&output.stderr)?; + return Err(error::CommandError::BuildFailed) + } + + Ok(()) +} + #[cfg(test)] mod tests { use std::path::PathBuf; diff --git a/cli/src/main.rs b/cli/src/main.rs index 05b79ad3289870714c541c52fe6c39ae2416fb89..4ba29e16e1725f19b86cf483483f7fce6e2d57a2 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -94,6 +94,9 @@ enum Command { /// Builds the smart contract. #[structopt(name = "build")] Build {}, + /// Generate abi artifacts + #[structopt(name = "generate-abi")] + GenerateAbi {}, /// Test the smart contract off-chain. #[structopt(name = "test")] Test {}, @@ -142,6 +145,7 @@ fn exec(cmd: Command) -> cmd::Result { target_dir, } => cmd::execute_new(*layer, name, target_dir.as_ref()), Command::Build {} => cmd::execute_build(None), + Command::GenerateAbi {} => cmd::execute_generate_abi(None), Command::Test {} => Err(CommandError::UnimplementedCommand), Command::Deploy { url,