Sitelet https://github.com/voronor/compilers/commit/db66310c33e48fbac456079a6fb57e3ef4a54c1e
Skip to content

Commit db66310

Browse files
authored
feat: allow passing extra cli args to solc + some cleanup (foundry-rs#171)
This refactors `Compiler` a bit moving some of the configuration methods from `CompilerInput` to `CompilerSettings`, preferring sanitization of settings during input construction instead of in `with_*` methods of version-aware input. Instead of using JSON solc settings, I've added separate `SolcSettings` type divided into JSON and CLI settings
1 parent b04423c commit db66310

15 files changed

Lines changed: 241 additions & 178 deletions

File tree

‎crates/artifacts/solc/src/lib.rs‎

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,12 @@ impl SolcInput {
133133
/// This will remove/adjust values in the [`SolcInput`] that are not compatible with this
134134
/// version
135135
pub fn sanitize(&mut self, version: &Version) {
136-
self.settings.sanitize(version)
136+
self.settings.sanitize(version, self.language);
137137
}
138138

139139
/// Consumes the type and returns a [SolcInput::sanitized] version
140140
pub fn sanitized(mut self, version: &Version) -> Self {
141-
self.settings.sanitize(version);
141+
self.settings.sanitize(version, self.language);
142142
self
143143
}
144144

@@ -178,18 +178,6 @@ impl SolcInput {
178178
pub fn is_yul(&self) -> bool {
179179
self.language == SolcLanguage::Yul
180180
}
181-
182-
pub fn with_remappings(mut self, remappings: Vec<Remapping>) -> Self {
183-
if self.language == SolcLanguage::Yul {
184-
if !remappings.is_empty() {
185-
warn!("omitting remappings supplied for the yul sources");
186-
}
187-
} else {
188-
self.settings.remappings = remappings;
189-
}
190-
191-
self
192-
}
193181
}
194182

195183
/// A `CompilerInput` representation used for verify
@@ -292,13 +280,13 @@ impl Settings {
292280
}
293281

294282
/// Consumes the type and returns a [Settings::sanitize] version
295-
pub fn sanitized(mut self, version: &Version) -> Self {
296-
self.sanitize(version);
283+
pub fn sanitized(mut self, version: &Version, language: SolcLanguage) -> Self {
284+
self.sanitize(version, language);
297285
self
298286
}
299287

300288
/// This will remove/adjust values in the settings that are not compatible with this version.
301-
pub fn sanitize(&mut self, version: &Version) {
289+
pub fn sanitize(&mut self, version: &Version, language: SolcLanguage) {
302290
const V0_6_0: Version = Version::new(0, 6, 0);
303291
if *version < V0_6_0 {
304292
if let Some(meta) = &mut self.metadata {
@@ -364,6 +352,13 @@ impl Settings {
364352
if let Some(ref mut evm_version) = self.evm_version {
365353
self.evm_version = evm_version.normalize_version_solc(version);
366354
}
355+
356+
if language == SolcLanguage::Yul {
357+
if !self.remappings.is_empty() {
358+
warn!("omitting remappings supplied for the yul sources");
359+
}
360+
self.remappings = Vec::new();
361+
}
367362
}
368363

369364
/// Inserts a set of `ContractOutputSelection`

‎crates/artifacts/vyper/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ foundry-compilers-core.workspace = true
2121
serde.workspace = true
2222
alloy-primitives.workspace = true
2323
alloy-json-abi.workspace = true
24+
semver.workspace = true
2425

2526
[target.'cfg(windows)'.dependencies]
2627
path-slash.workspace = true

‎crates/artifacts/vyper/src/input.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::VyperSettings;
22
use foundry_compilers_artifacts_solc::sources::Sources;
33
use foundry_compilers_core::utils::strip_prefix_owned;
4+
use semver::Version;
45
use serde::{Deserialize, Serialize};
56
use std::path::Path;
67

@@ -47,4 +48,16 @@ impl VyperInput {
4748

4849
self.settings.strip_prefix(base)
4950
}
51+
52+
/// This will remove/adjust values in the [`VyperInput`] that are not compatible with this
53+
/// version
54+
pub fn sanitize(&mut self, version: &Version) {
55+
self.settings.sanitize(version);
56+
}
57+
58+
/// Consumes the type and returns a [VyperInput::sanitized] version
59+
pub fn sanitized(mut self, version: &Version) -> Self {
60+
self.sanitize(version);
61+
self
62+
}
5063
}

‎crates/artifacts/vyper/src/settings.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
use foundry_compilers_artifacts_solc::{
22
output_selection::OutputSelection, serde_helpers, EvmVersion,
33
};
4+
use semver::Version;
45
use serde::{Deserialize, Serialize};
56
use std::{
67
collections::BTreeSet,
78
path::{Path, PathBuf},
89
};
910

11+
pub const VYPER_SEARCH_PATHS: Version = Version::new(0, 4, 0);
12+
1013
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1114
#[serde(rename_all = "lowercase")]
1215
pub enum VyperOptimizationMode {
@@ -68,4 +71,19 @@ impl VyperSettings {
6871
})
6972
});
7073
}
74+
75+
/// Sanitize the settings based on the compiler version.
76+
pub fn sanitize(&mut self, version: &Version) {
77+
if version < &VYPER_SEARCH_PATHS {
78+
self.search_paths = None;
79+
}
80+
81+
self.sanitize_output_selection();
82+
}
83+
84+
/// Sanitize the settings based on the compiler version.
85+
pub fn sanitized(mut self, version: &Version) -> Self {
86+
self.sanitize(version);
87+
self
88+
}
7189
}

‎crates/compilers/src/cache.rs‎

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ impl<S: CompilerSettings> CompilerCache<S> {
103103
/// # Examples
104104
#[cfg_attr(not(feature = "svm-solc"), doc = "```ignore")]
105105
/// ```no_run
106-
/// use foundry_compilers::{artifacts::Settings, cache::CompilerCache, Project};
106+
/// use foundry_compilers::{cache::CompilerCache, solc::SolcSettings, Project};
107107
///
108108
/// let project = Project::builder().build(Default::default())?;
109-
/// let mut cache = CompilerCache::<Settings>::read(project.cache_path())?;
109+
/// let mut cache = CompilerCache::<SolcSettings>::read(project.cache_path())?;
110110
/// cache.join_artifacts_files(project.artifacts_path());
111111
/// # Ok::<_, Box<dyn std::error::Error>>(())
112112
/// ```
@@ -129,10 +129,10 @@ impl<S: CompilerSettings> CompilerCache<S> {
129129
/// # Examples
130130
#[cfg_attr(not(feature = "svm-solc"), doc = "```ignore")]
131131
/// ```no_run
132-
/// use foundry_compilers::{artifacts::Settings, cache::CompilerCache, Project};
132+
/// use foundry_compilers::{cache::CompilerCache, solc::SolcSettings, Project};
133133
///
134134
/// let project = Project::builder().build(Default::default())?;
135-
/// let cache: CompilerCache<Settings> = CompilerCache::read_joined(&project.paths)?;
135+
/// let cache: CompilerCache<SolcSettings> = CompilerCache::read_joined(&project.paths)?;
136136
/// # Ok::<_, Box<dyn std::error::Error>>(())
137137
/// ```
138138
pub fn read_joined<L>(paths: &ProjectPathsConfig<L>) -> Result<Self> {
@@ -210,13 +210,11 @@ impl<S: CompilerSettings> CompilerCache<S> {
210210
#[cfg_attr(not(feature = "svm-solc"), doc = "```ignore")]
211211
/// ```no_run
212212
/// use foundry_compilers::{
213-
/// artifacts::{contract::CompactContract, Settings},
214-
/// cache::CompilerCache,
215-
/// Project,
213+
/// artifacts::contract::CompactContract, cache::CompilerCache, solc::SolcSettings, Project,
216214
/// };
217215
///
218216
/// let project = Project::builder().build(Default::default())?;
219-
/// let cache: CompilerCache<Settings> =
217+
/// let cache: CompilerCache<SolcSettings> =
220218
/// CompilerCache::read(project.cache_path())?.with_stripped_file_prefixes(project.root());
221219
/// let artifact: CompactContract = cache.read_artifact("src/Greeter.sol".as_ref(), "Greeter")?;
222220
/// # Ok::<_, Box<dyn std::error::Error>>(())
@@ -237,10 +235,10 @@ impl<S: CompilerSettings> CompilerCache<S> {
237235
/// # Examples
238236
#[cfg_attr(not(feature = "svm-solc"), doc = "```ignore")]
239237
/// ```no_run
240-
/// use foundry_compilers::{artifacts::Settings, cache::CompilerCache, Project};
238+
/// use foundry_compilers::{cache::CompilerCache, solc::SolcSettings, Project};
241239
///
242240
/// let project = Project::builder().build(Default::default())?;
243-
/// let cache: CompilerCache<Settings> = CompilerCache::read_joined(&project.paths)?;
241+
/// let cache: CompilerCache<SolcSettings> = CompilerCache::read_joined(&project.paths)?;
244242
/// cache.find_artifact_path("/Users/git/myproject/src/Greeter.sol".as_ref(), "Greeter");
245243
/// # Ok::<_, Box<dyn std::error::Error>>(())
246244
/// ```
@@ -256,13 +254,11 @@ impl<S: CompilerSettings> CompilerCache<S> {
256254
#[cfg_attr(not(feature = "svm-solc"), doc = "```ignore")]
257255
/// ```no_run
258256
/// use foundry_compilers::{
259-
/// artifacts::{contract::CompactContract, Settings},
260-
/// cache::CompilerCache,
261-
/// Project,
257+
/// artifacts::contract::CompactContract, cache::CompilerCache, solc::SolcSettings, Project,
262258
/// };
263259
///
264260
/// let project = Project::builder().build(Default::default())?;
265-
/// let cache = CompilerCache::<Settings>::read_joined(&project.paths)?;
261+
/// let cache = CompilerCache::<SolcSettings>::read_joined(&project.paths)?;
266262
/// let artifact: CompactContract =
267263
/// cache.read_artifact("/Users/git/myproject/src/Greeter.sol".as_ref(), "Greeter")?;
268264
/// # Ok::<_, Box<dyn std::error::Error>>(())
@@ -288,13 +284,12 @@ impl<S: CompilerSettings> CompilerCache<S> {
288284
#[cfg_attr(not(feature = "svm-solc"), doc = "```ignore")]
289285
/// ```no_run
290286
/// use foundry_compilers::{
291-
/// artifacts::{contract::CompactContractBytecode, Settings},
292-
/// cache::CompilerCache,
287+
/// artifacts::contract::CompactContractBytecode, cache::CompilerCache, solc::SolcSettings,
293288
/// Project,
294289
/// };
295290
///
296291
/// let project = Project::builder().build(Default::default())?;
297-
/// let cache: CompilerCache<Settings> = CompilerCache::read_joined(&project.paths)?;
292+
/// let cache: CompilerCache<SolcSettings> = CompilerCache::read_joined(&project.paths)?;
298293
/// let artifacts = cache.read_artifacts::<CompactContractBytecode>()?;
299294
/// # Ok::<_, Box<dyn std::error::Error>>(())
300295
/// ```

‎crates/compilers/src/compile/project.rs‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ use crate::{
109109
output::{AggregatedCompilerOutput, Builds},
110110
report,
111111
resolver::GraphEdges,
112-
ArtifactOutput, Graph, Project, ProjectCompileOutput, Sources,
112+
ArtifactOutput, CompilerSettings, Graph, Project, ProjectCompileOutput, Sources,
113113
};
114114
use foundry_compilers_core::error::Result;
115115
use rayon::prelude::*;
@@ -447,11 +447,13 @@ impl<L: Language> CompilerSources<L> {
447447

448448
trace!("calling {} with {} sources {:?}", version, sources.len(), sources.keys());
449449

450-
let mut input = C::Input::build(sources, opt_settings, language, version.clone())
451-
.with_base_path(project.paths.root.clone())
452-
.with_allow_paths(project.paths.allowed_paths.clone())
453-
.with_include_paths(include_paths.clone())
454-
.with_remappings(project.paths.remappings.clone());
450+
let settings = opt_settings
451+
.with_base_path(&project.paths.root)
452+
.with_allow_paths(&project.paths.allowed_paths)
453+
.with_include_paths(&include_paths)
454+
.with_remappings(&project.paths.remappings);
455+
456+
let mut input = C::Input::build(sources, settings, language, version.clone());
455457

456458
input.strip_prefix(project.paths.root.as_path());
457459

‎crates/compilers/src/compilers/mod.rs‎

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,29 @@ pub trait CompilerSettings:
7474
/// Ensures that all settings fields are equal except for `output_selection` which is required
7575
/// to be a subset of `cached.output_selection`.
7676
fn can_use_cached(&self, other: &Self) -> bool;
77+
78+
/// Method which might be invoked to add remappings to the input.
79+
fn with_remappings(self, _remappings: &[Remapping]) -> Self {
80+
self
81+
}
82+
83+
/// Builder method to set the base path for the compiler. Primarily used by solc implementation
84+
/// to se --base-path.
85+
fn with_base_path(self, _base_path: &Path) -> Self {
86+
self
87+
}
88+
89+
/// Builder method to set the allowed paths for the compiler. Primarily used by solc
90+
/// implementation to set --allow-paths.
91+
fn with_allow_paths(self, _allowed_paths: &BTreeSet<PathBuf>) -> Self {
92+
self
93+
}
94+
95+
/// Builder method to set the include paths for the compiler. Primarily used by solc
96+
/// implementation to set --include-paths.
97+
fn with_include_paths(self, _include_paths: &BTreeSet<PathBuf>) -> Self {
98+
self
99+
}
77100
}
78101

79102
/// Input of a compiler, including sources and settings used for their compilation.
@@ -101,29 +124,6 @@ pub trait CompilerInput: Serialize + Send + Sync + Sized + Debug {
101124
/// Returns compiler name used by reporters to display output during compilation.
102125
fn compiler_name(&self) -> Cow<'static, str>;
103126

104-
/// Method which might be invoked to add remappings to the input.
105-
fn with_remappings(self, _remappings: Vec<Remapping>) -> Self {
106-
self
107-
}
108-
109-
/// Builder method to set the base path for the compiler. Primarily used by solc implementation
110-
/// to se --base-path.
111-
fn with_base_path(self, _base_path: PathBuf) -> Self {
112-
self
113-
}
114-
115-
/// Builder method to set the allowed paths for the compiler. Primarily used by solc
116-
/// implementation to set --allow-paths.
117-
fn with_allow_paths(self, _allowed_paths: BTreeSet<PathBuf>) -> Self {
118-
self
119-
}
120-
121-
/// Builder method to set the include paths for the compiler. Primarily used by solc
122-
/// implementation to set --include-paths.
123-
fn with_include_paths(self, _include_paths: BTreeSet<PathBuf>) -> Self {
124-
self
125-
}
126-
127127
/// Strips given prefix from all paths.
128128
fn strip_prefix(&mut self, base: &Path);
129129
}

‎crates/compilers/src/compilers/multi.rs‎

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ use super::{
1010
use crate::{
1111
artifacts::vyper::{VyperCompilationError, VyperSettings},
1212
resolver::parse::SolData,
13+
solc::SolcSettings,
1314
};
1415
use foundry_compilers_artifacts::{
1516
error::SourceLocation,
1617
output_selection::OutputSelection,
1718
remappings::Remapping,
1819
sources::{Source, Sources},
19-
Error, Settings as SolcSettings, Severity, SolcLanguage,
20+
Error, Severity, SolcLanguage,
2021
};
2122
use foundry_compilers_core::error::{Result, SolcError};
2223
use semver::Version;
@@ -137,8 +138,36 @@ impl CompilerSettings for MultiCompilerSettings {
137138
}
138139

139140
fn update_output_selection(&mut self, f: impl FnOnce(&mut OutputSelection) + Copy) {
140-
f(&mut self.solc.output_selection);
141-
f(&mut self.vyper.output_selection);
141+
self.solc.update_output_selection(f);
142+
self.vyper.update_output_selection(f);
143+
}
144+
145+
fn with_allow_paths(self, allowed_paths: &BTreeSet<PathBuf>) -> Self {
146+
Self {
147+
solc: self.solc.with_allow_paths(allowed_paths),
148+
vyper: self.vyper.with_allow_paths(allowed_paths),
149+
}
150+
}
151+
152+
fn with_base_path(self, base_path: &Path) -> Self {
153+
Self {
154+
solc: self.solc.with_base_path(base_path),
155+
vyper: self.vyper.with_base_path(base_path),
156+
}
157+
}
158+
159+
fn with_include_paths(self, include_paths: &BTreeSet<PathBuf>) -> Self {
160+
Self {
161+
solc: self.solc.with_include_paths(include_paths),
162+
vyper: self.vyper.with_include_paths(include_paths),
163+
}
164+
}
165+
166+
fn with_remappings(self, remappings: &[Remapping]) -> Self {
167+
Self {
168+
solc: self.solc.with_remappings(remappings),
169+
vyper: self.vyper.with_remappings(remappings),
170+
}
142171
}
143172
}
144173

@@ -210,34 +239,6 @@ impl CompilerInput for MultiCompilerInput {
210239
}
211240
}
212241

213-
fn with_allow_paths(self, allowed_paths: BTreeSet<PathBuf>) -> Self {
214-
match self {
215-
Self::Solc(input) => Self::Solc(input.with_allow_paths(allowed_paths)),
216-
Self::Vyper(input) => Self::Vyper(input.with_allow_paths(allowed_paths)),
217-
}
218-
}
219-
220-
fn with_base_path(self, base_path: PathBuf) -> Self {
221-
match self {
222-
Self::Solc(input) => Self::Solc(input.with_base_path(base_path)),
223-
Self::Vyper(input) => Self::Vyper(input.with_base_path(base_path)),
224-
}
225-
}
226-
227-
fn with_include_paths(self, include_paths: BTreeSet<PathBuf>) -> Self {
228-
match self {
229-
Self::Solc(input) => Self::Solc(input.with_include_paths(include_paths)),
230-
Self::Vyper(input) => Self::Vyper(input.with_include_paths(include_paths)),
231-
}
232-
}
233-
234-
fn with_remappings(self, remappings: Vec<Remapping>) -> Self {
235-
match self {
236-
Self::Solc(input) => Self::Solc(input.with_remappings(remappings)),
237-
Self::Vyper(input) => Self::Vyper(input.with_remappings(remappings)),
238-
}
239-
}
240-
241242
fn sources(&self) -> impl Iterator<Item = (&Path, &Source)> {
242243
let ret: Box<dyn Iterator<Item = _>> = match self {
243244
Self::Solc(input) => Box::new(input.sources()),

0 commit comments

Comments
 (0)