Skip to content

Commit c3771e5

Browse files
authored
feat: better extra_args handling (#208)
ref foundry-rs/foundry#8997 Adds `Solc` constructor for creating solc instances with arguments. Changes `extra_args` to being prepended to actual solc arguments instead of appended as for now. This allows us to use eof binary through `Solc::new_with_args("docker", ["run", ... ])` We didn't end up using those for `--eof-version`, so this shouldn't break anything. Will add a test for this in scope `--eof` flag on foundry side
1 parent 940cc24 commit c3771e5

File tree

4 files changed

+43
-13
lines changed

4 files changed

+43
-13
lines changed

crates/compilers/src/compilers/mod.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -278,19 +278,24 @@ pub trait Compiler: Send + Sync + Clone {
278278

279279
pub(crate) fn cache_version(
280280
path: PathBuf,
281+
args: &[String],
281282
f: impl FnOnce(&Path) -> Result<Version>,
282283
) -> Result<Version> {
283-
static VERSION_CACHE: OnceLock<Mutex<HashMap<PathBuf, Version>>> = OnceLock::new();
284+
#[allow(clippy::complexity)]
285+
static VERSION_CACHE: OnceLock<Mutex<HashMap<PathBuf, HashMap<Vec<String>, Version>>>> =
286+
OnceLock::new();
284287
let mut lock = VERSION_CACHE
285288
.get_or_init(|| Mutex::new(HashMap::new()))
286289
.lock()
287290
.unwrap_or_else(std::sync::PoisonError::into_inner);
288-
Ok(match lock.entry(path) {
289-
std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(),
290-
std::collections::hash_map::Entry::Vacant(entry) => {
291-
let value = f(entry.key())?;
292-
entry.insert(value)
293-
}
291+
292+
if let Some(version) = lock.get(&path).and_then(|versions| versions.get(args)) {
293+
return Ok(version.clone());
294294
}
295-
.clone())
295+
296+
let version = f(&path)?;
297+
298+
lock.entry(path).or_default().insert(args.to_vec(), version.clone());
299+
300+
Ok(version)
296301
}

crates/compilers/src/compilers/solc/compiler.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ impl Solc {
9494
Ok(Self::new_with_version(path, version))
9595
}
9696

97+
/// A new instance which points to `solc` with additional cli arguments. Invokes `solc
98+
/// --version` to determine the version.
99+
///
100+
/// Returns error if `solc` is not found in the system or if the version cannot be retrieved.
101+
pub fn new_with_args(
102+
path: impl Into<PathBuf>,
103+
extra_args: impl IntoIterator<Item: Into<String>>,
104+
) -> Result<Self> {
105+
let args = extra_args.into_iter().map(Into::into).collect::<Vec<_>>();
106+
let path = path.into();
107+
let version = Self::version_with_args(path.clone(), &args)?;
108+
109+
let mut solc = Self::new_with_version(path, version);
110+
solc.extra_args = args;
111+
112+
Ok(solc)
113+
}
114+
97115
/// A new instance which points to `solc` with the given version
98116
pub fn new_with_version(path: impl Into<PathBuf>, version: Version) -> Self {
99117
Self {
@@ -429,9 +447,16 @@ impl Solc {
429447
/// Invokes `solc --version` and parses the output as a SemVer [`Version`].
430448
#[instrument(level = "debug", skip_all)]
431449
pub fn version(solc: impl Into<PathBuf>) -> Result<Version> {
432-
crate::cache_version(solc.into(), |solc| {
450+
Self::version_with_args(solc, &[])
451+
}
452+
453+
/// Invokes `solc --version` and parses the output as a SemVer [`Version`].
454+
#[instrument(level = "debug", skip_all)]
455+
pub fn version_with_args(solc: impl Into<PathBuf>, args: &[String]) -> Result<Version> {
456+
crate::cache_version(solc.into(), args, |solc| {
433457
let mut cmd = Command::new(solc);
434-
cmd.arg("--version")
458+
cmd.args(args)
459+
.arg("--version")
435460
.stdin(Stdio::piped())
436461
.stderr(Stdio::piped())
437462
.stdout(Stdio::piped());
@@ -454,6 +479,7 @@ impl Solc {
454479
pub fn configure_cmd(&self) -> Command {
455480
let mut cmd = Command::new(&self.solc);
456481
cmd.stdin(Stdio::piped()).stderr(Stdio::piped()).stdout(Stdio::piped());
482+
cmd.args(&self.extra_args);
457483

458484
if !self.allow_paths.is_empty() {
459485
cmd.arg("--allow-paths");
@@ -478,7 +504,6 @@ impl Solc {
478504
cmd.current_dir(base_path);
479505
}
480506

481-
cmd.args(&self.extra_args);
482507
cmd.arg("--standard-json");
483508

484509
cmd

crates/compilers/src/compilers/solc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl Compiler for SolcCompiler {
5555
solc.base_path.clone_from(&input.cli_settings.base_path);
5656
solc.allow_paths.clone_from(&input.cli_settings.allow_paths);
5757
solc.include_paths.clone_from(&input.cli_settings.include_paths);
58-
solc.extra_args.clone_from(&input.cli_settings.extra_args);
58+
solc.extra_args.extend_from_slice(&input.cli_settings.extra_args);
5959

6060
let solc_output = solc.compile(&input.input)?;
6161

crates/compilers/src/compilers/vyper/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl Vyper {
166166
/// Invokes `vyper --version` and parses the output as a SemVer [`Version`].
167167
#[instrument(level = "debug", skip_all)]
168168
pub fn version(vyper: impl Into<PathBuf>) -> Result<Version> {
169-
crate::cache_version(vyper.into(), |vyper| {
169+
crate::cache_version(vyper.into(), &[], |vyper| {
170170
let mut cmd = Command::new(vyper);
171171
cmd.arg("--version")
172172
.stdin(Stdio::piped())

0 commit comments

Comments
 (0)