diff --git a/Cargo.toml b/Cargo.toml index 237be2ea7..fb0b5af24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ once_cell = "1.19" solang-parser = { path = "solang-parser", version = "0.3.5" } codespan-reporting = "0.11" phf = { version = "0.11", features = ["macros"] } +rayon = "1" rust-lapper = { version = "1.1", optional = true } anchor-syn = { version = "0.29.0", features = ["idl-build"] } convert_case = "0.6" @@ -87,7 +88,6 @@ pretty_assertions = "1.4" byte-slice-cast = "1.2" borsh = "1.1" borsh-derive = "1.1" -rayon = "1" walkdir = "2.4" ink_primitives = "5.0.0" wasm_host_attr = { path = "tests/wasm_host_attr" } diff --git a/src/bin/solang.rs b/src/bin/solang.rs index 40112b584..948722530 100644 --- a/src/bin/solang.rs +++ b/src/bin/solang.rs @@ -5,6 +5,7 @@ use clap::{Command, CommandFactory, FromArgMatches}; use clap_complete::generate; use cli::PackageTrait; use itertools::Itertools; +use rayon::prelude::*; use solang::{ abi, codegen::{codegen, Options}, @@ -174,7 +175,7 @@ fn compile(compile_args: &Compile) { eprintln!("info: Solang version {}", env!("SOLANG_VERSION")); } - let mut resolver = imports_arg(&compile_args.package); + let resolver = imports_arg(&compile_args.package); let compile_package = &compile_args.package; @@ -184,8 +185,6 @@ fn compile(compile_args: &Compile) { compile_package, ); - let mut namespaces = Vec::new(); - let mut errors = false; // Build a map of requested contract names, and a flag specifying whether it was found or not @@ -195,29 +194,33 @@ fn compile(compile_args: &Compile) { HashSet::new() }; - for filename in compile_args.package.get_input() { - // TODO: this could be parallelized using e.g. rayon - let ns = process_file( - filename, - &mut resolver, - target, - &compile_args.compiler_output, - &opt, - ); + let resolved_inputs: Vec<_> = compile_args.package.get_input().iter().collect(); + let mut namespaces_with_resolvers: Vec<_> = resolved_inputs + .par_iter() + .map(|filename| { + let mut resolver = resolver.clone(); + let ns = process_file( + filename, + &mut resolver, + target, + &compile_args.compiler_output, + &opt, + ); - namespaces.push(ns); - } + (ns, resolver) + }) + .collect(); let mut json_contracts = HashMap::new(); let std_json = compile_args.compiler_output.std_json_output; - for ns in &namespaces { + for (ns, resolver) in &namespaces_with_resolvers { if std_json { - let mut out = ns.diagnostics_as_json(&resolver); + let mut out = ns.diagnostics_as_json(resolver); json.errors.append(&mut out); } else { - ns.print_diagnostics(&resolver, compile_args.compiler_output.verbose); + ns.print_diagnostics(resolver, compile_args.compiler_output.verbose); } if ns.diagnostics.any_errors() { @@ -230,7 +233,11 @@ fn compile(compile_args: &Compile) { } // Ensure we have at least one contract - if !errors && namespaces.iter().all(|ns| ns.contracts.is_empty()) { + if !errors + && namespaces_with_resolvers + .iter() + .all(|(ns, _resolver)| ns.contracts.is_empty()) + { eprintln!("error: no contacts found"); errors = true; } @@ -239,9 +246,9 @@ fn compile(compile_args: &Compile) { let not_found: Vec<_> = contract_names .iter() .filter(|name| { - !namespaces + !namespaces_with_resolvers .iter() - .flat_map(|ns| ns.contracts.iter()) + .flat_map(|(ns, _resolver)| ns.contracts.iter()) .any(|contract| **name == contract.id.name) }) .collect(); @@ -269,6 +276,11 @@ fn compile(compile_args: &Compile) { "0.0.1" }; + let mut namespaces: Vec<_> = namespaces_with_resolvers + .drain(..) + .map(|(ns, _resolver)| ns) + .collect(); + for ns in &mut namespaces { for contract_no in 0..ns.contracts.len() { contract_results( diff --git a/src/file_resolver.rs b/src/file_resolver.rs index 81f25ff96..66519186e 100644 --- a/src/file_resolver.rs +++ b/src/file_resolver.rs @@ -11,7 +11,7 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::sync::Arc; -#[derive(Default)] +#[derive(Clone, Default)] pub struct FileResolver { /// Set of import paths search for imports import_paths: Vec<(Option, PathBuf)>,