mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-11-15 07:07:16 +00:00
Separate compilation and linker phases (#376)
Separate between compilation and linker phases to allow deploy time linking and back-porting era compiler changes to fix #91. Unlinked contract binaries (caused by missing libraries or missing factory dependencies in turn) are emitted as raw ELF object. Few drive by fixes: - #98 - A compiler panic on missing libraries definitions. - Fixes some incosistent type forwarding in JSON output (empty string vs. null object). - Remove the unused fallback for size optimization setting. - Remove the broken `--lvm-ir` mode. - CI workflow fixes. --------- Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by: xermicus <bigcyrill@hotmail.com> Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
1 parent
13faedf08a
commit
94ec34c4d5
169 files changed
+6288
-5206
No files matched your search
+273
-210
@@ -1,12 +1,35 @@
|
||||
//! Solidity to PolkaVM compiler library.
|
||||
|
||||
pub(crate) mod build;
|
||||
pub(crate) mod r#const;
|
||||
pub(crate) mod missing_libraries;
|
||||
pub(crate) mod process;
|
||||
pub(crate) mod project;
|
||||
pub(crate) mod solc;
|
||||
pub(crate) mod version;
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::iter::IntoParallelIterator;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::iter::ParallelIterator;
|
||||
use revive_common::EVMVersion;
|
||||
use revive_common::MetadataHash;
|
||||
use revive_common::EXIT_CODE_SUCCESS;
|
||||
use revive_llvm_context::DebugConfig;
|
||||
use revive_llvm_context::OptimizerSettings;
|
||||
use revive_solc_json_interface::CombinedJsonSelector;
|
||||
use revive_solc_json_interface::ResolcWarning;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputLanguage;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsLibraries;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVM;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutputError;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutputErrorHandler;
|
||||
|
||||
use crate::linker::Output;
|
||||
|
||||
pub use self::build::contract::Contract as ContractBuild;
|
||||
pub use self::build::Build;
|
||||
@@ -31,118 +54,76 @@ pub use self::solc::FIRST_SUPPORTED_VERSION as SolcFirstSupportedVersion;
|
||||
pub use self::solc::LAST_SUPPORTED_VERSION as SolcLastSupportedVersion;
|
||||
pub use self::version::Version as ResolcVersion;
|
||||
|
||||
pub(crate) mod build;
|
||||
pub(crate) mod r#const;
|
||||
pub(crate) mod linker;
|
||||
pub(crate) mod missing_libraries;
|
||||
pub(crate) mod process;
|
||||
pub(crate) mod project;
|
||||
pub(crate) mod solc;
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
pub mod test_utils;
|
||||
pub mod tests;
|
||||
pub(crate) mod version;
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use revive_solc_json_interface::standard_json::input::settings::metadata_hash::MetadataHash;
|
||||
use revive_solc_json_interface::ResolcWarning;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputLanguage;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVM;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection;
|
||||
/// The rayon worker stack size.
|
||||
pub const RAYON_WORKER_STACK_SIZE: usize = 64 * 1024 * 1024;
|
||||
|
||||
/// Runs the Yul mode.
|
||||
pub fn yul<T: Compiler>(
|
||||
solc: &T,
|
||||
input_files: &[PathBuf],
|
||||
solc: &mut T,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
mut debug_config: revive_llvm_context::DebugConfig,
|
||||
libraries: &[String],
|
||||
metadata_hash: MetadataHash,
|
||||
messages: &mut Vec<SolcStandardJsonOutputError>,
|
||||
optimizer_settings: OptimizerSettings,
|
||||
debug_config: DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||
) -> anyhow::Result<Build> {
|
||||
let path = match input_files.len() {
|
||||
1 => input_files.first().expect("Always exists"),
|
||||
0 => anyhow::bail!("The input file is missing"),
|
||||
length => anyhow::bail!(
|
||||
"Only one input file is allowed in the Yul mode, but found {}",
|
||||
length,
|
||||
),
|
||||
};
|
||||
let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?;
|
||||
solc.validate_yul_paths(input_files, libraries.clone(), messages)?;
|
||||
|
||||
if solc.version()?.default != solc::LAST_SUPPORTED_VERSION {
|
||||
anyhow::bail!(
|
||||
"The Yul mode is only supported with the most recent version of the Solidity compiler: {}",
|
||||
solc::LAST_SUPPORTED_VERSION,
|
||||
);
|
||||
}
|
||||
|
||||
let solc_validator = Some(&*solc);
|
||||
let project = Project::try_from_yul_path(path, solc_validator)?;
|
||||
|
||||
debug_config.set_yul_path(path);
|
||||
let build = project.compile(
|
||||
let linker_symbols = libraries.as_linker_symbols()?;
|
||||
let project = Project::try_from_yul_paths(input_files, None, libraries, &debug_config)?;
|
||||
let mut build = project.compile(
|
||||
messages,
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
memory_config,
|
||||
)?;
|
||||
|
||||
Ok(build)
|
||||
}
|
||||
|
||||
/// Runs the LLVM IR mode.
|
||||
pub fn llvm_ir(
|
||||
input_files: &[PathBuf],
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||
) -> anyhow::Result<Build> {
|
||||
let path = match input_files.len() {
|
||||
1 => input_files.first().expect("Always exists"),
|
||||
0 => anyhow::bail!("The input file is missing"),
|
||||
length => anyhow::bail!(
|
||||
"Only one input file is allowed in the LLVM IR mode, but found {}",
|
||||
length,
|
||||
),
|
||||
};
|
||||
|
||||
let project = Project::try_from_llvm_ir_path(path)?;
|
||||
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
metadata_hash,
|
||||
&debug_config,
|
||||
llvm_arguments,
|
||||
memory_config,
|
||||
)?;
|
||||
build.take_and_write_warnings();
|
||||
build.check_errors()?;
|
||||
|
||||
let mut build = build.link(linker_symbols, &debug_config);
|
||||
build.take_and_write_warnings();
|
||||
build.check_errors()?;
|
||||
Ok(build)
|
||||
}
|
||||
|
||||
/// Runs the standard output mode.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn standard_output<T: Compiler>(
|
||||
solc: &T,
|
||||
input_files: &[PathBuf],
|
||||
libraries: Vec<String>,
|
||||
solc: &mut T,
|
||||
evm_version: Option<revive_common::EVMVersion>,
|
||||
libraries: &[String],
|
||||
metadata_hash: MetadataHash,
|
||||
messages: &mut Vec<SolcStandardJsonOutputError>,
|
||||
evm_version: Option<EVMVersion>,
|
||||
solc_optimizer_enabled: bool,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
optimizer_settings: OptimizerSettings,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
remappings: Option<BTreeSet<String>>,
|
||||
suppressed_warnings: Option<Vec<ResolcWarning>>,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
remappings: BTreeSet<String>,
|
||||
suppressed_warnings: Vec<ResolcWarning>,
|
||||
debug_config: DebugConfig,
|
||||
llvm_arguments: Vec<String>,
|
||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||
) -> anyhow::Result<Build> {
|
||||
let solc_version = solc.version()?;
|
||||
|
||||
let solc_input = SolcStandardJsonInput::try_from_paths(
|
||||
SolcStandardJsonInputLanguage::Solidity,
|
||||
let mut solc_input = SolcStandardJsonInput::try_from_solidity_paths(
|
||||
evm_version,
|
||||
input_files,
|
||||
libraries,
|
||||
@@ -150,162 +131,211 @@ pub fn standard_output<T: Compiler>(
|
||||
SolcStandardJsonInputSettingsSelection::new_required(),
|
||||
SolcStandardJsonInputSettingsOptimizer::new(
|
||||
solc_optimizer_enabled,
|
||||
None,
|
||||
&solc_version.default,
|
||||
optimizer_settings.is_fallback_to_size_enabled(),
|
||||
SolcStandardJsonInputSettingsOptimizer::default_mode(),
|
||||
Default::default(),
|
||||
),
|
||||
None,
|
||||
Default::default(),
|
||||
suppressed_warnings,
|
||||
Some(SolcStandardJsonInputSettingsPolkaVM::new(
|
||||
SolcStandardJsonInputSettingsPolkaVM::new(
|
||||
Some(memory_config),
|
||||
debug_config.emit_debug_info,
|
||||
)),
|
||||
),
|
||||
llvm_arguments,
|
||||
false,
|
||||
)?;
|
||||
let mut solc_output = solc.standard_json(
|
||||
&mut solc_input,
|
||||
messages,
|
||||
base_path,
|
||||
include_paths,
|
||||
allow_paths,
|
||||
)?;
|
||||
solc_output.take_and_write_warnings();
|
||||
solc_output.check_errors()?;
|
||||
|
||||
let source_code_files = solc_input
|
||||
.sources
|
||||
.iter()
|
||||
.map(|(path, source)| (path.to_owned(), source.content.to_owned()))
|
||||
.collect();
|
||||
|
||||
let libraries = solc_input.settings.libraries.clone().unwrap_or_default();
|
||||
let solc_output = solc.standard_json(solc_input, base_path, include_paths, allow_paths)?;
|
||||
|
||||
if let Some(errors) = solc_output.errors.as_deref() {
|
||||
let mut has_errors = false;
|
||||
|
||||
for error in errors.iter() {
|
||||
if error.severity.as_str() == "error" {
|
||||
has_errors = true;
|
||||
}
|
||||
|
||||
writeln!(std::io::stderr(), "{error}")?;
|
||||
}
|
||||
|
||||
if has_errors {
|
||||
anyhow::bail!("Error(s) found. Compilation aborted");
|
||||
}
|
||||
}
|
||||
let linker_symbols = solc_input.settings.libraries.as_linker_symbols()?;
|
||||
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&solc_output,
|
||||
source_code_files,
|
||||
libraries,
|
||||
&mut solc_output,
|
||||
solc_input.settings.libraries,
|
||||
&solc_version,
|
||||
&debug_config,
|
||||
)?;
|
||||
solc_output.take_and_write_warnings();
|
||||
solc_output.check_errors()?;
|
||||
|
||||
let build = project.compile(
|
||||
let mut build = project.compile(
|
||||
messages,
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
metadata_hash,
|
||||
&debug_config,
|
||||
&solc_input.settings.llvm_arguments,
|
||||
memory_config,
|
||||
)?;
|
||||
build.take_and_write_warnings();
|
||||
build.check_errors()?;
|
||||
|
||||
let mut build = build.link(linker_symbols, &debug_config);
|
||||
build.take_and_write_warnings();
|
||||
build.check_errors()?;
|
||||
|
||||
Ok(build)
|
||||
}
|
||||
|
||||
/// Runs the standard JSON mode.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn standard_json<T: Compiler>(
|
||||
solc: &mut T,
|
||||
detect_missing_libraries: bool,
|
||||
solc: &T,
|
||||
metadata_hash: MetadataHash,
|
||||
messages: &mut Vec<SolcStandardJsonOutputError>,
|
||||
json_path: Option<PathBuf>,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
mut debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
mut debug_config: DebugConfig,
|
||||
detect_missing_libraries: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
let solc_version = solc.version()?;
|
||||
|
||||
let solc_input = SolcStandardJsonInput::try_from_stdin()?;
|
||||
let source_code_files = solc_input
|
||||
.sources
|
||||
.iter()
|
||||
.map(|(path, source)| (path.to_owned(), source.content.to_owned()))
|
||||
.collect();
|
||||
|
||||
let optimizer_settings =
|
||||
revive_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?;
|
||||
|
||||
let polkavm_settings = solc_input.settings.polkavm.unwrap_or_default();
|
||||
debug_config.emit_debug_info = polkavm_settings.debug_information.unwrap_or_default();
|
||||
|
||||
let include_metadata_hash = match solc_input.settings.metadata {
|
||||
Some(ref metadata) => metadata.bytecode_hash != Some(MetadataHash::None),
|
||||
None => true,
|
||||
};
|
||||
|
||||
let libraries = solc_input.settings.libraries.clone().unwrap_or_default();
|
||||
let mut solc_output = solc.standard_json(solc_input, base_path, include_paths, allow_paths)?;
|
||||
|
||||
if let Some(errors) = solc_output.errors.as_deref() {
|
||||
for error in errors.iter() {
|
||||
if error.severity.as_str() == "error" {
|
||||
serde_json::to_writer(std::io::stdout(), &solc_output)?;
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&solc_output,
|
||||
source_code_files,
|
||||
libraries,
|
||||
&solc_version,
|
||||
&debug_config,
|
||||
let mut solc_input = SolcStandardJsonInput::try_from(json_path.as_deref())?;
|
||||
let language = solc_input.language;
|
||||
let prune_output = solc_input.settings.selection_to_prune();
|
||||
let deployed_libraries = solc_input.settings.libraries.as_paths();
|
||||
let linker_symbols = solc_input.settings.libraries.as_linker_symbols()?;
|
||||
let optimizer_settings = OptimizerSettings::try_from_cli(solc_input.settings.optimizer.mode)?;
|
||||
let detect_missing_libraries =
|
||||
solc_input.settings.detect_missing_libraries || detect_missing_libraries;
|
||||
debug_config.emit_debug_info = solc_input
|
||||
.settings
|
||||
.polkavm
|
||||
.debug_information
|
||||
.unwrap_or(false);
|
||||
solc_input.extend_selection(SolcStandardJsonInputSettingsSelection::new_required());
|
||||
let mut solc_output = solc.standard_json(
|
||||
&mut solc_input,
|
||||
messages,
|
||||
base_path,
|
||||
include_paths,
|
||||
allow_paths,
|
||||
)?;
|
||||
|
||||
if detect_missing_libraries {
|
||||
let missing_libraries = project.get_missing_libraries();
|
||||
missing_libraries.write_to_standard_json(&mut solc_output, &solc_version)?;
|
||||
} else {
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
polkavm_settings
|
||||
.memory_config
|
||||
.unwrap_or_else(SolcStandardJsonInputSettingsPolkaVMMemory::default),
|
||||
)?;
|
||||
build.write_to_standard_json(&mut solc_output, &solc_version)?;
|
||||
let (mut solc_output, project) = match language {
|
||||
SolcStandardJsonInputLanguage::Solidity => {
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&mut solc_output,
|
||||
solc_input.settings.libraries,
|
||||
&solc_version,
|
||||
&debug_config,
|
||||
)?;
|
||||
(solc_output, project)
|
||||
}
|
||||
SolcStandardJsonInputLanguage::Yul => {
|
||||
let mut solc_output = solc.validate_yul_standard_json(&mut solc_input, messages)?;
|
||||
if solc_output.has_errors() {
|
||||
solc_output.write_and_exit(prune_output);
|
||||
}
|
||||
let project = Project::try_from_yul_sources(
|
||||
solc_input.sources,
|
||||
solc_input.settings.libraries,
|
||||
Some(&mut solc_output),
|
||||
&debug_config,
|
||||
)?;
|
||||
|
||||
(solc_output, project)
|
||||
}
|
||||
};
|
||||
|
||||
if solc_output.has_errors() {
|
||||
solc_output.write_and_exit(prune_output);
|
||||
}
|
||||
serde_json::to_writer(std::io::stdout(), &solc_output)?;
|
||||
std::process::exit(0);
|
||||
|
||||
if detect_missing_libraries {
|
||||
let missing_libraries = project.get_missing_libraries(&deployed_libraries);
|
||||
missing_libraries.write_to_standard_json(&mut solc_output, &solc_version);
|
||||
solc_output.write_and_exit(prune_output);
|
||||
}
|
||||
|
||||
let build = project.compile(
|
||||
messages,
|
||||
optimizer_settings,
|
||||
metadata_hash,
|
||||
&debug_config,
|
||||
&solc_input.settings.llvm_arguments,
|
||||
solc_input
|
||||
.settings
|
||||
.polkavm
|
||||
.memory_config
|
||||
.unwrap_or_default(),
|
||||
)?;
|
||||
if build.has_errors() {
|
||||
build.write_to_standard_json(&mut solc_output, &solc_version)?;
|
||||
solc_output.write_and_exit(prune_output);
|
||||
}
|
||||
|
||||
let build = build.link(linker_symbols, &debug_config);
|
||||
build.write_to_standard_json(&mut solc_output, &solc_version)?;
|
||||
solc_output.write_and_exit(prune_output);
|
||||
}
|
||||
|
||||
/// Runs the combined JSON mode.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn combined_json<T: Compiler>(
|
||||
solc: &T,
|
||||
paths: &[PathBuf],
|
||||
libraries: &[String],
|
||||
metadata_hash: MetadataHash,
|
||||
messages: &mut Vec<SolcStandardJsonOutputError>,
|
||||
evm_version: Option<EVMVersion>,
|
||||
format: String,
|
||||
input_files: &[PathBuf],
|
||||
libraries: Vec<String>,
|
||||
solc: &mut T,
|
||||
evm_version: Option<revive_common::EVMVersion>,
|
||||
solc_optimizer_enabled: bool,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
optimizer_settings: OptimizerSettings,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
remappings: Option<BTreeSet<String>>,
|
||||
suppressed_warnings: Option<Vec<ResolcWarning>>,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
remappings: BTreeSet<String>,
|
||||
suppressed_warnings: Vec<ResolcWarning>,
|
||||
debug_config: DebugConfig,
|
||||
output_directory: Option<PathBuf>,
|
||||
overwrite: bool,
|
||||
llvm_arguments: &[String],
|
||||
llvm_arguments: Vec<String>,
|
||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||
) -> anyhow::Result<()> {
|
||||
let build = standard_output(
|
||||
input_files,
|
||||
libraries,
|
||||
let selectors = CombinedJsonSelector::from_cli(format.as_str())
|
||||
.into_iter()
|
||||
.filter_map(|result| match result {
|
||||
Ok(selector) => Some(selector),
|
||||
Err(error) => {
|
||||
messages.push(SolcStandardJsonOutputError::new_error(
|
||||
error.to_string(),
|
||||
None,
|
||||
None,
|
||||
));
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<HashSet<_>>();
|
||||
if !selectors.contains(&CombinedJsonSelector::Bytecode) {
|
||||
messages.push(SolcStandardJsonOutputError::new_warning(
|
||||
"Bytecode is always emitted even if the selector is not provided.".to_string(),
|
||||
None,
|
||||
None,
|
||||
));
|
||||
}
|
||||
if selectors.contains(&CombinedJsonSelector::BytecodeRuntime) {
|
||||
messages.push(SolcStandardJsonOutputError::new_warning(
|
||||
format!("The `{}` selector does not make sense for the PVM target, since there is only one bytecode segment.", CombinedJsonSelector::BytecodeRuntime),
|
||||
None,
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
||||
let mut combined_json = solc.combined_json(paths, selectors)?;
|
||||
standard_output(
|
||||
solc,
|
||||
paths,
|
||||
libraries,
|
||||
metadata_hash,
|
||||
messages,
|
||||
evm_version,
|
||||
solc_optimizer_enabled,
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
base_path,
|
||||
include_paths,
|
||||
allow_paths,
|
||||
@@ -314,24 +344,57 @@ pub fn combined_json<T: Compiler>(
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
memory_config,
|
||||
)?;
|
||||
|
||||
let mut combined_json = solc.combined_json(input_files, format.as_str())?;
|
||||
build.write_to_combined_json(&mut combined_json)?;
|
||||
)?
|
||||
.write_to_combined_json(&mut combined_json)?;
|
||||
|
||||
match output_directory {
|
||||
Some(output_directory) => {
|
||||
std::fs::create_dir_all(output_directory.as_path())?;
|
||||
|
||||
combined_json.write_to_directory(output_directory.as_path(), overwrite)?;
|
||||
}
|
||||
None => {
|
||||
|
||||
writeln!(
|
||||
std::io::stdout(),
|
||||
"{}",
|
||||
serde_json::to_string(&combined_json).expect("Always valid")
|
||||
std::io::stderr(),
|
||||
"Compiler run successful. Artifact(s) can be found in directory {output_directory:?}."
|
||||
)?;
|
||||
}
|
||||
None => {
|
||||
serde_json::to_writer(std::io::stdout(), &combined_json)?;
|
||||
}
|
||||
}
|
||||
std::process::exit(0);
|
||||
std::process::exit(EXIT_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
/// Links unlinked bytecode files.
|
||||
pub fn link(paths: Vec<String>, libraries: Vec<String>) -> anyhow::Result<()> {
|
||||
#[cfg(feature = "parallel")]
|
||||
let iter = paths.into_par_iter();
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let iter = paths.into_iter();
|
||||
|
||||
let bytecodes = iter
|
||||
.map(|path| {
|
||||
let bytecode = std::fs::read(path.as_str())?;
|
||||
Ok((path, bytecode))
|
||||
})
|
||||
.collect::<anyhow::Result<BTreeMap<String, Vec<u8>>>>()?;
|
||||
|
||||
let output = Output::try_from(&bytecodes, &libraries)?;
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
let iter = output.linked.into_par_iter();
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let iter = output.linked.into_iter();
|
||||
|
||||
iter.map(|(path, bytecode)| {
|
||||
std::fs::write(path, bytecode)?;
|
||||
Ok(())
|
||||
})
|
||||
.collect::<anyhow::Result<()>>()?;
|
||||
|
||||
for (path, _) in output.unlinked {
|
||||
println!("Warning: file '{path}' still unresolved");
|
||||
}
|
||||
println!("Linking completed");
|
||||
|
||||
std::process::exit(EXIT_CODE_SUCCESS);
|
||||
}
|
||||
Reference in new issue
Block a user