Skip to content

Commit

Permalink
chore(cairo_native): make the starknet-native-compile crate a part of…
Browse files Browse the repository at this point in the history
… the workspace
  • Loading branch information
avi-starkware committed Feb 2, 2025
1 parent a3d8940 commit b3f6e8e
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 46 deletions.
28 changes: 27 additions & 1 deletion Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
resolver = "2"

members = [
"crates/bin/starknet-native-compile",
"crates/blockifier",
"crates/blockifier_reexecution",
"crates/committer_cli",
Expand Down Expand Up @@ -57,8 +58,6 @@ members = [
"workspace_tests",
]

exclude = ["crates/bin/starknet-native-compile"]

[workspace.package]
version = "0.14.0-rc.0"
edition = "2021"
Expand Down Expand Up @@ -105,6 +104,7 @@ cairo-lang-utils = "2.10.0-rc.1"
cairo-native = { git = "https://github.com/lambdaclass/cairo_native", rev = "981093a" }
cairo-vm = "=1.0.2"
camelpaste = "0.1.0"
cargo_metadata = "0.19.1"
chrono = "0.4.26"
clap = "4.5.4"
colored = "2.1.0"
Expand Down
37 changes: 26 additions & 11 deletions crates/bin/starknet-native-compile/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
[package]
name = "starknet-native-compile"
# The version of this crate should equal the version of cairo-native.
version = "0.2.5"
edition = "2021"
repository = "https://github.com/starkware-libs/sequencer/"
license = "Apache-2.0"
# Make sure this version equals the version of `cairo-native`.
version.workspace = true
edition.workspace = true
repository.workspace = true
license-file.workspace = true
description = "A binary that compiles Sierra into Cairo native."

[lints]
workspace = true

[features]
cairo_native = [
"dep:cairo-lang-sierra",
"dep:cairo-lang-starknet-classes",
"dep:cairo-native",
"dep:clap",
"dep:serde_json",
]

[dependencies]
# TODO(Avi, 01/02/2025): Check consistency with the blockifier.
cairo-lang-sierra = "2.10.0-rc.1"
cairo-lang-starknet-classes = "2.10.0-rc.1"
cairo-native = { git = "https://github.com/lambdaclass/cairo_native", rev = "981093a" }
clap = { version = "4.5.4", features = ["derive"] }
serde_json = "1.0.116"
cairo-lang-sierra = { workspace = true, optional = true }
cairo-lang-starknet-classes = { workspace = true, optional = true }
cairo-native = { workspace = true, optional = true }
clap = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }

[build-dependencies]
cargo_metadata.workspace = true
30 changes: 30 additions & 0 deletions crates/bin/starknet-native-compile/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#[cfg(feature = "cairo_native")]
use cargo_metadata::{CargoOpt, MetadataCommand};

#[cfg(feature = "cairo_native")]
fn main() {
let cairo_native_version = find_cairo_native_version();
println!("cargo:rustc-env=DEP_CAIRO_NATIVE_VERSION={}", cairo_native_version);
}

#[cfg(feature = "cairo_native")]
fn find_cairo_native_version() -> String {
let target_package_name = "cairo-native";

// Query Cargo for the actual resolved metadata
let metadata = MetadataCommand::new()
.features(CargoOpt::SomeFeatures(vec!["cairo_native".into()]))
.exec()
.unwrap_or_else(|err| {
eprintln!("Failed to read Cargo metadata: {}", err);
std::process::exit(1);
});

// Find the package in the resolved graph
let package = metadata.packages.iter().find(|package| package.name == target_package_name);

package.expect("Could not find cairo-native package in Cargo metadata").version.to_string()
}

#[cfg(not(feature = "cairo_native"))]
fn main() {}
58 changes: 38 additions & 20 deletions crates/bin/starknet-native-compile/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
#[cfg(feature = "cairo_native")]
use std::path::PathBuf;
use std::process;

#[cfg(feature = "cairo_native")]
use cairo_native::executor::AotContractExecutor;
#[cfg(feature = "cairo_native")]
use cairo_native::OptLevel;
#[cfg(feature = "cairo_native")]
use clap::Parser;

#[cfg(feature = "cairo_native")]
use crate::utils::load_sierra_program_from_file;

#[cfg(feature = "cairo_native")]
mod utils;

#[cfg(feature = "cairo_native")]
#[derive(Parser, Debug)]
#[clap(version, verbatim_doc_comment)]
#[command(version=env!("DEP_CAIRO_NATIVE_VERSION"),verbatim_doc_comment)]
struct Args {
/// The path of the Sierra file to compile.
path: PathBuf,
Expand All @@ -19,25 +26,36 @@ struct Args {
}

fn main() {
// TODO(Avi, 01/12/2024): Find a way to restrict time, memory and file size during compilation.
let args = Args::parse();
let path = args.path;
let output = args.output;
#[cfg(not(feature = "cairo_native"))]
{
eprintln!(
"The `starknet-native-compile` binary was compiled without the 'cairo_native' feature."
);
process::exit(1);
}
#[cfg(feature = "cairo_native")]
{
// TODO(Avi, 01/12/2024): Find a way to restrict time, memory and file size during
// compilation.
let args = Args::parse();
let path = args.path;
let output = args.output;

let (contract_class, sierra_program) = load_sierra_program_from_file(&path);
let (contract_class, sierra_program) = load_sierra_program_from_file(&path);

// TODO(Avi, 01/12/2024): Test different optimization levels for best performance.
let mut contract_executor = AotContractExecutor::new(
&sierra_program,
&contract_class.entry_points_by_type,
OptLevel::default(),
)
.unwrap_or_else(|err| {
eprintln!("Error compiling Sierra program: {}", err);
process::exit(1);
});
contract_executor.save(output.clone()).unwrap_or_else(|err| {
eprintln!("Error saving compiled program: {}", err);
process::exit(1);
});
// TODO(Avi, 01/12/2024): Test different optimization levels for best performance.
let mut contract_executor = AotContractExecutor::new(
&sierra_program,
&contract_class.entry_points_by_type,
OptLevel::default(),
)
.unwrap_or_else(|err| {
eprintln!("Error compiling Sierra program: {}", err);
process::exit(1);
});
contract_executor.save(output.clone()).unwrap_or_else(|err| {
eprintln!("Error saving compiled program: {}", err);
process::exit(1);
});
}
}
5 changes: 5 additions & 0 deletions crates/bin/starknet-native-compile/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#[cfg(feature = "cairo_native")]
use std::path::PathBuf;
#[cfg(feature = "cairo_native")]
use std::process;

#[cfg(feature = "cairo_native")]
use cairo_lang_sierra::program::Program;
#[cfg(feature = "cairo_native")]
use cairo_lang_starknet_classes::contract_class::ContractClass;

#[cfg(feature = "cairo_native")]
pub(crate) fn load_sierra_program_from_file(path: &PathBuf) -> (ContractClass, Program) {
let raw_contract_class = std::fs::read_to_string(path).unwrap_or_else(|err| {
eprintln!("Error reading Sierra file: {}", err);
Expand Down
34 changes: 23 additions & 11 deletions crates/starknet_sierra_multicompile/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ fn main() {
install_starknet_native_compile();
}

const REQUIRED_CAIRO_LANG_VERSION: &str = "2.7.1";
const REQUIRED_CAIRO_LANG_VERSION: &str = "2.10.0-rc.1";
#[cfg(feature = "cairo_native")]
const REQUIRED_CAIRO_NATIVE_VERSION: &str = "0.2.5";
const REQUIRED_CAIRO_NATIVE_VERSION: &str = "0.2.9";

/// Downloads the Cairo crate from StarkWare's release page and extracts its contents into the
/// `target` directory. This crate includes the `starknet-sierra-compile` binary, which is used to
Expand All @@ -27,7 +27,7 @@ fn install_starknet_sierra_compile() {
let binary_name = CAIRO_LANG_BINARY_NAME;
let required_version = REQUIRED_CAIRO_LANG_VERSION;

let cargo_install_args = &[binary_name, "--version", required_version];
let cargo_install_args = vec![binary_name, "--version", required_version];
install_compiler_binary(binary_name, required_version, cargo_install_args);
}

Expand All @@ -44,18 +44,30 @@ fn install_starknet_native_compile() {
starknet_infra_utils::path::project_path().expect("Should be able to get the project path");

let starknet_native_compile_crate_path = repo_root_dir.join("crates/bin").join(binary_name);
let starknet_native_compile_crate_path_str = starknet_native_compile_crate_path
.to_str()
.expect("Failed to convert the crate path to str");
println!("cargo:rerun-if-changed={}", starknet_native_compile_crate_path_str);

let cargo_install_args = &["--path", starknet_native_compile_crate_path_str];
let mut cargo_install_args: Vec<&str>;
if starknet_native_compile_crate_path.exists() {
println!("The crate {binary_name} is found locally - installing from local path.");
let starknet_native_compile_crate_path_str = starknet_native_compile_crate_path
.to_str()
.expect("Failed to convert the crate path to str");
println!("cargo:rerun-if-changed={}", starknet_native_compile_crate_path_str);

cargo_install_args = vec!["--path", starknet_native_compile_crate_path_str];
} else {
println!("The crate {binary_name} is not found locally - installing from crates.io.");
cargo_install_args = vec![binary_name, "--version", required_version];
}
cargo_install_args.append(&mut vec!["--features", "cairo_native"]);
install_compiler_binary(binary_name, required_version, cargo_install_args);
}

fn install_compiler_binary(binary_name: &str, required_version: &str, cargo_install_args: &[&str]) {
fn install_compiler_binary(
binary_name: &str,
required_version: &str,
cargo_install_args: Vec<&str>,
) {
let binary_path = binary_path(out_dir(), binary_name);
println!("cargo:rerun-if-changed={}", binary_path.to_str().unwrap());
println!("cargo:rerun-if-changed={}", binary_path.display());

match Command::new(&binary_path).args(["--version"]).output() {
Ok(binary_version) => {
Expand Down
2 changes: 1 addition & 1 deletion crates/starknet_sierra_multicompile/src/compile_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn get_faulty_test_contract() -> ContractClass {
#[rstest]
#[case::command_line_compiler(command_line_compiler())]
fn test_compile_sierra_to_casm(#[case] compiler: impl SierraToCasmCompiler) {
let expected_casm_contract_length = 72304;
let expected_casm_contract_length = 72305;

let contract_class = get_test_contract();
let casm_contract = compiler.compile(contract_class).unwrap();
Expand Down

0 comments on commit b3f6e8e

Please sign in to comment.