Skip to content

Commit

Permalink
feat: better extra_args handling (#208)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
klkvr authored Oct 1, 2024
1 parent 940cc24 commit c3771e5
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
21 changes: 13 additions & 8 deletions crates/compilers/src/compilers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,19 +278,24 @@ pub trait Compiler: Send + Sync + Clone {

pub(crate) fn cache_version(
path: PathBuf,
args: &[String],
f: impl FnOnce(&Path) -> Result<Version>,
) -> Result<Version> {
static VERSION_CACHE: OnceLock<Mutex<HashMap<PathBuf, Version>>> = OnceLock::new();
#[allow(clippy::complexity)]
static VERSION_CACHE: OnceLock<Mutex<HashMap<PathBuf, HashMap<Vec<String>, Version>>>> =
OnceLock::new();
let mut lock = VERSION_CACHE
.get_or_init(|| Mutex::new(HashMap::new()))
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
Ok(match lock.entry(path) {
std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(),
std::collections::hash_map::Entry::Vacant(entry) => {
let value = f(entry.key())?;
entry.insert(value)
}

if let Some(version) = lock.get(&path).and_then(|versions| versions.get(args)) {
return Ok(version.clone());
}
.clone())

let version = f(&path)?;

lock.entry(path).or_default().insert(args.to_vec(), version.clone());

Ok(version)
}
31 changes: 28 additions & 3 deletions crates/compilers/src/compilers/solc/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,24 @@ impl Solc {
Ok(Self::new_with_version(path, version))
}

/// A new instance which points to `solc` with additional cli arguments. Invokes `solc
/// --version` to determine the version.
///
/// Returns error if `solc` is not found in the system or if the version cannot be retrieved.
pub fn new_with_args(
path: impl Into<PathBuf>,
extra_args: impl IntoIterator<Item: Into<String>>,
) -> Result<Self> {
let args = extra_args.into_iter().map(Into::into).collect::<Vec<_>>();
let path = path.into();
let version = Self::version_with_args(path.clone(), &args)?;

let mut solc = Self::new_with_version(path, version);
solc.extra_args = args;

Ok(solc)
}

/// A new instance which points to `solc` with the given version
pub fn new_with_version(path: impl Into<PathBuf>, version: Version) -> Self {
Self {
Expand Down Expand Up @@ -429,9 +447,16 @@ impl Solc {
/// Invokes `solc --version` and parses the output as a SemVer [`Version`].
#[instrument(level = "debug", skip_all)]
pub fn version(solc: impl Into<PathBuf>) -> Result<Version> {
crate::cache_version(solc.into(), |solc| {
Self::version_with_args(solc, &[])
}

/// Invokes `solc --version` and parses the output as a SemVer [`Version`].
#[instrument(level = "debug", skip_all)]
pub fn version_with_args(solc: impl Into<PathBuf>, args: &[String]) -> Result<Version> {
crate::cache_version(solc.into(), args, |solc| {
let mut cmd = Command::new(solc);
cmd.arg("--version")
cmd.args(args)
.arg("--version")
.stdin(Stdio::piped())
.stderr(Stdio::piped())
.stdout(Stdio::piped());
Expand All @@ -454,6 +479,7 @@ impl Solc {
pub fn configure_cmd(&self) -> Command {
let mut cmd = Command::new(&self.solc);
cmd.stdin(Stdio::piped()).stderr(Stdio::piped()).stdout(Stdio::piped());
cmd.args(&self.extra_args);

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

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

cmd
Expand Down
2 changes: 1 addition & 1 deletion crates/compilers/src/compilers/solc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Compiler for SolcCompiler {
solc.base_path.clone_from(&input.cli_settings.base_path);
solc.allow_paths.clone_from(&input.cli_settings.allow_paths);
solc.include_paths.clone_from(&input.cli_settings.include_paths);
solc.extra_args.clone_from(&input.cli_settings.extra_args);
solc.extra_args.extend_from_slice(&input.cli_settings.extra_args);

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

Expand Down
2 changes: 1 addition & 1 deletion crates/compilers/src/compilers/vyper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl Vyper {
/// Invokes `vyper --version` and parses the output as a SemVer [`Version`].
#[instrument(level = "debug", skip_all)]
pub fn version(vyper: impl Into<PathBuf>) -> Result<Version> {
crate::cache_version(vyper.into(), |vyper| {
crate::cache_version(vyper.into(), &[], |vyper| {
let mut cmd = Command::new(vyper);
cmd.arg("--version")
.stdin(Stdio::piped())
Expand Down

0 comments on commit c3771e5

Please sign in to comment.