Support multiple compiler versions (#92)

* Allow for downloader to use version requirements.

We will soon add support for the compiler version requirement from the
metadata files to be honored. The compiler version is specified in the
solc modes section of the file and its specified as a `VersionReq` and
not as a version.

Therefore, we need to have the ability to honor this version requirement
and find the best version that satisfies the requirement.

* Request `VersionOrRequirement` in compiler interface

* Honor the compiler version requirement in metadata

This commit honors the compiler version requirement listed in the solc
modes of the metadata file. If this version requirement is provided then
it overrides what was passed in the CLI. Otherwise, the CLI version will
be used.

* Make compiler IO completely generic.

Before this commit, the types that were used for the compiler input and
output were the resolc compiler types which was a leaky abstraction as
we have traits to abstract the compilers away but we expose their
internal types out to other crates.

This commit did the following:
1. Made the compiler IO types fully generic so that all of the logic for
   constructing the map of compiled contracts is all done by the
   compiler implementation and not by the consuming code.
2. Changed the input types used for Solc to be the forge standard JSON
   types for Solc instead of resolc.

* Fix machete

* Add resolc to CI

* Add resolc to CI

* Add resolc to CI

* Add resolc to CI
This commit is contained in:
Omar
2025-07-30 07:56:23 +03:00
committed by GitHub
parent 4db7009640
commit f51693cb9f
26 changed files with 838 additions and 370 deletions
+38 -13
View File
@@ -5,6 +5,8 @@ use std::{
sync::{LazyLock, Mutex},
};
use revive_dt_common::types::VersionOrRequirement;
use semver::Version;
use sha2::{Digest, Sha256};
@@ -52,27 +54,50 @@ impl GHDownloader {
pub const WINDOWS_NAME: &str = "solc-windows.exe";
pub const WASM_NAME: &str = "soljson.js";
fn new(version: Version, target: &'static str, list: &'static str) -> Self {
Self {
version,
target,
list,
fn new(
version: impl Into<VersionOrRequirement>,
target: &'static str,
list: &'static str,
) -> anyhow::Result<Self> {
let version_or_requirement = version.into();
match version_or_requirement {
VersionOrRequirement::Version(version) => Ok(Self {
version,
target,
list,
}),
VersionOrRequirement::Requirement(requirement) => {
let Some(version) = List::download(list)?
.builds
.into_iter()
.map(|build| build.version)
.filter(|version| requirement.matches(version))
.max()
else {
anyhow::bail!("Failed to find a version that satisfies {requirement:?}");
};
Ok(Self {
version,
target,
list,
})
}
}
}
pub fn linux(version: Version) -> Self {
pub fn linux(version: impl Into<VersionOrRequirement>) -> anyhow::Result<Self> {
Self::new(version, Self::LINUX_NAME, List::LINUX_URL)
}
pub fn macosx(version: Version) -> Self {
pub fn macosx(version: impl Into<VersionOrRequirement>) -> anyhow::Result<Self> {
Self::new(version, Self::MACOSX_NAME, List::MACOSX_URL)
}
pub fn windows(version: Version) -> Self {
pub fn windows(version: impl Into<VersionOrRequirement>) -> anyhow::Result<Self> {
Self::new(version, Self::WINDOWS_NAME, List::WINDOWS_URL)
}
pub fn wasm(version: Version) -> Self {
pub fn wasm(version: impl Into<VersionOrRequirement>) -> anyhow::Result<Self> {
Self::new(version, Self::WASM_NAME, List::WASM_URL)
}
@@ -111,24 +136,24 @@ mod tests {
#[test]
fn try_get_windows() {
let version = List::download(List::WINDOWS_URL).unwrap().latest_release;
GHDownloader::windows(version).download().unwrap();
GHDownloader::windows(version).unwrap().download().unwrap();
}
#[test]
fn try_get_macosx() {
let version = List::download(List::MACOSX_URL).unwrap().latest_release;
GHDownloader::macosx(version).download().unwrap();
GHDownloader::macosx(version).unwrap().download().unwrap();
}
#[test]
fn try_get_linux() {
let version = List::download(List::LINUX_URL).unwrap().latest_release;
GHDownloader::linux(version).download().unwrap();
GHDownloader::linux(version).unwrap().download().unwrap();
}
#[test]
fn try_get_wasm() {
let version = List::download(List::WASM_URL).unwrap().latest_release;
GHDownloader::wasm(version).download().unwrap();
GHDownloader::wasm(version).unwrap().download().unwrap();
}
}
+4 -3
View File
@@ -7,7 +7,8 @@ use std::path::{Path, PathBuf};
use cache::get_or_download;
use download::GHDownloader;
use semver::Version;
use revive_dt_common::types::VersionOrRequirement;
pub mod cache;
pub mod download;
@@ -20,7 +21,7 @@ pub mod list;
/// and not download it again.
pub fn download_solc(
cache_directory: &Path,
version: Version,
version: impl Into<VersionOrRequirement>,
wasm: bool,
) -> anyhow::Result<PathBuf> {
let downloader = if wasm {
@@ -33,7 +34,7 @@ pub fn download_solc(
GHDownloader::windows(version)
} else {
unimplemented!()
};
}?;
get_or_download(cache_directory, &downloader)
}