Skip to content

Commit c99fe3b

Browse files
authored
refactor: extract artifacts to a separate crate (#142)
Closes #129 Divides `foundry-compilers` into 3 crates: - `foundry-compilers-artifacts` - JSON artifacts for Solc and Vyper compilers - `foundry-compilers-project` - Project related logic, including compiler abstraction and compilation pipeline - `foundry-compilers-core` - error types and utilties shared by both crates
1 parent 43da903 commit c99fe3b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1507
-1216
lines changed

Cargo.toml

+23-101
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
[package]
2-
name = "foundry-compilers"
1+
[workspace]
2+
members = ["crates/artifacts/*", "crates/core", "crates/project"]
3+
resolver = "2"
4+
5+
[workspace.package]
36
authors = ["Foundry Maintainers"]
47
version = "0.7.0"
58
rust-version = "1.65"
@@ -13,110 +16,29 @@ keywords = ["foundry", "solidity", "solc", "ethereum", "ethers"]
1316
edition = "2021"
1417
exclude = [".github/", "scripts/", "test-data/"]
1518

16-
[package.metadata.docs.rs]
17-
all-features = true
18-
rustdoc-args = ["--cfg", "docsrs"]
19-
20-
[package.metadata.playground]
21-
all-features = true
22-
23-
[dependencies]
19+
[workspace.dependencies]
20+
foundry-compilers-artifacts-solc = { path = "crates/artifacts/solc", version = "0.7.0" }
21+
foundry-compilers-artifacts-vyper = { path = "crates/artifacts/vyper", version = "0.7.0" }
22+
foundry-compilers-artifacts = { path = "crates/artifacts/artifacts", version = "0.7.0" }
23+
foundry-compilers-core = { path = "crates/core", version = "0.7.0" }
24+
serde = { version = "1", features = ["derive", "rc"] }
25+
semver = { version = "1.0", features = ["serde"] }
26+
serde_json = "1.0"
2427
alloy-primitives = { version = "0.7", features = ["serde", "rand"] }
2528
alloy-json-abi = { version = "0.7", features = ["serde_json"] }
26-
27-
solang-parser = { version = "=0.3.3", default-features = false }
28-
29-
cfg-if = "1.0.0"
30-
dirs = "5.0"
31-
dunce = "1.0"
32-
md-5 = "0.10"
33-
memmap2 = "0.9"
34-
once_cell = "1.19"
35-
path-slash = "0.2"
29+
tracing = "0.1"
3630
rayon = "1.8"
31+
thiserror = "1"
3732
regex = "1.10"
38-
semver = { version = "1.0", features = ["serde"] }
39-
serde = { version = "1", features = ["derive", "rc"] }
40-
serde_json = "1.0"
41-
thiserror = "1.0"
42-
tracing = "0.1"
43-
walkdir = "2.4"
33+
path-slash = "0.2"
34+
md-5 = "0.10"
4435
yansi = "1.0.1"
45-
46-
# async
47-
futures-util = { version = "0.3", optional = true }
48-
tokio = { version = "1.35", features = ["rt-multi-thread"], optional = true }
49-
50-
# project-util
51-
tempfile = { version = "3.9", optional = true }
52-
fs_extra = { version = "1.3", optional = true }
53-
rand = { version = "0.8", optional = true }
54-
55-
# svm
56-
home = "0.5"
57-
svm = { package = "svm-rs", version = "0.5", default-features = false, optional = true }
58-
svm-builds = { package = "svm-rs-builds", version = "0.5", default-features = false, optional = true }
59-
sha2 = { version = "0.10", default-features = false, optional = true }
60-
itertools = "0.13"
61-
auto_impl = "1"
62-
63-
winnow = "0.6"
64-
dyn-clone = "1"
65-
derivative = "2.2"
66-
67-
[dev-dependencies]
68-
alloy-primitives = { version = "0.7", features = ["serde", "rand"] }
69-
criterion = { version = "0.5", features = ["async_tokio"] }
36+
once_cell = "1.19"
37+
svm = { package = "svm-rs", version = "0.5", default-features = false }
38+
solang-parser = { version = "=0.3.3", default-features = false }
7039
pretty_assertions = "1"
71-
rand = "0.8"
72-
serde_path_to_error = "0.1"
7340
tempfile = "3.9"
74-
tokio = { version = "1.35", features = ["rt-multi-thread", "macros"] }
75-
tracing-subscriber = { version = "0.3", default-features = false, features = [
76-
"env-filter",
77-
"fmt",
78-
] }
79-
reqwest = "0.12"
80-
fd-lock = "4.0.0"
81-
82-
[[bench]]
83-
name = "compile_many"
84-
required-features = ["svm-solc"]
85-
harness = false
86-
87-
[[bench]]
88-
name = "read_all"
89-
required-features = ["project-util", "svm-solc"]
90-
harness = false
91-
92-
[[test]]
93-
name = "project"
94-
path = "tests/project.rs"
95-
required-features = ["full", "project-util", "test-utils"]
96-
97-
[[test]]
98-
name = "mocked"
99-
path = "tests/mocked.rs"
100-
required-features = ["full", "project-util"]
10141

102-
[features]
103-
default = ["rustls"]
104-
test-utils = []
105-
106-
full = ["async", "svm-solc"]
107-
108-
# Adds extra `async` methods using `tokio` to some types.
109-
async = [
110-
"dep:futures-util",
111-
"dep:tokio",
112-
"tokio/fs",
113-
"tokio/process",
114-
"tokio/io-util",
115-
]
116-
# Enables `svm` to auto-detect and manage `solc` builds.
117-
svm-solc = ["dep:svm", "dep:svm-builds", "dep:sha2", "dep:tokio"]
118-
# Utilities for creating and testing project workspaces.
119-
project-util = ["dep:tempfile", "dep:fs_extra", "dep:rand", "svm-solc"]
120-
121-
rustls = ["svm?/rustls"]
122-
openssl = ["svm?/openssl"]
42+
# async
43+
futures-util = "0.3"
44+
tokio = { version = "1.35", features = ["rt-multi-thread"] }

benches/compile_many.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn compile_many_benchmark(c: &mut Criterion) {
3838

3939
fn load_compiler_inputs() -> Vec<SolcInput> {
4040
let mut inputs = Vec::new();
41-
for file in std::fs::read_dir(Path::new(&env!("CARGO_MANIFEST_DIR")).join("test-data/in"))
41+
for file in std::fs::read_dir(Path::new(&env!("CARGO_MANIFEST_DIR")).join("../../test-data/in"))
4242
.unwrap()
4343
.take(5)
4444
{

crates/artifacts/artifacts/Cargo.toml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "foundry-compilers-artifacts"
3+
description = "Rust bindings for compilers JSON artifacts"
4+
5+
version.workspace = true
6+
edition.workspace = true
7+
rust-version.workspace = true
8+
authors.workspace = true
9+
license.workspace = true
10+
homepage.workspace = true
11+
repository.workspace = true
12+
exclude.workspace = true
13+
14+
[package.metadata.docs.rs]
15+
all-features = true
16+
rustdoc-args = ["--cfg", "docsrs"]
17+
18+
[package.metadata.playground]
19+
all-features = true
20+
21+
[dependencies]
22+
foundry-compilers-artifacts-solc.workspace = true
23+
foundry-compilers-artifacts-vyper.workspace = true
24+
25+
[features]
26+
async = ["foundry-compilers-artifacts-solc/async"]

crates/artifacts/artifacts/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! Meta crate reexporting all artifacts types.
2+
3+
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
4+
5+
pub use foundry_compilers_artifacts_solc as solc;
6+
pub use foundry_compilers_artifacts_vyper as vyper;
7+
pub use solc::*;

crates/artifacts/solc/Cargo.toml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[package]
2+
name = "foundry-compilers-artifacts-solc"
3+
description = "Rust bindings for Solc JSON artifacts"
4+
5+
version.workspace = true
6+
edition.workspace = true
7+
rust-version.workspace = true
8+
authors.workspace = true
9+
license.workspace = true
10+
homepage.workspace = true
11+
repository.workspace = true
12+
exclude.workspace = true
13+
14+
[package.metadata.docs.rs]
15+
all-features = true
16+
rustdoc-args = ["--cfg", "docsrs"]
17+
18+
[package.metadata.playground]
19+
all-features = true
20+
21+
[dependencies]
22+
foundry-compilers-core.workspace = true
23+
24+
serde.workspace = true
25+
semver.workspace = true
26+
serde_json.workspace = true
27+
tracing.workspace = true
28+
alloy-primitives.workspace = true
29+
alloy-json-abi.workspace = true
30+
rayon.workspace = true
31+
thiserror.workspace = true
32+
md-5.workspace = true
33+
yansi.workspace = true
34+
futures-util = { workspace = true, optional = true}
35+
tokio = { workspace = true, optional = true }
36+
37+
walkdir = "2.4"
38+
39+
[target.'cfg(windows)'.dependencies]
40+
path-slash.workspace = true
41+
42+
[dev-dependencies]
43+
serde_path_to_error = "0.1"
44+
pretty_assertions.workspace = true
45+
foundry-compilers-core = { workspace = true, features = ["test-utils"] }
46+
47+
[features]
48+
async = ["dep:tokio", "futures-util", "tokio/fs"]

src/artifacts/ast/lowfidelity.rs renamed to crates/artifacts/solc/src/ast/lowfidelity.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Bindings for solc's `ast` output field
22
3-
use crate::artifacts::serde_helpers;
3+
use crate::serde_helpers;
44
use serde::{de::DeserializeOwned, Deserialize, Serialize};
55
use std::{collections::BTreeMap, fmt, fmt::Write, str::FromStr};
66

@@ -213,7 +213,7 @@ mod tests {
213213

214214
#[test]
215215
fn can_parse_ast() {
216-
let ast = include_str!("../../../test-data/ast/ast-erc4626.json");
216+
let ast = include_str!("../../../../../test-data/ast/ast-erc4626.json");
217217
let _ast: Ast = serde_json::from_str(ast).unwrap();
218218
}
219219
}
File renamed without changes.
File renamed without changes.

src/artifacts/ast/mod.rs renamed to crates/artifacts/solc/src/ast/mod.rs

+21-19
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use lowfidelity::{Ast, Node, NodeType, SourceLocation as LowFidelitySourceLo
2727
/// The Yul AST is embedded into the Solidity AST for inline assembly blocks.
2828
pub mod yul;
2929

30-
use crate::artifacts::serde_helpers;
30+
use crate::serde_helpers;
3131
use macros::{ast_node, expr_node, node_group, stmt_node};
3232
use serde::{Deserialize, Serialize};
3333
use std::collections::BTreeMap;
@@ -1093,24 +1093,26 @@ mod tests {
10931093

10941094
#[test]
10951095
fn can_parse_ast() {
1096-
fs::read_dir(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data").join("ast"))
1097-
.unwrap()
1098-
.for_each(|path| {
1099-
let path = path.unwrap().path();
1100-
let path_str = path.to_string_lossy();
1101-
1102-
let input = fs::read_to_string(&path).unwrap();
1103-
let deserializer = &mut serde_json::Deserializer::from_str(&input);
1104-
let result: Result<SourceUnit, _> = serde_path_to_error::deserialize(deserializer);
1105-
match result {
1106-
Err(e) => {
1107-
println!("... {path_str} fail: {e}");
1108-
panic!();
1109-
}
1110-
Ok(_) => {
1111-
println!("... {path_str} ok");
1112-
}
1096+
fs::read_dir(
1097+
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../../test-data").join("ast"),
1098+
)
1099+
.unwrap()
1100+
.for_each(|path| {
1101+
let path = path.unwrap().path();
1102+
let path_str = path.to_string_lossy();
1103+
1104+
let input = fs::read_to_string(&path).unwrap();
1105+
let deserializer = &mut serde_json::Deserializer::from_str(&input);
1106+
let result: Result<SourceUnit, _> = serde_path_to_error::deserialize(deserializer);
1107+
match result {
1108+
Err(e) => {
1109+
println!("... {path_str} fail: {e}");
1110+
panic!();
11131111
}
1114-
})
1112+
Ok(_) => {
1113+
println!("... {path_str} ok");
1114+
}
1115+
}
1116+
})
11151117
}
11161118
}
File renamed without changes.

src/artifacts/ast/yul.rs renamed to crates/artifacts/solc/src/ast/yul.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{macros::node_group, misc::SourceLocation};
2-
use crate::artifacts::serde_helpers;
2+
use crate::serde_helpers;
33
use serde::{Deserialize, Serialize};
44

55
node_group! {

src/artifacts/bytecode.rs renamed to crates/artifacts/solc/src/bytecode.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! Bytecode related types.
22
33
use crate::{
4-
artifacts::{serde_helpers, FunctionDebugData, GeneratedSource, Offsets},
4+
serde_helpers,
55
sourcemap::{self, SourceMap, SyntaxError},
6-
utils,
6+
FunctionDebugData, GeneratedSource, Offsets,
77
};
88
use alloy_primitives::{hex, Address, Bytes};
9+
use foundry_compilers_core::utils;
910
use serde::{Deserialize, Serialize, Serializer};
1011
use std::collections::BTreeMap;
1112

@@ -498,7 +499,7 @@ impl From<CompactDeployedBytecode> for DeployedBytecode {
498499

499500
#[cfg(test)]
500501
mod tests {
501-
use crate::{artifacts::ContractBytecode, ConfigurableContractArtifact};
502+
use crate::{ConfigurableContractArtifact, ContractBytecode};
502503

503504
#[test]
504505
fn test_empty_bytecode() {

0 commit comments

Comments
 (0)