Skip to content

Commit 121696d

Browse files
maciektrDelevoXDG
andauthored
Fix check command for cairo compilation units dependant on Scarb proc macros (#1780)
fix #1779 --------- Signed-off-by: maciektr <[email protected]> Co-authored-by: Maksim Zdobnikau <[email protected]>
1 parent 91fc0ad commit 121696d

File tree

2 files changed

+81
-6
lines changed

2 files changed

+81
-6
lines changed

scarb/src/ops/compile.rs

+48-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use scarb_ui::args::FeaturesSpec;
88
use scarb_ui::components::Status;
99
use scarb_ui::HumanDuration;
1010
use smol_str::{SmolStr, ToSmolStr};
11+
use std::collections::HashSet;
1112
use std::thread;
1213

1314
use crate::compiler::db::{build_scarb_root_database, has_starknet_plugin, ScarbDatabase};
@@ -97,12 +98,12 @@ impl CompileOpts {
9798

9899
#[tracing::instrument(skip_all, level = "debug")]
99100
pub fn compile(packages: Vec<PackageId>, opts: CompileOpts, ws: &Workspace<'_>) -> Result<()> {
100-
process(packages, opts, ws, compile_unit, None)
101+
process(packages, opts, ws, compile_units, None)
101102
}
102103

103104
#[tracing::instrument(skip_all, level = "debug")]
104105
pub fn check(packages: Vec<PackageId>, opts: CompileOpts, ws: &Workspace<'_>) -> Result<()> {
105-
process(packages, opts, ws, check_unit, Some("checking"))
106+
process(packages, opts, ws, check_units, Some("checking"))
106107
}
107108

108109
#[tracing::instrument(skip_all, level = "debug")]
@@ -114,7 +115,7 @@ fn process<F>(
114115
operation_type: Option<&str>,
115116
) -> Result<()>
116117
where
117-
F: FnMut(CompilationUnit, &Workspace<'_>) -> Result<()>,
118+
F: FnMut(Vec<CompilationUnit>, &Workspace<'_>) -> Result<()>,
118119
{
119120
let resolve = ops::resolve_workspace(ws)?;
120121
let packages_to_process = ws
@@ -155,9 +156,7 @@ where
155156
})
156157
.collect::<Vec<_>>();
157158

158-
for unit in compilation_units {
159-
operation(unit, ws)?;
160-
}
159+
operation(compilation_units, ws)?;
161160

162161
let elapsed_time = HumanDuration(ws.config().elapsed_time());
163162
let profile = ws.current_profile()?;
@@ -174,6 +173,13 @@ where
174173

175174
/// Run compiler in a new thread.
176175
/// The stack size of created threads can be altered with `RUST_MIN_STACK` env variable.
176+
pub fn compile_units(units: Vec<CompilationUnit>, ws: &Workspace<'_>) -> Result<()> {
177+
for unit in units {
178+
compile_unit(unit, ws)?;
179+
}
180+
Ok(())
181+
}
182+
177183
pub fn compile_unit(unit: CompilationUnit, ws: &Workspace<'_>) -> Result<()> {
178184
thread::scope(|s| {
179185
thread::Builder::new()
@@ -217,6 +223,42 @@ fn compile_unit_inner(unit: CompilationUnit, ws: &Workspace<'_>) -> Result<()> {
217223
})
218224
}
219225

226+
fn check_units(units: Vec<CompilationUnit>, ws: &Workspace<'_>) -> Result<()> {
227+
// Select proc macro units that need to be compiled for Cairo compilation units.
228+
let required_plugins = units
229+
.iter()
230+
.flat_map(|unit| match unit {
231+
CompilationUnit::Cairo(unit) => unit
232+
.cairo_plugins
233+
.iter()
234+
.map(|p| p.package.id)
235+
.collect_vec(),
236+
_ => Vec::new(),
237+
})
238+
.collect::<HashSet<PackageId>>();
239+
240+
// We guarantee that proc-macro units are always processed first,
241+
// so that all required plugins are compiled before we start checking Cairo units.
242+
let units = units.into_iter().sorted_by_key(|unit| {
243+
if matches!(unit, CompilationUnit::ProcMacro(_)) {
244+
0
245+
} else {
246+
1
247+
}
248+
});
249+
250+
for unit in units {
251+
if matches!(unit, CompilationUnit::ProcMacro(_))
252+
&& required_plugins.contains(&unit.main_package_id())
253+
{
254+
compile_unit(unit, ws)?;
255+
} else {
256+
check_unit(unit, ws)?;
257+
}
258+
}
259+
Ok(())
260+
}
261+
220262
fn check_unit(unit: CompilationUnit, ws: &Workspace<'_>) -> Result<()> {
221263
let package_name = unit.main_package_id().name.clone();
222264

scarb/tests/build_cairo_plugin.rs

+33
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use scarb_test_support::cairo_plugin_project_builder::CairoPluginProjectBuilder;
66
use scarb_test_support::command::Scarb;
77
use scarb_test_support::fsx::ChildPathEx;
88
use scarb_test_support::project_builder::ProjectBuilder;
9+
use scarb_test_support::workspace_builder::WorkspaceBuilder;
910
use snapbox::assert_matches;
1011

1112
#[test]
@@ -70,6 +71,38 @@ fn check_cairo_plugin() {
7071
);
7172
}
7273

74+
#[test]
75+
fn can_check_cairo_project_with_plugins() {
76+
let temp = TempDir::new().unwrap();
77+
let t = temp.child("some");
78+
CairoPluginProjectBuilder::default().build(&t);
79+
let project = temp.child("hello");
80+
let y = project.child("other");
81+
CairoPluginProjectBuilder::default().name("other").build(&y);
82+
WorkspaceBuilder::start()
83+
.add_member("other")
84+
.package(
85+
ProjectBuilder::start()
86+
.name("hello")
87+
.version("1.0.0")
88+
.dep("some", &t),
89+
)
90+
.build(&project);
91+
Scarb::quick_snapbox()
92+
.arg("check")
93+
// Disable output from Cargo.
94+
.env("CARGO_TERM_QUIET", "true")
95+
.current_dir(&project)
96+
.assert()
97+
.success()
98+
.stdout_matches(indoc! {r#"
99+
[..]Compiling some v1.0.0 ([..]Scarb.toml)
100+
[..]Checking other v1.0.0 ([..]Scarb.toml)
101+
[..]Checking hello v1.0.0 ([..]Scarb.toml)
102+
[..]Finished checking `dev` profile target(s) in [..]
103+
"#});
104+
}
105+
73106
#[test]
74107
fn resolve_fetched_plugins() {
75108
let t = TempDir::new().unwrap();

0 commit comments

Comments
 (0)