diff --git a/scarb/src/compiler/compilers/executable.rs b/scarb/src/compiler/compilers/executable.rs index e69de29bb..582ccc20f 100644 --- a/scarb/src/compiler/compilers/executable.rs +++ b/scarb/src/compiler/compilers/executable.rs @@ -0,0 +1,46 @@ +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 executable = { + let _ = trace_span!("compile_executable").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/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/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()); +}