1use std::{fs, path::Path};
6
7use clap::Parser;
8use iota_move_build::{BuildConfig, check_invalid_dependencies, check_unpublished_dependencies};
9use move_cli::base;
10use move_package::BuildConfig as MoveBuildConfig;
11use serde_json::json;
12
13use crate::manage_package::resolve_lock_file_path;
14
15const LAYOUTS_DIR: &str = "layouts";
16const STRUCT_LAYOUTS_FILENAME: &str = "struct_layouts.yaml";
17
18#[derive(Parser)]
20#[group(id = "iota-move-build")]
21pub struct Build {
22 #[arg(long, global = true)]
25 pub with_unpublished_dependencies: bool,
26 #[arg(long, global = true)]
28 pub dump_bytecode_as_base64: bool,
29 #[arg(long, global = true, requires = "dump_bytecode_as_base64")]
34 pub ignore_chain: bool,
35 #[arg(long, global = true)]
40 pub generate_struct_layouts: bool,
41 #[arg(skip)]
45 pub chain_id: Option<String>,
46}
47
48impl Build {
49 pub fn execute(
50 &self,
51 path: Option<&Path>,
52 build_config: MoveBuildConfig,
53 ) -> anyhow::Result<()> {
54 let rerooted_path = base::reroot_path(path)?;
55 let build_config = resolve_lock_file_path(build_config, Some(&rerooted_path))?;
56 Self::execute_internal(
57 &rerooted_path,
58 build_config,
59 self.with_unpublished_dependencies,
60 self.dump_bytecode_as_base64,
61 self.generate_struct_layouts,
62 self.chain_id.clone(),
63 )
64 }
65
66 pub fn execute_internal(
67 rerooted_path: &Path,
68 config: MoveBuildConfig,
69 with_unpublished_deps: bool,
70 dump_bytecode_as_base64: bool,
71 generate_struct_layouts: bool,
72 chain_id: Option<String>,
73 ) -> anyhow::Result<()> {
74 let pkg = BuildConfig {
75 config,
76 run_bytecode_verifier: true,
77 print_diags_to_stderr: true,
78 chain_id,
79 }
80 .build(rerooted_path)?;
81 if dump_bytecode_as_base64 {
82 check_invalid_dependencies(&pkg.dependency_ids.invalid)?;
83 if !with_unpublished_deps {
84 check_unpublished_dependencies(&pkg.dependency_ids.unpublished)?;
85 }
86
87 println!(
88 "{}",
89 json!({
90 "modules": pkg.get_package_base64(with_unpublished_deps),
91 "dependencies": pkg.get_dependency_storage_package_ids(),
92 "digest": pkg.get_package_digest(with_unpublished_deps),
93 })
94 )
95 }
96
97 if generate_struct_layouts {
98 let layout_str = serde_yaml::to_string(&pkg.generate_struct_layouts()).unwrap();
99 let dir_name = rerooted_path
101 .join("build")
102 .join(pkg.package.compiled_package_info.package_name.as_str())
103 .join(LAYOUTS_DIR);
104 let layout_filename = dir_name.join(STRUCT_LAYOUTS_FILENAME);
105 fs::create_dir_all(dir_name)?;
106 fs::write(layout_filename, layout_str)?
107 }
108
109 pkg.package
110 .compiled_package_info
111 .build_flags
112 .update_lock_file_toolchain_version(rerooted_path, env!("CARGO_PKG_VERSION").into())?;
113
114 Ok(())
115 }
116}