diff --git a/Cargo.lock b/Cargo.lock index 5d60fa82caa..bd721e82b1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1636,6 +1636,7 @@ name = "hydro_test" version = "0.0.0" dependencies = [ "async-ssh2-lite", + "ctor", "dfir_macro", "futures", "hydro_deploy", diff --git a/hydro_deploy/core/src/hydroflow_crate/build.rs b/hydro_deploy/core/src/hydroflow_crate/build.rs index b6612ca288a..edd3ced5389 100644 --- a/hydro_deploy/core/src/hydroflow_crate/build.rs +++ b/hydro_deploy/core/src/hydroflow_crate/build.rs @@ -2,7 +2,7 @@ use std::error::Error; use std::fmt::Display; use std::io::BufRead; use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; +use std::process::{Command, ExitStatus, Stdio}; use std::sync::OnceLock; use cargo_metadata::diagnostic::Diagnostic; @@ -179,14 +179,20 @@ pub async fn build_crate_memoized(params: BuildParams) -> Result<&'static BuildO ProgressTracker::println(msg.message.rendered.as_deref().unwrap()); diagnostics.push(msg.message); } + cargo_metadata::Message::TextLine(line) => { + ProgressTracker::println(&line); + } + cargo_metadata::Message::BuildFinished(_) => {} + cargo_metadata::Message::BuildScriptExecuted(_) => {} _ => {} } } - if spawned.wait().unwrap().success() { + let exit_code = spawned.wait().unwrap(); + if exit_code.success() { Err(BuildError::NoBinaryEmitted) } else { - Err(BuildError::FailedToBuildCrate(diagnostics)) + Err(BuildError::FailedToBuildCrate(exit_code, diagnostics)) } }) .await @@ -198,7 +204,7 @@ pub async fn build_crate_memoized(params: BuildParams) -> Result<&'static BuildO #[derive(Clone, Debug)] pub enum BuildError { - FailedToBuildCrate(Vec), + FailedToBuildCrate(ExitStatus, Vec), TokioJoinError, NoBinaryEmitted, } @@ -206,8 +212,8 @@ pub enum BuildError { impl Display for BuildError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::FailedToBuildCrate(diagnostics) => { - writeln!(f, "Failed to build crate:")?; + Self::FailedToBuildCrate(exit_status, diagnostics) => { + writeln!(f, "Failed to build crate (exit status {}):", exit_status)?; for diagnostic in diagnostics { write!(f, "{}", diagnostic)?; } diff --git a/hydro_lang/Cargo.toml b/hydro_lang/Cargo.toml index 66a4e6b0cce..c102a46d01c 100644 --- a/hydro_lang/Cargo.toml +++ b/hydro_lang/Cargo.toml @@ -22,7 +22,6 @@ build = [ "dep:dfir_lang" ] [dependencies] bincode = "1.3.1" -ctor = "0.2.8" hydro_deploy = { path = "../hydro_deploy/core", version = "^0.11.0", optional = true } dfir_rs = { path = "../dfir_rs", version = "^0.11.0", default-features = false, features = ["deploy_integration"] } dfir_lang = { path = "../dfir_lang", version = "^0.11.0", optional = true } @@ -41,6 +40,7 @@ syn = { version = "2.0.46", features = [ "parsing", "extra-traits", "visit-mut" tokio = { version = "1.29.0", features = [ "full" ] } toml = { version = "0.8.0", optional = true } trybuild-internals-api = { version = "1.0.99", optional = true } +ctor = "0.2" [build-dependencies] stageleft_tool = { path = "../stageleft_tool", version = "^0.5.0" } diff --git a/hydro_lang/src/deploy/trybuild.rs b/hydro_lang/src/deploy/trybuild.rs index a79f0c9118a..b40c250a341 100644 --- a/hydro_lang/src/deploy/trybuild.rs +++ b/hydro_lang/src/deploy/trybuild.rs @@ -10,7 +10,7 @@ use trybuild_internals_api::env::Update; use trybuild_internals_api::run::{PathDependency, Project}; use trybuild_internals_api::{dependencies, features, path, Runner}; -use super::trybuild_rewriters::{ReplaceCrateNameWithStaged, ReplaceCrateWithOrig}; +use super::trybuild_rewriters::ReplaceCrateNameWithStaged; static IS_TEST: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); @@ -44,19 +44,19 @@ pub fn create_graph_trybuild( ReplaceCrateNameWithStaged { crate_name: crate_name.clone(), + is_test, } .visit_file_mut(&mut generated_code); - let mut inlined_staged = stageleft_tool::gen_staged_trybuild( - &path!(source_dir / "src" / "lib.rs"), - crate_name.clone(), - is_test, - ); - - ReplaceCrateWithOrig { - crate_name: crate_name.clone(), - } - .visit_file_mut(&mut inlined_staged); + let inlined_staged = if is_test { + stageleft_tool::gen_staged_trybuild( + &path!(source_dir / "src" / "lib.rs"), + crate_name.clone(), + is_test, + ) + } else { + syn::parse_quote!() + }; let source = prettyplease::unparse(&syn::parse_quote! { #generated_code diff --git a/hydro_lang/src/deploy/trybuild_rewriters.rs b/hydro_lang/src/deploy/trybuild_rewriters.rs index 6a9a14cafe7..6af050a5183 100644 --- a/hydro_lang/src/deploy/trybuild_rewriters.rs +++ b/hydro_lang/src/deploy/trybuild_rewriters.rs @@ -2,6 +2,7 @@ use syn::visit_mut::VisitMut; pub struct ReplaceCrateNameWithStaged { pub crate_name: String, + pub is_test: bool, } impl VisitMut for ReplaceCrateNameWithStaged { @@ -9,27 +10,22 @@ impl VisitMut for ReplaceCrateNameWithStaged { if let Some(first) = i.path.segments.first() { if first.ident == self.crate_name { let tail = i.path.segments.iter().skip(1).collect::>(); - *i = syn::parse_quote!(crate::__staged #(::#tail)*); + + if self.is_test { + *i = syn::parse_quote!(crate::__staged #(::#tail)*); + } else { + let crate_ident = syn::Ident::new(&self.crate_name, first.ident.span()); + *i = syn::parse_quote!(#crate_ident::__staged #(::#tail)*); + } } } syn::visit_mut::visit_type_path_mut(self, i); } -} -pub struct ReplaceCrateWithOrig { - pub crate_name: String, -} - -impl VisitMut for ReplaceCrateWithOrig { - fn visit_item_use_mut(&mut self, i: &mut syn::ItemUse) { - if let syn::UseTree::Path(p) = &mut i.tree { - if p.ident == "crate" { - p.ident = syn::Ident::new(&self.crate_name, p.ident.span()); - i.leading_colon = Some(Default::default()); - } + fn visit_use_path_mut(&mut self, i: &mut syn::UsePath) { + if i.ident == "crate" && !self.is_test { + i.ident = syn::Ident::new(&self.crate_name, i.ident.span()); } - - syn::visit_mut::visit_item_use_mut(self, i); } } diff --git a/hydro_lang/src/lib.rs b/hydro_lang/src/lib.rs index 438ffcc73bf..aaad68cb902 100644 --- a/hydro_lang/src/lib.rs +++ b/hydro_lang/src/lib.rs @@ -54,7 +54,7 @@ fn add_private_reexports() { #[stageleft::runtime] #[cfg(test)] -mod tests { +mod test_init { #[ctor::ctor] fn init() { crate::deploy::init_test(); diff --git a/hydro_std/Cargo.toml b/hydro_std/Cargo.toml index 20599f0fae3..fdb4eaf80ff 100644 --- a/hydro_std/Cargo.toml +++ b/hydro_std/Cargo.toml @@ -26,4 +26,4 @@ hydro_lang = { path = "../hydro_lang", version = "^0.11.0" } insta = "1.39" hydro_deploy = { path = "../hydro_deploy/core", version = "^0.11.0" } async-ssh2-lite = { version = "0.5.0", features = ["vendored-openssl"] } -ctor = "0.2.8" +ctor = "0.2" diff --git a/hydro_std/src/lib.rs b/hydro_std/src/lib.rs index 624c2f33af7..bec45446438 100644 --- a/hydro_std/src/lib.rs +++ b/hydro_std/src/lib.rs @@ -5,7 +5,7 @@ pub mod request_response; #[stageleft::runtime] #[cfg(test)] -mod tests { +mod test_init { #[ctor::ctor] fn init() { hydro_lang::deploy::init_test(); diff --git a/hydro_test/Cargo.toml b/hydro_test/Cargo.toml index 3d3716a7e7d..8e860bba966 100644 --- a/hydro_test/Cargo.toml +++ b/hydro_test/Cargo.toml @@ -23,6 +23,7 @@ serde = { version = "1.0.197", features = [ "derive" ] } stageleft_tool = { path = "../stageleft_tool", version = "^0.5.0" } [dev-dependencies] +ctor = "0.2" insta = "1.39" hydro_deploy = { path = "../hydro_deploy/core", version = "^0.11.0" } hydro_lang = { path = "../hydro_lang", version = "^0.11.0", features = [ "deploy" ] } diff --git a/hydro_test/src/lib.rs b/hydro_test/src/lib.rs index 33e78227457..0eacd849987 100644 --- a/hydro_test/src/lib.rs +++ b/hydro_test/src/lib.rs @@ -9,3 +9,12 @@ pub mod distributed; mod docs { dfir_macro::doctest_markdown_glob!("docs/docs/hydro/**/*.md*"); } + +#[stageleft::runtime] +#[cfg(test)] +mod test_init { + #[ctor::ctor] + fn init() { + hydro_lang::deploy::init_test(); + } +} diff --git a/stageleft_tool/src/lib.rs b/stageleft_tool/src/lib.rs index 2d2dd15fbc7..6f1190fbe0a 100644 --- a/stageleft_tool/src/lib.rs +++ b/stageleft_tool/src/lib.rs @@ -157,6 +157,22 @@ impl VisitMut for GenFinalPubVistor { syn::visit_mut::visit_use_path_mut(self, i); } + fn visit_vis_restricted_mut(&mut self, _i: &mut syn::VisRestricted) { + // don't treat the restriction as a path, we don't want to rewrite that to `__staged` + } + + fn visit_path_mut(&mut self, i: &mut syn::Path) { + if !i.segments.is_empty() && i.segments[0].ident == "crate" { + i.segments.insert( + 1, + syn::PathSegment { + ident: parse_quote!(__staged), + arguments: Default::default(), + }, + ); + } + } + fn visit_item_mod_mut(&mut self, i: &mut syn::ItemMod) { let is_runtime_or_test = i.attrs.iter().any(|a| { a.path().to_token_stream().to_string() == "stageleft :: runtime" diff --git a/template/hydro/Cargo.toml b/template/hydro/Cargo.toml index 386d6f0d176..7d3f480e54d 100644 --- a/template/hydro/Cargo.toml +++ b/template/hydro/Cargo.toml @@ -19,6 +19,7 @@ stageleft_tool = { git = "{{ hydro_git | default: 'https://github.com/hydro-proj [dev-dependencies] async-ssh2-lite = { version = "0.5.0", features = ["vendored-openssl"] } +ctor = "0.2" hydro_deploy = { git = "{{ hydro_git | default: 'https://github.com/hydro-project/hydro.git' }}", branch = "{{ hydro_branch | default: 'main' }}" } hydro_lang = { git = "{{ hydro_git | default: 'https://github.com/hydro-project/hydro.git' }}", branch = "{{ hydro_branch | default: 'main' }}", features = [ "deploy", diff --git a/template/hydro/src/lib.rs b/template/hydro/src/lib.rs index 4e3abdc4f4c..d12b97d7624 100644 --- a/template/hydro/src/lib.rs +++ b/template/hydro/src/lib.rs @@ -3,3 +3,12 @@ stageleft::stageleft_no_entry_crate!(); pub mod first_ten; pub mod first_ten_cluster; pub mod first_ten_distributed; + +#[stageleft::runtime] +#[cfg(test)] +mod test_init { + #[ctor::ctor] + fn init() { + hydro_lang::deploy::init_test(); + } +}