1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Command `Build`.
use crate::utils::WasmBuilder;
use anyhow::{anyhow, Result};
use ccli::clap::{self, Parser};
use etc::{Etc, FileSystem};
use std::{env, fs, path::PathBuf};
use zinkc::{Compiler, Config};

/// Build zink project to EVM bytecode.
#[derive(Debug, Parser)]
#[command(name = "build", version)]
pub struct Build {
    /// The path of the cargo project.
    pub input: Option<PathBuf>,
    /// Write output to <filename>
    #[clap(short, long, value_name = "filename")]
    pub output: Option<PathBuf>,
    /// Write output to compiler-chosen filename in <dir>
    #[clap(long, value_name = "dir")]
    pub out_dir: Option<PathBuf>,
    /// Compiler configuration
    #[clap(flatten)]
    pub config: Config,
}

impl Build {
    /// Run build
    pub fn run(&self) -> Result<()> {
        // Get and check the input.
        let input = if let Some(input) = self.input.as_ref() {
            input.clone()
        } else {
            env::current_dir()?
        };
        {
            if Etc::new(&input)?.find("Cargo.toml").is_err() {
                return Ok(());
            }

            if !input.is_dir() {
                return Err(anyhow!(
                    "Only support rust project directory as input for now"
                ));
            }
        }

        // Build the wasm.
        let mut builder = WasmBuilder::new(input)?;
        {
            if let Some(out_dir) = self.out_dir.as_ref() {
                builder.with_out_dir(out_dir);
            }

            if let Some(output) = self.output.as_ref() {
                builder.with_output(output);
            }

            builder.build()?;
        }

        // Compile the wasm to evm bytecode.
        let wasm = fs::read(builder.output()?)?;
        let config = Config::default().dispatcher(self.config.dispatcher);
        let artifact = Compiler::new(config).compile(&wasm)?;
        let dst = builder.output()?.with_extension("bin");

        fs::write(dst, artifact.runtime_bytecode)?;
        Ok(())
    }
}