Skip to content

Commit f38a4b3

Browse files
feat(apollo_infra_utils): better cairo0 compiler checks
1 parent ed9e2c1 commit f38a4b3

File tree

5 files changed

+75
-27
lines changed

5 files changed

+75
-27
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/apollo_infra_utils/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ colored = { workspace = true, optional = true }
1919
serde = { workspace = true, features = ["derive"] }
2020
serde_json.workspace = true
2121
socket2 = { workspace = true, optional = true }
22+
thiserror.workspace = true
2223
tokio = { workspace = true, features = ["process", "rt", "time"] }
2324
toml = { workspace = true, optional = true }
2425
tracing.workspace = true
2526

2627
[dev-dependencies]
28+
assert-json-diff.workspace = true
2729
cached.workspace = true
30+
colored.workspace = true
2831
nix.workspace = true
2932
pretty_assertions.workspace = true
3033
rstest.workspace = true
Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,67 @@
1-
use std::fs;
21
use std::path::PathBuf;
32
use std::process::Command;
43
use std::sync::LazyLock;
54

65
use crate::path::resolve_project_relative_path;
76

7+
#[cfg(test)]
8+
#[path = "cairo0_compiler_test.rs"]
9+
pub mod test;
10+
11+
pub const STARKNET_COMPILE_DEPRECATED: &str = "starknet-compile-deprecated";
12+
pub const CAIRO0_COMPILE: &str = "cairo-compile";
13+
pub const EXPECTED_CAIRO0_VERSION: &str = "0.13.5";
14+
815
/// The local python requirements used to determine the cairo0 compiler version.
9-
static PIP_REQUIREMENTS_FILE: LazyLock<PathBuf> =
16+
pub(crate) static PIP_REQUIREMENTS_FILE: LazyLock<PathBuf> =
1017
LazyLock::new(|| resolve_project_relative_path("scripts/requirements.txt").unwrap());
1118

19+
#[derive(thiserror::Error, Debug)]
20+
pub enum Cairo0CompilerVersionError {
21+
#[error("{compiler} version is not correct: required {required}, got {existing}.")]
22+
IncorrectVersion { compiler: String, existing: String, required: String },
23+
#[error("{0} not found.")]
24+
NotFound(String),
25+
}
26+
27+
pub fn cairo0_compilers_correct_version() -> Result<(), Cairo0CompilerVersionError> {
28+
for compiler in [CAIRO0_COMPILE, STARKNET_COMPILE_DEPRECATED] {
29+
let version = match Command::new(compiler).arg("--version").output() {
30+
Ok(output) => String::from_utf8_lossy(&output.stdout).to_string(),
31+
Err(error) => {
32+
return Err(Cairo0CompilerVersionError::NotFound(format!(
33+
"Failed to get {compiler} version: {error}."
34+
)));
35+
}
36+
};
37+
if !version.trim().ends_with(EXPECTED_CAIRO0_VERSION) {
38+
return Err(Cairo0CompilerVersionError::IncorrectVersion {
39+
compiler: compiler.to_string(),
40+
existing: version,
41+
required: EXPECTED_CAIRO0_VERSION.to_string(),
42+
});
43+
}
44+
}
45+
46+
Ok(())
47+
}
48+
1249
/// Verifies that the required Cairo0 compiler is available; panics if unavailable.
1350
pub fn verify_cairo0_compiler_deps() {
14-
// Python compiler. Verify correct version.
15-
let cairo_lang_version_output =
16-
Command::new("sh").arg("-c").arg("pip freeze | grep cairo-lang").output().unwrap().stdout;
17-
let cairo_lang_version_untrimmed = String::from_utf8(cairo_lang_version_output).unwrap();
18-
let cairo_lang_version = cairo_lang_version_untrimmed.trim();
19-
let requirements_contents = fs::read_to_string(&*PIP_REQUIREMENTS_FILE).unwrap();
20-
let expected_cairo_lang_version = requirements_contents
21-
.lines()
22-
.find(|line| line.starts_with("cairo-lang"))
23-
.unwrap_or_else(|| panic!("Could not find cairo-lang in {:?}.", *PIP_REQUIREMENTS_FILE))
24-
.trim();
25-
26-
assert!(
27-
expected_cairo_lang_version.ends_with(cairo_lang_version),
28-
"cairo-lang version {expected_cairo_lang_version} not found ({}). Run the following \
29-
commands (enter a python venv and install dependencies) and retry:\npython -m venv \
30-
sequencer_venv\n. sequencer_venv/bin/activate\npip install -r {:?}",
31-
if cairo_lang_version.is_empty() {
32-
String::from("no installed cairo-lang found")
33-
} else {
34-
format!("installed version: {cairo_lang_version}")
35-
},
36-
*PIP_REQUIREMENTS_FILE
51+
let specific_error = match cairo0_compilers_correct_version() {
52+
Ok(_) => {
53+
return;
54+
}
55+
Err(Cairo0CompilerVersionError::NotFound(_)) => "no installed cairo-lang found".to_string(),
56+
Err(Cairo0CompilerVersionError::IncorrectVersion { existing, .. }) => {
57+
format!("installed version: {existing}")
58+
}
59+
};
60+
61+
panic!(
62+
"cairo-lang version {EXPECTED_CAIRO0_VERSION} not found ({specific_error}). Run the \
63+
following commands (enter a python venv and install dependencies) and retry:\npython -m \
64+
venv sequencer_venv\n. sequencer_venv/bin/activate\npip install -r {:?}",
65+
PIP_REQUIREMENTS_FILE.to_str().expect("Path to requirements.txt is valid unicode.")
3766
);
3867
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use crate::cairo0_compiler::{EXPECTED_CAIRO0_VERSION, PIP_REQUIREMENTS_FILE};
2+
3+
#[test]
4+
fn test_cairo0_version_pip_requirements() {
5+
let requirements_contents = std::fs::read_to_string(&*PIP_REQUIREMENTS_FILE).unwrap();
6+
let pip_cairo_lang_version = requirements_contents
7+
.lines()
8+
.find(|line| line.starts_with("cairo-lang"))
9+
.unwrap_or_else(|| panic!("Could not find cairo-lang in {:?}.", *PIP_REQUIREMENTS_FILE))
10+
.trim();
11+
assert_eq!(pip_cairo_lang_version, format!("cairo-lang=={EXPECTED_CAIRO0_VERSION}"));
12+
}

crates/blockifier_test_utils/src/cairo_compile.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use std::io::Write;
33
use std::path::{Path, PathBuf};
44
use std::process::{Command, Output};
55

6-
use apollo_infra_utils::cairo0_compiler::verify_cairo0_compiler_deps;
6+
use apollo_infra_utils::cairo0_compiler::{
7+
verify_cairo0_compiler_deps,
8+
STARKNET_COMPILE_DEPRECATED,
9+
};
710
use apollo_infra_utils::cairo_compiler_version::cairo1_compiler_version;
811
use apollo_infra_utils::compile_time_cargo_manifest_dir;
912
use tempfile::NamedTempFile;
@@ -53,7 +56,7 @@ pub fn cairo0_compile(
5356
debug_info: bool,
5457
) -> CompilationArtifacts {
5558
verify_cairo0_compiler_deps();
56-
let mut command = Command::new("starknet-compile-deprecated");
59+
let mut command = Command::new(STARKNET_COMPILE_DEPRECATED);
5760
command.arg(&path);
5861
if let Some(extra_arg) = extra_arg {
5962
command.arg(extra_arg);

0 commit comments

Comments
 (0)