diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 25bfc0256ff307652f47ba40f3b9e54ed0354838..cabdb1bd6467899cc8a4aa37adbb3624ca50516a 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -308,7 +308,10 @@ fn optimize_wasm( optimization_passes: OptimizationPasses, ) -> Result { let mut dest_optimized = crate_metadata.dest_wasm.clone(); - dest_optimized.set_file_name(format!("{}-opt.wasm", crate_metadata.package_name)); + dest_optimized.set_file_name(format!( + "{}-opt.wasm", + crate_metadata.contract_artifact_name + )); let _ = do_optimization( crate_metadata.dest_wasm.as_os_str(), &dest_optimized.as_os_str(), @@ -606,6 +609,7 @@ mod tests_ci_only { #[cfg(unix)] use std::os::unix::fs::PermissionsExt; use std::{ + ffi::OsStr, io::Write, path::{Path, PathBuf}, }; @@ -902,4 +906,42 @@ mod tests_ci_only { Ok(()) }) } + + #[test] + fn contract_lib_name_different_from_package_name_must_build() { + with_new_contract_project(|manifest_path| { + // given + let mut manifest = + Manifest::new(manifest_path.clone()).expect("manifest creation failed"); + let _ = manifest + .set_lib_name("some_lib_name") + .expect("setting lib name failed"); + let _ = manifest + .set_package_name("some_package_name") + .expect("setting pacakge name failed"); + manifest + .write(&manifest_path) + .expect("writing manifest failed"); + + // when + let cmd = BuildCommand { + manifest_path: Some(manifest_path.into()), + build_artifact: BuildArtifacts::All, + verbosity: VerbosityFlags::default(), + unstable_options: UnstableOptions::default(), + optimization_passes: None, + }; + let res = cmd.exec().expect("build failed"); + + // then + assert_eq!( + res.dest_wasm + .expect("`dest_wasm` does not exist") + .file_name(), + Some(OsStr::new("some_lib_name.wasm")) + ); + + Ok(()) + }) + } } diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 94cb4d104dcd70841267ff6391a0a055b65e2417..4fca166d2ea827bc0f511f4618b434ed1b374e71 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -67,7 +67,7 @@ pub(crate) fn execute( let target_directory = crate_metadata.target_directory.clone(); let out_path_metadata = target_directory.join(METADATA_FILE); - let fname_bundle = format!("{}.contract", crate_metadata.package_name); + let fname_bundle = format!("{}.contract", crate_metadata.contract_artifact_name); let out_path_bundle = target_directory.join(fname_bundle); // build the extended contract project metadata @@ -401,7 +401,10 @@ mod tests { assert_eq!(expected_wasm, wasm.as_str().unwrap()); assert_eq!(expected_language, language.as_str().unwrap()); assert_eq!(expected_compiler, compiler.as_str().unwrap()); - assert_eq!(crate_metadata.package_name, name.as_str().unwrap()); + assert_eq!( + crate_metadata.contract_artifact_name, + name.as_str().unwrap() + ); assert_eq!( crate_metadata.root_package.version.to_string(), version.as_str().unwrap() diff --git a/src/crate_metadata.rs b/src/crate_metadata.rs index 26bf7f5f0695bfe1504fbd94b4f46c573c3deaee..9b47b7d190f1e4e2461b757c7fe4c03ea5d053ab 100644 --- a/src/crate_metadata.rs +++ b/src/crate_metadata.rs @@ -28,7 +28,7 @@ use url::Url; pub struct CrateMetadata { pub manifest_path: ManifestPath, pub cargo_meta: cargo_metadata::Metadata, - pub package_name: String, + pub contract_artifact_name: String, pub root_package: Package, pub original_wasm: PathBuf, pub dest_wasm: PathBuf, @@ -45,25 +45,34 @@ impl CrateMetadata { let (metadata, root_package) = get_cargo_metadata(manifest_path)?; let mut target_directory = metadata.target_directory.as_path().join("ink"); - // Normalize the package name. + // Normalize the package and lib name. let package_name = root_package.name.replace("-", "_"); + let lib_name = &root_package + .targets + .iter() + .find(|target| target.kind.iter().any(|t| t == "cdylib")) + .expect("lib name not found") + .name + .replace("-", "_"); let absolute_manifest_path = manifest_path.absolute_directory()?; let absolute_workspace_root = metadata.workspace_root.canonicalize()?; if absolute_manifest_path != absolute_workspace_root { - target_directory = target_directory.join(package_name.clone()); + // If the contract is a package in a workspace, we use the package name + // as the name of the sub-folder where we put the `.contract` bundle. + target_directory = target_directory.join(package_name); } - // {target_dir}/wasm32-unknown-unknown/release/{package_name}.wasm + // {target_dir}/wasm32-unknown-unknown/release/{lib_name}.wasm let mut original_wasm = target_directory.clone(); original_wasm.push("wasm32-unknown-unknown"); original_wasm.push("release"); - original_wasm.push(package_name.clone()); + original_wasm.push(lib_name.clone()); original_wasm.set_extension("wasm"); - // {target_dir}/{package_name}.wasm + // {target_dir}/{lib_name}.wasm let mut dest_wasm = target_directory.clone(); - dest_wasm.push(package_name.clone()); + dest_wasm.push(lib_name.clone()); dest_wasm.set_extension("wasm"); let ink_version = metadata @@ -91,7 +100,7 @@ impl CrateMetadata { manifest_path: manifest_path.clone(), cargo_meta: metadata, root_package, - package_name, + contract_artifact_name: lib_name.to_string(), original_wasm: original_wasm.into(), dest_wasm: dest_wasm.into(), ink_version, diff --git a/src/workspace/manifest.rs b/src/workspace/manifest.rs index fc2a52ed25a1e947dab0d68b451a46dae016c340..7db38880436f6c58b0f0221b7fdc7f82fc6843ad 100644 --- a/src/workspace/manifest.rs +++ b/src/workspace/manifest.rs @@ -224,6 +224,32 @@ impl Manifest { .insert("version".into(), value::Value::String(version.into()))) } + /// Set the `lib` name to `name`. + #[cfg(feature = "test-ci-only")] + #[cfg(test)] + pub fn set_lib_name(&mut self, name: &str) -> Result> { + Ok(self + .toml + .get_mut("lib") + .ok_or_else(|| anyhow::anyhow!("[lib] section not found"))? + .as_table_mut() + .ok_or_else(|| anyhow::anyhow!("[lib] should be a table"))? + .insert("name".into(), value::Value::String(name.into()))) + } + + /// Set the `package` name to `name`. + #[cfg(feature = "test-ci-only")] + #[cfg(test)] + pub fn set_package_name(&mut self, name: &str) -> Result> { + Ok(self + .toml + .get_mut("package") + .ok_or_else(|| anyhow::anyhow!("[package] section not found"))? + .as_table_mut() + .ok_or_else(|| anyhow::anyhow!("[package] should be a table"))? + .insert("name".into(), value::Value::String(name.into()))) + } + /// Set `[profile.release]` lto flag pub fn with_profile_release_lto(&mut self, enabled: bool) -> Result<&mut Self> { let lto = self