Skip to content

Commit ecb767d

Browse files
committed
[wip] feat: compilation restrictions
1 parent 07a1f67 commit ecb767d

File tree

11 files changed

+194
-56
lines changed

11 files changed

+194
-56
lines changed

Cargo.lock

Lines changed: 24 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ foundry-linking = { path = "crates/linking" }
167167

168168
# solc & compilation utilities
169169
foundry-block-explorers = { version = "0.7.3", default-features = false }
170-
foundry-compilers = { version = "0.11.1", default-features = false }
170+
foundry-compilers = { version = "0.11", default-features = false }
171171
foundry-fork-db = "0.3"
172172
solang-parser = "=0.3.3"
173173

@@ -276,7 +276,7 @@ soldeer = "=0.3.4"
276276
proptest = "1"
277277
comfy-table = "7"
278278

279-
# [patch.crates-io]
279+
[patch.crates-io]
280280
# alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" }
281281
# alloy-contract = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" }
282282
# alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" }
@@ -300,3 +300,4 @@ comfy-table = "7"
300300
# alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" }
301301
# alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" }
302302
# alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" }
303+
foundry-compilers = { git = "https://github.com/foundry-rs/compilers", rev = "5b42d05" }

crates/cast/bin/cmd/storage.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use foundry_compilers::{
2222
artifacts::{ConfigurableContractArtifact, StorageLayout},
2323
compilers::{
2424
solc::{Solc, SolcCompiler},
25-
Compiler, CompilerSettings,
25+
Compiler,
2626
},
2727
Artifact, Project,
2828
};
@@ -288,7 +288,7 @@ fn print_storage(layout: StorageLayout, values: Vec<StorageValue>, pretty: bool)
288288

289289
fn add_storage_layout_output<C: Compiler>(project: &mut Project<C>) {
290290
project.artifacts.additional_values.storage_layout = true;
291-
project.settings.update_output_selection(|selection| {
291+
project.update_output_selection(|selection| {
292292
selection.0.values_mut().for_each(|contract_selection| {
293293
contract_selection
294294
.values_mut()

crates/config/src/compilation.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use crate::{filter::GlobMatcher, serde_helpers};
2+
use foundry_compilers::{
3+
artifacts::EvmVersion,
4+
multi::{MultiCompilerRestrictions, MultiCompilerSettings},
5+
settings::VyperRestrictions,
6+
solc::{EvmVersionRestriction, SolcRestrictions},
7+
RestrictionsWithVersion,
8+
};
9+
use semver::VersionReq;
10+
use serde::{Deserialize, Serialize};
11+
12+
/// Keeps possible overrides for default settings which users may configure to construct additional
13+
/// settings profile.
14+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
15+
pub struct SettingsOverrides {
16+
pub name: String,
17+
via_ir: Option<bool>,
18+
#[serde(default, with = "serde_helpers::display_from_str_opt")]
19+
evm_version: Option<EvmVersion>,
20+
optimizer: Option<bool>,
21+
optimizer_runs: Option<usize>,
22+
}
23+
24+
impl SettingsOverrides {
25+
/// Applies the overrides to the given settings.
26+
pub fn apply(&self, settings: &mut MultiCompilerSettings) {
27+
if let Some(via_ir) = self.via_ir {
28+
settings.solc.via_ir = Some(via_ir);
29+
}
30+
31+
if let Some(evm_version) = self.evm_version {
32+
settings.solc.evm_version = Some(evm_version);
33+
settings.vyper.evm_version = Some(evm_version);
34+
}
35+
36+
if let Some(enabled) = self.optimizer {
37+
settings.solc.optimizer.enabled = Some(enabled);
38+
}
39+
40+
if let Some(optimizer_runs) = self.optimizer_runs {
41+
settings.solc.optimizer.runs = Some(optimizer_runs);
42+
}
43+
}
44+
}
45+
46+
/// Restrictions for compilation of given paths.
47+
///
48+
/// Only purpose of this type is to accept user input to later construct
49+
/// `RestrictionsWithVersion<MultiCompilerRestrictions>`.
50+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
51+
pub struct CompilationRestrictions {
52+
pub paths: GlobMatcher,
53+
version: Option<VersionReq>,
54+
via_ir: Option<bool>,
55+
min_optimizer_runs: Option<usize>,
56+
max_optimizer_runs: Option<usize>,
57+
#[serde(flatten)]
58+
evm_version: EvmVersionRestriction,
59+
}
60+
61+
impl From<CompilationRestrictions> for RestrictionsWithVersion<MultiCompilerRestrictions> {
62+
fn from(value: CompilationRestrictions) -> Self {
63+
Self {
64+
restrictions: MultiCompilerRestrictions {
65+
solc: SolcRestrictions {
66+
evm_version: value.evm_version,
67+
via_ir: value.via_ir,
68+
min_optimizer_runs: value.min_optimizer_runs,
69+
max_optimizer_runs: value.max_optimizer_runs,
70+
},
71+
vyper: VyperRestrictions { evm_version: value.evm_version },
72+
},
73+
version: value.version,
74+
}
75+
}
76+
}

crates/config/src/lib.rs

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ use foundry_compilers::{
3333
Compiler,
3434
},
3535
error::SolcError,
36+
multi::{MultiCompilerParsedSource, MultiCompilerRestrictions},
3637
solc::{CliSettings, SolcSettings},
37-
ConfigurableArtifacts, Project, ProjectPathsConfig, VyperLanguage,
38+
ConfigurableArtifacts, Graph, Project, ProjectPathsConfig, RestrictionsWithVersion,
39+
VyperLanguage,
3840
};
3941
use inflector::Inflector;
4042
use regex::Regex;
@@ -43,7 +45,7 @@ use semver::Version;
4345
use serde::{Deserialize, Serialize, Serializer};
4446
use std::{
4547
borrow::Cow,
46-
collections::HashMap,
48+
collections::{BTreeMap, HashMap},
4749
fs,
4850
path::{Path, PathBuf},
4951
str::FromStr,
@@ -115,6 +117,9 @@ use vyper::VyperConfig;
115117
mod bind_json;
116118
use bind_json::BindJsonConfig;
117119

120+
mod compilation;
121+
use compilation::{CompilationRestrictions, SettingsOverrides};
122+
118123
/// Foundry configuration
119124
///
120125
/// # Defaults
@@ -469,6 +474,14 @@ pub struct Config {
469474
#[serde(rename = "__warnings", default, skip_serializing)]
470475
pub warnings: Vec<Warning>,
471476

477+
/// Additional settings profiles to use when compiling.
478+
#[serde(default)]
479+
pub additional_compiler_profiles: Vec<SettingsOverrides>,
480+
481+
/// Restrictions on compilation of certain files.
482+
#[serde(default)]
483+
pub compilation_restrictions: Vec<CompilationRestrictions>,
484+
472485
/// PRIVATE: This structure may grow, As such, constructing this structure should
473486
/// _always_ be done using a public constructor or update syntax:
474487
///
@@ -835,12 +848,65 @@ impl Config {
835848
self.create_project(false, true)
836849
}
837850

851+
/// Builds mapping with additional settings profiles.
852+
fn additional_settings(
853+
&self,
854+
base: &MultiCompilerSettings,
855+
) -> BTreeMap<String, MultiCompilerSettings> {
856+
let mut map = BTreeMap::new();
857+
858+
for profile in &self.additional_compiler_profiles {
859+
let mut settings = base.clone();
860+
profile.apply(&mut settings);
861+
map.insert(profile.name.clone(), settings);
862+
}
863+
864+
map
865+
}
866+
867+
/// Resolves globs and builds a mapping from individual source files to their restrictions
868+
fn restrictions(
869+
&self,
870+
paths: &ProjectPathsConfig,
871+
) -> Result<BTreeMap<PathBuf, RestrictionsWithVersion<MultiCompilerRestrictions>>, SolcError>
872+
{
873+
let mut map = BTreeMap::new();
874+
875+
let graph = Graph::<MultiCompilerParsedSource>::resolve(paths)?;
876+
let (sources, _) = graph.into_sources();
877+
878+
for res in &self.compilation_restrictions {
879+
for source in sources.keys().filter(|path| {
880+
if res.paths.is_match(path) {
881+
true
882+
} else if let Ok(path) = path.strip_prefix(&paths.root) {
883+
res.paths.is_match(path)
884+
} else {
885+
false
886+
}
887+
}) {
888+
let res: RestrictionsWithVersion<_> = res.clone().into();
889+
if !map.contains_key(source) {
890+
map.insert(source.clone(), res);
891+
} else {
892+
map.get_mut(source.as_path()).unwrap().merge(res);
893+
}
894+
}
895+
}
896+
897+
Ok(map)
898+
}
899+
838900
/// Creates a [Project] with the given `cached` and `no_artifacts` flags
839901
pub fn create_project(&self, cached: bool, no_artifacts: bool) -> Result<Project, SolcError> {
902+
let settings = self.compiler_settings()?;
903+
let paths = self.project_paths();
840904
let mut builder = Project::builder()
841905
.artifacts(self.configured_artifacts_handler())
842-
.paths(self.project_paths())
843-
.settings(self.compiler_settings()?)
906+
.additional_settings(self.additional_settings(&settings))
907+
.restrictions(self.restrictions(&paths)?)
908+
.settings(settings)
909+
.paths(paths)
844910
.ignore_error_codes(self.ignored_error_codes.iter().copied().map(Into::into))
845911
.ignore_paths(self.ignored_file_paths.clone())
846912
.set_compiler_severity_filter(if self.deny_warnings {
@@ -2182,6 +2248,8 @@ impl Default for Config {
21822248
eof_version: None,
21832249
alphanet: false,
21842250
transaction_timeout: 120,
2251+
additional_compiler_profiles: Default::default(),
2252+
compilation_restrictions: vec![],
21852253
_non_exhaustive: (),
21862254
}
21872255
}

0 commit comments

Comments
 (0)