diff --git a/src/cmd/build.rs b/src/cmd/build.rs index ea25295ebf802fed95b214130a445da7f54ec0a4..ef100e4f68f2900e743af5b742733c210f237c38 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -24,7 +24,7 @@ use std::{ use crate::{ util, workspace::{ManifestPath, Workspace}, - Verbosity, + UnstableFlags, Verbosity, }; use anyhow::{Context, Result}; use cargo_metadata::Package; @@ -94,7 +94,18 @@ pub fn collect_crate_metadata(manifest_path: &ManifestPath) -> Result) -> Result<()> { +/// +/// # Cargo.toml optimizations +/// +/// The original Cargo.toml will be amended to remove the `rlib` crate type in order to minimize +/// the final Wasm binary size. +/// +/// To disable this and use the `Cargo.toml` as is then pass the `-Z original_manifest` flag. +fn build_cargo_project( + crate_metadata: &CrateMetadata, + verbosity: Option, + unstable_options: UnstableFlags, +) -> Result<()> { util::assert_channel()?; // set RUSTFLAGS, read from environment var by cargo-xbuild @@ -136,14 +147,24 @@ fn build_cargo_project(crate_metadata: &CrateMetadata, verbosity: Option Result<()> { pub(crate) fn execute_build( manifest_path: ManifestPath, verbosity: Option, + unstable_options: UnstableFlags, ) -> Result { println!( " {} {}", @@ -285,7 +307,7 @@ pub(crate) fn execute_build( "[2/4]".bold(), "Building cargo project".bright_green().bold() ); - build_cargo_project(&crate_metadata, verbosity)?; + build_cargo_project(&crate_metadata, verbosity, unstable_options)?; println!( " {} {}", "[3/4]".bold(), @@ -308,7 +330,9 @@ pub(crate) fn execute_build( #[cfg(feature = "test-ci-only")] #[cfg(test)] mod tests { - use crate::{cmd::execute_new, util::tests::with_tmp_dir, workspace::ManifestPath}; + use crate::{ + cmd::execute_new, util::tests::with_tmp_dir, workspace::ManifestPath, UnstableFlags, + }; #[test] fn build_template() { @@ -316,7 +340,8 @@ mod tests { execute_new("new_project", Some(path)).expect("new project creation failed"); let manifest_path = ManifestPath::new(&path.join("new_project").join("Cargo.toml")).unwrap(); - super::execute_build(manifest_path, None).expect("build failed"); + super::execute_build(manifest_path, None, UnstableFlags::default()) + .expect("build failed"); }); } } diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 98803c77541685f7ac8a0042f666e5b4009df066..ca70f176426e8daaf56a7a670deb78315ab23cad 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -17,7 +17,7 @@ use crate::{ util, workspace::{ManifestPath, Workspace}, - Verbosity, + UnstableFlags, Verbosity, }; use anyhow::Result; @@ -27,44 +27,49 @@ const METADATA_FILE: &str = "metadata.json"; /// /// It does so by invoking build by cargo and then post processing the final binary. pub(crate) fn execute_generate_metadata( - manifest_path: ManifestPath, + original_manifest_path: ManifestPath, verbosity: Option, + unstable_options: UnstableFlags, ) -> Result { util::assert_channel()?; println!(" Generating metadata"); - let (metadata, root_package_id) = crate::util::get_cargo_metadata(&manifest_path)?; + let (metadata, root_package_id) = crate::util::get_cargo_metadata(&original_manifest_path)?; let out_path = metadata.target_directory.join(METADATA_FILE); let out_path_display = format!("{}", out_path.display()); let target_dir = metadata.target_directory.clone(); - let generate_metadata = move |tmp_manifest_path: &ManifestPath| -> Result<()> { + let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); util::invoke_cargo( "run", &[ "--package", "abi-gen", - &tmp_manifest_path.cargo_arg(), + &manifest_path.cargo_arg(), &target_dir_arg, "--release", // "--no-default-features", // Breaks builds for MacOS (linker errors), we should investigate this issue asap! ], - manifest_path.directory(), + original_manifest_path.directory(), verbosity, ) }; - Workspace::new(&metadata, &root_package_id)? - .with_root_package_manifest(|manifest| { - manifest - .with_added_crate_type("rlib")? - .with_profile_release_lto(false)?; - Ok(()) - })? - .using_temp(generate_metadata)?; + if unstable_options.original_manifest { + generate_metadata(&original_manifest_path)?; + } else { + Workspace::new(&metadata, &root_package_id)? + .with_root_package_manifest(|manifest| { + manifest + .with_added_crate_type("rlib")? + .with_profile_release_lto(false)?; + Ok(()) + })? + .using_temp(generate_metadata)?; + } Ok(format!( "Your metadata file is ready.\nYou can find it here:\n{}", @@ -79,6 +84,7 @@ mod tests { cmd::{execute_generate_metadata, execute_new}, util::tests::with_tmp_dir, workspace::ManifestPath, + UnstableFlags, }; #[test] @@ -88,8 +94,8 @@ mod tests { execute_new("new_project", Some(path)).expect("new project creation failed"); let working_dir = path.join("new_project"); let manifest_path = ManifestPath::new(working_dir.join("Cargo.toml")).unwrap(); - let message = - execute_generate_metadata(manifest_path, None).expect("generate metadata failed"); + let message = execute_generate_metadata(manifest_path, None, UnstableFlags::default()) + .expect("generate metadata failed"); println!("{}", message); let mut abi_file = working_dir; diff --git a/src/main.rs b/src/main.rs index 870d711c1991fb7cb9ee69b68f92bb3411afcb12..adeae4d3b4af5c8f357ccc088b6f40d5a6af2a06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,6 +112,37 @@ impl TryFrom<&VerbosityFlags> for Option { } } +#[derive(Debug, StructOpt)] +struct UnstableOptions { + /// Use the original manifest (Cargo.toml), do not modify for build optimizations + #[structopt(long = "unstable-options", short = "Z", number_of_values = 1)] + options: Vec, +} + +#[derive(Default)] +struct UnstableFlags { + original_manifest: bool, +} + +impl TryFrom<&UnstableOptions> for UnstableFlags { + type Error = Error; + + fn try_from(value: &UnstableOptions) -> Result { + let valid_flags = ["original-manifest"]; + let invalid_flags = value + .options + .iter() + .filter(|o| !valid_flags.contains(&o.as_str())) + .collect::>(); + if !invalid_flags.is_empty() { + anyhow::bail!("Unknown unstable-options {:?}", invalid_flags) + } + Ok(UnstableFlags { + original_manifest: value.options.contains(&"original-manifest".to_owned()), + }) + } +} + #[derive(Debug, StructOpt)] enum Command { /// Setup and create a new smart contract project @@ -128,12 +159,16 @@ enum Command { Build { #[structopt(flatten)] verbosity: VerbosityFlags, + #[structopt(flatten)] + unstable_options: UnstableOptions, }, /// Generate contract metadata artifacts #[structopt(name = "generate-metadata")] GenerateMetadata { #[structopt(flatten)] verbosity: VerbosityFlags, + #[structopt(flatten)] + unstable_options: UnstableOptions, }, /// Test the smart contract off-chain #[structopt(name = "test")] @@ -197,12 +232,22 @@ fn main() { fn exec(cmd: Command) -> Result { match &cmd { Command::New { name, target_dir } => cmd::execute_new(name, target_dir.as_ref()), - Command::Build { verbosity } => { - cmd::execute_build(Default::default(), verbosity.try_into()?) - } - Command::GenerateMetadata { verbosity } => { - cmd::execute_generate_metadata(Default::default(), verbosity.try_into()?) - } + Command::Build { + verbosity, + unstable_options, + } => cmd::execute_build( + Default::default(), + verbosity.try_into()?, + unstable_options.try_into()?, + ), + Command::GenerateMetadata { + verbosity, + unstable_options, + } => cmd::execute_generate_metadata( + Default::default(), + verbosity.try_into()?, + unstable_options.try_into()?, + ), Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), #[cfg(feature = "extrinsics")] Command::Deploy {