Skip to content

Commit

Permalink
feat: better extra_args handling
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr committed Oct 1, 2024
1 parent 940cc24 commit 9a84423
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 16 deletions.
20 changes: 12 additions & 8 deletions crates/compilers/src/compilers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,19 +278,23 @@ pub trait Compiler: Send + Sync + Clone {

pub(crate) fn cache_version(
path: PathBuf,
args: &Vec<String>,
f: impl FnOnce(&Path) -> Result<Version>,
) -> Result<Version> {
static VERSION_CACHE: OnceLock<Mutex<HashMap<PathBuf, Version>>> = OnceLock::new();
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.clone(), version.clone());

Ok(version)
}
31 changes: 25 additions & 6 deletions crates/compilers/src/compilers/solc/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,28 @@ impl Solc {
/// Returns error if `solc` is not found in the system or if the version cannot be retrieved.
pub fn new(path: impl Into<PathBuf>) -> Result<Self> {
let path = path.into();
let version = Self::version(path.clone())?;
let version = Self::version(path.clone(), &Vec::new())?;
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();
let path = path.into();
let version = Self::version(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 @@ -428,10 +446,11 @@ 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| {
pub fn version(solc: impl Into<PathBuf>, args: &Vec<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 +473,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 +498,6 @@ impl Solc {
cmd.current_dir(base_path);
}

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

cmd
Expand Down Expand Up @@ -624,7 +643,7 @@ mod tests {

#[test]
fn solc_version_works() {
Solc::version(solc().solc).unwrap();
Solc::version(solc().solc, &Vec::new()).unwrap();
}

#[test]
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(), &Vec::new(), |vyper| {
let mut cmd = Command::new(vyper);
cmd.arg("--version")
.stdin(Stdio::piped())
Expand Down

0 comments on commit 9a84423

Please sign in to comment.