Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
60154e0
Compute and add bytecode hashes to the report.
elle-j Feb 16, 2026
d97c8b4
Update hash type to fixed-size byte array.
elle-j Feb 16, 2026
1b8113b
Remove leftover clone.
elle-j Feb 16, 2026
2312786
Hex decode the bytecode string prior to hashing.
elle-j Feb 16, 2026
e442719
Add additional comment to info field.
elle-j Feb 16, 2026
88b26b5
Implement the Compile context/subcommand.
elle-j Feb 17, 2026
e30302b
Implement driver and reporter for the compile subcommand.
elle-j Feb 19, 2026
0d7fdca
Refactor runner_event macros to improve readability and maintainability.
elle-j Feb 19, 2026
27a7bbb
Implement CLI reporting for standalone compile mode.
elle-j Feb 20, 2026
d9f5363
Fix clippy.
elle-j Feb 20, 2026
dc5077f
Merge branch 'main' into lj/compile-context
elle-j Feb 20, 2026
b884fa9
Key compilation information in report by mode.
elle-j Feb 20, 2026
5934bdb
Prepare multi-mode support.
elle-j Feb 20, 2026
4481128
Add compatibility check for pragma solidity version.
elle-j Feb 23, 2026
921c187
Minor docs and structure update.
elle-j Feb 23, 2026
28d1cbc
Move compilation reports onto the MetadataFileReport.
elle-j Feb 24, 2026
fe0cc4b
Remove build_label from context for now.
elle-j Feb 24, 2026
aa8f68a
Share pre-link comp events between execution and standalone contexts.
elle-j Feb 25, 2026
3edf5f9
Remove unnecessary ignore check for compilation.
elle-j Feb 25, 2026
8706916
Update terminology from "standalone" to "pre-link".
elle-j Feb 25, 2026
6c680ff
Update match cases in cached compiler.
elle-j Feb 25, 2026
8246f3c
Merge branch 'main' into lj/compile-context
elle-j Feb 27, 2026
ab8346a
Share orchestration logic between tests and compilations.
elle-j Mar 2, 2026
361247c
Merge branch 'main' into lj/compile-context
elle-j Mar 2, 2026
856d62e
Merge branch 'main' into lj/compile-context
elle-j Mar 2, 2026
7c46dcd
Enable cache invalidation.
elle-j Mar 2, 2026
4b84f27
Don't panic clearing the cache if the cache directory does not exit.
elle-j Mar 2, 2026
b382150
Fix clippy.
elle-j Mar 2, 2026
eb3aad9
Update naming.
elle-j Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/common/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
mod identifiers;
mod mode;
mod parsed_compilation_specifier;
mod parsed_test_specifier;
mod private_key_allocator;
mod round_robin_pool;
mod version_or_requirement;

pub use identifiers::*;
pub use mode::*;
pub use parsed_compilation_specifier::*;
pub use parsed_test_specifier::*;
pub use private_key_allocator::*;
pub use round_robin_pool::*;
Expand Down
80 changes: 80 additions & 0 deletions crates/common/src/types/parsed_compilation_specifier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::{fmt::Display, path::PathBuf, str::FromStr};

use anyhow::Context as _;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ParsedCompilationSpecifier {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this file rather than the TestSpecifier? They seem to be functionally the same but the test specifier seems to be more permissive in what it allows us to point to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grouped my response here to some related comments such as that ☝️ one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this and I agree with you that your approach here is better. Will mark this as resolved.

/// All of the contracts in the file should be compiled.
FileOrDirectory {
/// The path of the metadata file containing the contracts or the references to the contracts.
metadata_or_directory_file_path: PathBuf,
},
}

impl Display for ParsedCompilationSpecifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParsedCompilationSpecifier::FileOrDirectory {
metadata_or_directory_file_path,
} => {
write!(f, "{}", metadata_or_directory_file_path.display())
}
}
}
}

impl FromStr for ParsedCompilationSpecifier {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let path = PathBuf::from(s)
.canonicalize()
.context("Failed to canonicalize the path of the contracts")?;

Ok(Self::FileOrDirectory {
metadata_or_directory_file_path: path,
})
}
}

impl From<ParsedCompilationSpecifier> for String {
fn from(value: ParsedCompilationSpecifier) -> Self {
value.to_string()
}
}

impl TryFrom<String> for ParsedCompilationSpecifier {
type Error = anyhow::Error;

fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}

impl TryFrom<&str> for ParsedCompilationSpecifier {
type Error = anyhow::Error;

fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}

impl Serialize for ParsedCompilationSpecifier {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.to_string().serialize(serializer)
}
}

impl<'de> Deserialize<'de> for ParsedCompilationSpecifier {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
string.parse().map_err(serde::de::Error::custom)
}
}
2 changes: 1 addition & 1 deletion crates/common/src/types/parsed_test_specifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::types::Mode;

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ParsedTestSpecifier {
/// All of the test cases in the file should be ran across all of the specified modes
/// All of the test cases in the file should be ran across all of the specified modes.
FileOrDirectory {
/// The path of the metadata file containing the test cases.
metadata_or_directory_file_path: PathBuf,
Expand Down
60 changes: 50 additions & 10 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use alloy::{
};
use anyhow::Context as _;
use clap::{Parser, ValueEnum, ValueHint};
use revive_dt_common::types::{ParsedTestSpecifier, PlatformIdentifier};
use revive_dt_common::types::{
ParsedCompilationSpecifier, ParsedTestSpecifier, PlatformIdentifier,
};
use semver::Version;
use serde::{Deserialize, Serialize, Serializer};
use strum::{AsRefStr, Display, EnumString, IntoStaticStr};
Expand All @@ -39,7 +41,7 @@ mod context {
pub output_format: OutputFormatConfiguration,
pub platforms: PlatformConfiguration,
pub working_directory: WorkingDirectoryConfiguration,
pub corpus: CorpusConfiguration,
pub corpus: CorpusExecutionConfiguration,
pub fail_fast: FailFastConfiguration,
pub solc: SolcConfiguration,
pub resolc: ResolcConfiguration,
Expand All @@ -65,7 +67,7 @@ mod context {
pub platforms: PlatformConfiguration,
pub working_directory: WorkingDirectoryConfiguration,
pub benchmark_run: BenchmarkRunConfiguration,
pub corpus: CorpusConfiguration,
pub corpus: CorpusExecutionConfiguration,
pub solc: SolcConfiguration,
pub resolc: ResolcConfiguration,
pub polkadot_parachain: PolkadotParachainConfiguration,
Expand Down Expand Up @@ -97,6 +99,20 @@ mod context {
#[subcommand]
pub struct ExportJsonSchema;

/// Compiles contracts for pre-link compilations only without executing any tests.
#[subcommand]
pub struct Compile {
pub output_format: OutputFormatConfiguration,
pub working_directory: WorkingDirectoryConfiguration,
pub corpus: CorpusCompilationConfiguration,
pub fail_fast: FailFastConfiguration,
pub solc: SolcConfiguration,
pub resolc: ResolcConfiguration,
pub concurrency: ConcurrencyConfiguration,
pub compilation: CompilationConfiguration,
pub report: ReportConfiguration,
}

/// Configuration for the commandline profile.
#[configuration]
pub struct ProfileConfiguration {
Expand All @@ -112,6 +128,9 @@ mod context {
/// The output format to use for the tool's output.
#[arg(short, long, default_value_t = OutputFormat::CargoTestLike)]
pub output_format: OutputFormat,
/// If applicable, show verbose details when executing the tool.
#[arg(long)]
pub verbose: bool,
}

/// Configuration for the set of platforms.
Expand All @@ -131,7 +150,7 @@ mod context {
#[configuration]
pub struct WorkingDirectoryConfiguration {
/// The working directory that the program will use for all of the temporary artifacts
/// needed at runtime.
/// needed at runtime, as well as the generated report.
///
/// If not specified, then a temporary directory will be created and used by the program
/// for all temporary artifacts.
Expand Down Expand Up @@ -170,10 +189,10 @@ mod context {
pub fail_fast: bool,
}

/// A set of configuration parameters for the corpus files to use for the execution.
/// A set of configuration parameters for the corpus files to use for the test execution.
#[serde_with::serde_as]
#[configuration(key = "corpus")]
pub struct CorpusConfiguration {
pub struct CorpusExecutionConfiguration {
/// A list of test specifiers for the tests that the tool should run.
///
/// Test specifiers follow the following format:
Expand All @@ -192,6 +211,22 @@ mod context {
pub test_specifiers: Vec<ParsedTestSpecifier>,
}

/// A set of configuration parameters for the corpus files to use for the pre-link-only compilation.
#[serde_with::serde_as]
#[configuration(key = "corpus")]
pub struct CorpusCompilationConfiguration {
/// A list of compilation specifiers for the pre-link-only compilations that the tool should run.
///
/// Compile specifiers follow the following format:
///
/// - `{directory_path|metadata_file_path}`: A path to a metadata file where all of the contracts,
/// or references to the contracts, live and should be compiled. Alternatively, it points to a
/// directory instructing the framework to discover the metadata files that live there and compile them.
#[serde_as(as = "Vec<serde_with::DisplayFromStr>")]
#[arg(short = 'c', long = "compile", required = true)]
pub compilation_specifiers: Vec<ParsedCompilationSpecifier>,
}

/// A set of configuration parameters for Solc.
#[configuration(key = "solc")]
pub struct SolcConfiguration {
Expand Down Expand Up @@ -517,10 +552,9 @@ mod context {
impl Context {
pub fn update_for_profile(&mut self) {
match self {
Context::Test(ctx) => ctx.update_for_profile(),
Context::Benchmark(ctx) => ctx.update_for_profile(),
Context::ExportJsonSchema(_) => {}
Context::ExportGenesis(_) => {}
Self::Test(ctx) => ctx.update_for_profile(),
Self::Benchmark(ctx) => ctx.update_for_profile(),
Self::ExportJsonSchema(_) | Self::ExportGenesis(..) | Self::Compile(..) => {}
}
}
}
Expand Down Expand Up @@ -610,6 +644,12 @@ mod context {
Self::parse_from(["benchmark", "--test", "."])
}
}

impl Default for Compile {
fn default() -> Self {
Self::parse_from(["compile", "--compile", "."])
}
}
}

/// Represents the working directory that the program uses.
Expand Down
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ clap = { workspace = true }
dashmap = { workspace = true }
futures = { workspace = true }
indexmap = { workspace = true }
regex = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
tracing-appender = { workspace = true }
Expand Down
40 changes: 40 additions & 0 deletions crates/core/src/compilations/driver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use anyhow::{Context as _, Result};
use revive_dt_report::CompilationReporter;
use tracing::error;

use crate::helpers::{CachedCompiler, CompilationDefinition};

/// The compilation driver.
pub struct Driver<'a> {
/// The definition of the compilation that the driver is instructed to execute.
compilation_definition: &'a CompilationDefinition<'a>,
}

impl<'a> Driver<'a> {
/// Creates a new driver.
pub fn new(compilation_definition: &'a CompilationDefinition<'a>) -> Self {
Self {
compilation_definition,
}
}

/// Compiles all contracts specified by the [`CompilationDefinition`].
pub async fn compile_all(&self, cached_compiler: &CachedCompiler<'a>) -> Result<()> {
cached_compiler
.compile_contracts(
self.compilation_definition.metadata,
self.compilation_definition.metadata_file_path,
self.compilation_definition.mode.clone(),
None,
self.compilation_definition.compiler.as_ref(),
self.compilation_definition.compiler_identifier,
None,
&CompilationReporter::PreLink(&self.compilation_definition.reporter),
)
.await
.inspect_err(|err| error!(?err, "Compilation failed"))
.context("Failed to produce the compiled contracts")?;

Ok(())
}
}
Loading
Loading