build_solidity_contracts/
lib.rs1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![doc = include_str!("../README.md")]
3#![deny(missing_docs)]
4
5use std::{path::PathBuf, fs, process::Command};
6
7pub fn build(contracts_path: &str, artifacts_path: &str) -> Result<(), String> {
11 println!("cargo:rerun-if-changed={contracts_path}/*");
12 println!("cargo:rerun-if-changed={artifacts_path}/*");
13
14 for line in String::from_utf8(
15 Command::new("solc")
16 .args(["--version"])
17 .output()
18 .map_err(|_| "couldn't fetch solc output".to_string())?
19 .stdout,
20 )
21 .map_err(|_| "solc stdout wasn't UTF-8")?
22 .lines()
23 {
24 if let Some(version) = line.strip_prefix("Version: ") {
25 let version =
26 version.split('+').next().ok_or_else(|| "no value present on line".to_string())?;
27 if version != "0.8.25" {
28 Err(format!("version was {version}, 0.8.25 required"))?
29 }
30 }
31 }
32
33 #[rustfmt::skip]
34 let args = [
35 "--base-path", ".",
36 "-o", artifacts_path, "--overwrite",
37 "--bin", "--bin-runtime", "--abi",
38 "--via-ir", "--optimize",
39 "--no-color",
40 ];
41 let mut args = args.into_iter().map(str::to_string).collect::<Vec<_>>();
42
43 let mut queue = vec![PathBuf::from(contracts_path)];
44 while let Some(folder) = queue.pop() {
45 for entry in fs::read_dir(folder).map_err(|e| format!("couldn't read directory: {e:?}"))? {
46 let entry = entry.map_err(|e| format!("couldn't read directory in entry: {e:?}"))?;
47 let kind = entry.file_type().map_err(|e| format!("couldn't fetch file type: {e:?}"))?;
48 if kind.is_dir() {
49 queue.push(entry.path());
50 }
51
52 if kind.is_file() &&
53 entry
54 .file_name()
55 .into_string()
56 .map_err(|_| "file name wasn't a valid UTF-8 string".to_string())?
57 .ends_with(".sol")
58 {
59 args.push(
60 entry
61 .path()
62 .into_os_string()
63 .into_string()
64 .map_err(|_| "file path wasn't a valid UTF-8 string".to_string())?,
65 );
66 }
67
68 }
70 }
71
72 let solc = Command::new("solc")
73 .args(args)
74 .output()
75 .map_err(|_| "couldn't fetch solc output".to_string())?;
76 let stderr =
77 String::from_utf8(solc.stderr).map_err(|_| "solc stderr wasn't UTF-8".to_string())?;
78 if !solc.status.success() {
79 Err(format!("solc didn't successfully execute: {stderr}"))?;
80 }
81 for line in stderr.lines() {
82 if line.contains("Error:") {
83 Err(format!("solc output had error: {stderr}"))?;
84 }
85 }
86
87 Ok(())
88}