From c52eaca2634f920fd3c6f679d37e194720f203b9 Mon Sep 17 00:00:00 2001 From: FroyaTheHen Date: Wed, 11 Dec 2024 14:58:08 +0100 Subject: [PATCH] feat: compile executable commit-id:4510e5a4 --- scarb/src/compiler/compilers/executable.rs | 47 +++++++++++++++++++ scarb/src/compiler/compilers/lib.rs | 9 ++-- scarb/src/compiler/compilers/mod.rs | 2 + .../compilers/starknet_contract/compiler.rs | 13 +++-- scarb/src/compiler/compilers/test.rs | 7 +-- .../compiler/plugin/proc_macro/compilation.rs | 3 +- scarb/src/compiler/repository.rs | 5 +- scarb/src/core/manifest/target_kind.rs | 1 + scarb/tests/build_targets.rs | 29 ++++++++++++ 9 files changed, 104 insertions(+), 12 deletions(-) diff --git a/scarb/src/compiler/compilers/executable.rs b/scarb/src/compiler/compilers/executable.rs index e69de29bb..735d3f670 100644 --- a/scarb/src/compiler/compilers/executable.rs +++ b/scarb/src/compiler/compilers/executable.rs @@ -0,0 +1,47 @@ +use crate::compiler::helpers::write_json; +use crate::compiler::helpers::{build_compiler_config, collect_main_crate_ids}; +use crate::compiler::{CairoCompilationUnit, CompilationUnitAttributes, Compiler}; +use crate::core::{TargetKind, Workspace}; +use anyhow::Result; +use cairo_lang_compiler::db::RootDatabase; +use cairo_lang_executable::executable::Executable; +use tracing::trace_span; + +pub struct ExecutableCompiler; + +impl Compiler for ExecutableCompiler { + fn target_kind(&self) -> TargetKind { + TargetKind::EXECUTABLE.clone() + } + + fn compile( + &self, + unit: CairoCompilationUnit, + db: &mut RootDatabase, + ws: &Workspace<'_>, + ) -> Result<()> { + let target_dir = unit.target_dir(ws); + let main_crate_ids = collect_main_crate_ids(&unit, db); + let compiler_config = build_compiler_config(db, &unit, &main_crate_ids, ws); + let span = trace_span!("compile_executable"); + let executable = { + let _guard = span.enter(); + Executable::new( + cairo_lang_executable::compile::compile_executable_in_prepared_db( + db, + None, + main_crate_ids, + compiler_config.diagnostics_reporter, + )?, + ) + }; + + write_json( + format!("{}.executable.json", unit.main_component().target_name()).as_str(), + "output file", + &target_dir, + ws, + &executable, + ) + } +} diff --git a/scarb/src/compiler/compilers/lib.rs b/scarb/src/compiler/compilers/lib.rs index 458c5f5f9..42a382f0e 100644 --- a/scarb/src/compiler/compilers/lib.rs +++ b/scarb/src/compiler/compilers/lib.rs @@ -62,8 +62,9 @@ impl Compiler for LibCompiler { validate_compiler_config(db, &compiler_config, &unit, ws); + let span = trace_span!("compile_sierra"); let sierra_program: VersionedProgram = { - let _ = trace_span!("compile_sierra").enter(); + let _guard = span.enter(); let program_artifact = cairo_lang_compiler::compile_prepared_db_program_artifact( db, main_crate_ids, @@ -101,8 +102,9 @@ impl Compiler for LibCompiler { if props.casm { let program = sierra_program.into_v1().unwrap().program; + let span = trace_span!("casm_calc_metadata"); let metadata = { - let _ = trace_span!("casm_calc_metadata").enter(); + let _guard = span.enter(); if unit.compiler_config.enable_gas { debug!("calculating Sierra variables"); @@ -114,8 +116,9 @@ impl Compiler for LibCompiler { .context("failed calculating Sierra variables")? }; + let span = trace_span!("compile_casm"); let cairo_program = { - let _ = trace_span!("compile_casm").enter(); + let _ = span.enter(); let sierra_to_casm = SierraToCasmConfig { gas_usage_check: unit.compiler_config.enable_gas, max_bytecode_size: usize::MAX, diff --git a/scarb/src/compiler/compilers/mod.rs b/scarb/src/compiler/compilers/mod.rs index 4d810b570..c268bdb22 100644 --- a/scarb/src/compiler/compilers/mod.rs +++ b/scarb/src/compiler/compilers/mod.rs @@ -1,7 +1,9 @@ +pub use executable::*; pub use lib::*; pub use starknet_contract::*; pub use test::*; +mod executable; mod lib; mod starknet_contract; mod test; diff --git a/scarb/src/compiler/compilers/starknet_contract/compiler.rs b/scarb/src/compiler/compilers/starknet_contract/compiler.rs index 73263c2e5..4091226c6 100644 --- a/scarb/src/compiler/compilers/starknet_contract/compiler.rs +++ b/scarb/src/compiler/compilers/starknet_contract/compiler.rs @@ -114,7 +114,9 @@ impl Compiler for StarknetContractCompiler { check_allowed_libfuncs(&props, &contracts, &classes, db, &unit, ws)?; let casm_classes: Vec> = if props.casm { - let _ = trace_span!("compile_sierra").enter(); + let span = trace_span!("compile_sierra"); + let _guard = span.enter(); + zip(&contracts, &classes) .map(|(decl, class)| -> Result<_> { let contract_name = decl.submodule_id.name(db.upcast_mut()); @@ -159,8 +161,9 @@ pub fn get_compiled_contracts( .collect::>(); trace!(contracts = ?contract_paths); + let span = trace_span!("compile_starknet"); let classes = { - let _ = trace_span!("compile_starknet").enter(); + let _guard = span.enter(); compile_prepared_db(db, &contracts.iter().collect::>(), compiler_config)? }; Ok(CompiledContracts { @@ -177,14 +180,16 @@ pub fn find_project_contracts( main_crate_ids: Vec, external_contracts: Option>, ) -> Result> { + let span = trace_span!("find_internal_contracts"); let internal_contracts = { - let _ = trace_span!("find_internal_contracts").enter(); + let _guard = span.enter(); find_contracts(db, &main_crate_ids) }; + let span = trace_span!("find_external_contracts"); let external_contracts: Vec = if let Some(external_contracts) = external_contracts { - let _ = trace_span!("find_external_contracts").enter(); + let _guard = span.enter(); debug!("external contracts selectors: {:?}", external_contracts); let crate_ids = external_contracts diff --git a/scarb/src/compiler/compilers/test.rs b/scarb/src/compiler/compilers/test.rs index 5a3e27224..6d4d9fc3c 100644 --- a/scarb/src/compiler/compilers/test.rs +++ b/scarb/src/compiler/compilers/test.rs @@ -62,8 +62,9 @@ impl Compiler for TestCompiler { let diagnostics_reporter = build_compiler_config(db, &unit, &test_crate_ids, ws).diagnostics_reporter; + let span = trace_span!("compile_test"); let test_compilation = { - let _ = trace_span!("compile_test").enter(); + let _guard = span.enter(); let config = TestsCompilationConfig { starknet, add_statements_functions: unit @@ -79,9 +80,9 @@ impl Compiler for TestCompiler { compile_test_prepared_db(db, config, test_crate_ids.clone(), diagnostics_reporter)? }; + let span = trace_span!("serialize_test"); { - let _ = trace_span!("serialize_test").enter(); - + let _guard = span.enter(); let sierra_program: VersionedProgram = test_compilation.sierra_program.clone().into(); let file_name = format!("{}.test.sierra.json", unit.main_component().target_name()); write_json(&file_name, "output file", &target_dir, ws, &sierra_program)?; diff --git a/scarb/src/compiler/plugin/proc_macro/compilation.rs b/scarb/src/compiler/plugin/proc_macro/compilation.rs index a51a48b7e..cebcb2949 100644 --- a/scarb/src/compiler/plugin/proc_macro/compilation.rs +++ b/scarb/src/compiler/plugin/proc_macro/compilation.rs @@ -200,8 +200,9 @@ fn run_cargo(action: CargoAction, package: &Package, ws: &Workspace<'_>) -> Resu .to_path_buf(), config: ws.config(), }; + let span = trace_span!("proc_macro"); { - let _ = trace_span!("proc_macro").enter(); + let _guard = span.enter(); exec(&mut cmd.into(), ws.config())?; } Ok(()) diff --git a/scarb/src/compiler/repository.rs b/scarb/src/compiler/repository.rs index 523f5a5eb..0cc3c45d1 100644 --- a/scarb/src/compiler/repository.rs +++ b/scarb/src/compiler/repository.rs @@ -7,7 +7,9 @@ use cairo_lang_compiler::db::RootDatabase; use itertools::Itertools; use smol_str::SmolStr; -use crate::compiler::compilers::{LibCompiler, StarknetContractCompiler, TestCompiler}; +use crate::compiler::compilers::{ + ExecutableCompiler, LibCompiler, StarknetContractCompiler, TestCompiler, +}; use crate::compiler::{CairoCompilationUnit, CompilationUnitAttributes, Compiler}; use crate::core::Workspace; @@ -27,6 +29,7 @@ impl CompilerRepository { repo.add(Box::new(LibCompiler)).unwrap(); repo.add(Box::new(StarknetContractCompiler)).unwrap(); repo.add(Box::new(TestCompiler)).unwrap(); + repo.add(Box::new(ExecutableCompiler)).unwrap(); repo } diff --git a/scarb/src/core/manifest/target_kind.rs b/scarb/src/core/manifest/target_kind.rs index be789157d..0a99a385f 100644 --- a/scarb/src/core/manifest/target_kind.rs +++ b/scarb/src/core/manifest/target_kind.rs @@ -15,6 +15,7 @@ impl TargetKind { pub const LIB: Self = TargetKind(SmolStr::new_inline("lib")); pub const TEST: Self = TargetKind(SmolStr::new_inline("test")); pub const STARKNET_CONTRACT: Self = TargetKind(SmolStr::new_inline("starknet-contract")); + pub const EXECUTABLE: Self = TargetKind(SmolStr::new_inline("executable")); /// Constructs and validates new [`TargetKind`]. /// diff --git a/scarb/tests/build_targets.rs b/scarb/tests/build_targets.rs index edba3c70b..8d8500cc9 100644 --- a/scarb/tests/build_targets.rs +++ b/scarb/tests/build_targets.rs @@ -1090,3 +1090,32 @@ fn transitive_dev_deps_not_available() { error: could not check `hello` due to previous error "#}); } + +#[test] +fn test_executable_compiler_creates_output_files() { + let t = TempDir::new().unwrap(); + ProjectBuilder::start() + .name("executable_test") + .dep_cairo_test() + .dep_starknet() + .dep_executable() + .manifest_extra(indoc! {r#" + [[target.executable]] + "#}) + .lib_cairo(indoc! {r#" + #[executable] + fn main() -> felt252 { + 42 + } + "#}) + .build(&t); + + Scarb::quick_snapbox() + .arg("build") + .current_dir(&t) + .assert() + .success(); + + t.child("target/dev/executable_test.executable.json") + .assert(predicates::path::exists()); +}