cargo_unc/commands/build_command/
build.rs1use camino::Utf8PathBuf;
2use colored::Colorize;
3use sha2::{Digest, Sha256};
4use unc_abi::BuildInfo;
5
6use crate::commands::abi_command::abi::{AbiCompression, AbiFormat, AbiResult};
7use crate::common::ColorPreference;
8use crate::types::{manifest::CargoManifestPath, metadata::CrateMetadata};
9use crate::util;
10use crate::{commands::abi_command::abi, util::wasm32_target_libdir_exists};
11
12const COMPILATION_TARGET: &str = "wasm32-unknown-unknown";
13
14pub fn run(args: super::BuildCommand) -> color_eyre::eyre::Result<util::CompilationArtifact> {
15 let color = args.color.unwrap_or(ColorPreference::Auto);
16 color.apply();
17
18 util::handle_step("Checking the host environment...", || {
19 if !wasm32_target_libdir_exists() {
20 color_eyre::eyre::bail!("rust target `{}` is not installed", COMPILATION_TARGET);
21 }
22 Ok(())
23 })?;
24
25 let crate_metadata = util::handle_step("Collecting cargo project metadata...", || {
26 let manifest_path: Utf8PathBuf = if let Some(manifest_path) = args.manifest_path {
27 manifest_path.into()
28 } else {
29 "Cargo.toml".into()
30 };
31 CrateMetadata::collect(CargoManifestPath::try_from(manifest_path)?)
32 })?;
33
34 let out_dir = args
35 .out_dir
36 .map_or(Ok(crate_metadata.target_directory.clone()), |out_dir| {
37 let out_dir = Utf8PathBuf::from(out_dir);
38 util::force_canonicalize_dir(&out_dir)
39 })?;
40
41 let mut build_env = vec![("RUSTFLAGS", "-C link-arg=-s")];
42 let mut cargo_args = vec!["--target", COMPILATION_TARGET];
43 let mut cargo_feature_args = vec![];
44
45 if !args.no_release {
46 cargo_args.push("--release");
47 }
48
49 if let Some(features) = args.features.as_ref() {
50 cargo_feature_args.extend(&["--features", features]);
51 }
52
53 if args.no_default_features {
54 cargo_feature_args.push("--no-default-features");
55 }
56
57 let mut abi = None;
58 let mut min_abi_path = None;
59 if !args.no_abi {
60 let mut contract_abi = abi::generate_abi(
61 &crate_metadata,
62 !args.no_doc,
63 true,
64 &cargo_feature_args,
65 color.clone(),
66 )?;
67 contract_abi.metadata.build = Some(BuildInfo {
68 compiler: format!("rustc {}", rustc_version::version()?),
69 builder: format!("cargo-unc {}", env!("CARGO_PKG_VERSION")),
70 image: None,
71 });
72 if !args.no_embed_abi {
73 let path = util::handle_step("Compressing ABI to be embedded..", || {
74 let AbiResult { path } = abi::write_to_file(
75 &contract_abi,
76 &crate_metadata,
77 AbiFormat::JsonMin,
78 AbiCompression::Zstd,
79 )?;
80 Ok(path)
81 })?;
82 min_abi_path.replace(util::copy(&path, &out_dir)?);
83 }
84 abi = Some(contract_abi);
85 }
86
87 cargo_args.extend(cargo_feature_args);
88
89 if let (false, Some(abi_path)) = (args.no_embed_abi, &min_abi_path) {
90 cargo_args.extend(&["--features", "unc-sdk/__abi-embed"]);
91 build_env.push(("CARGO_UNC_ABI_PATH", abi_path.as_str()));
92 }
93
94 util::print_step("Building contract");
95 let mut wasm_artifact = util::compile_project(
96 &crate_metadata.manifest_path,
97 &cargo_args,
98 build_env,
99 "wasm",
100 false,
101 color,
102 )?;
103
104 wasm_artifact.path = util::copy(&wasm_artifact.path, &out_dir)?;
105
106 util::print_success("Contract successfully built!");
108 let mut messages = vec![(
109 "Binary",
110 wasm_artifact.path.to_string().bright_yellow().bold(),
111 )];
112 if let Some(mut abi) = abi {
113 let mut hasher = Sha256::new();
114 hasher.update(std::fs::read(&wasm_artifact.path)?);
115 let hash = hasher.finalize();
116 let hash = bs58::encode(hash).into_string();
117 abi.metadata.wasm_hash = Some(hash);
118
119 let AbiResult { path } =
120 abi::write_to_file(&abi, &crate_metadata, AbiFormat::Json, AbiCompression::NoOp)?;
121 let pretty_abi_path = util::copy(&path, &out_dir)?;
122 messages.push(("ABI", pretty_abi_path.to_string().yellow().bold()));
123 }
124 if let Some(abi_path) = min_abi_path {
125 messages.push(("Embedded ABI", abi_path.to_string().yellow().bold()));
126 }
127
128 let max_width = messages.iter().map(|(h, _)| h.len()).max().unwrap();
129 for (header, message) in messages {
130 eprintln!(" - {:>width$}: {}", header, message, width = max_width);
131 }
132
133 Ok(wasm_artifact)
134}