diff --git a/crates/moon/src/cli.rs b/crates/moon/src/cli.rs index c0b2a789..79a62f3a 100644 --- a/crates/moon/src/cli.rs +++ b/crates/moon/src/cli.rs @@ -29,6 +29,7 @@ pub mod generate_test_driver; pub mod info; pub mod mooncake_adapter; pub mod new; +mod pre_build; pub mod run; pub mod shell_completion; pub mod test; diff --git a/crates/moon/src/cli/build.rs b/crates/moon/src/cli/build.rs index 4e10eb23..b6203cfb 100644 --- a/crates/moon/src/cli/build.rs +++ b/crates/moon/src/cli/build.rs @@ -34,6 +34,7 @@ use std::path::Path; use std::sync::Arc; use std::thread; +use super::pre_build::run_pre_build; use super::{BuildFlags, UniversalFlags}; /// Build the current package @@ -146,6 +147,13 @@ fn run_build_internal( &moonc_opt, &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; moonc_opt.build_opt.warn_lists = module .get_all_packages() .iter() diff --git a/crates/moon/src/cli/bundle.rs b/crates/moon/src/cli/bundle.rs index 8e039514..4c5d642d 100644 --- a/crates/moon/src/cli/bundle.rs +++ b/crates/moon/src/cli/bundle.rs @@ -29,7 +29,7 @@ use moonutil::{ }; use std::{path::Path, sync::Arc, thread}; -use super::BuildFlags; +use super::{pre_build::run_pre_build, BuildFlags}; /// Bundle the module #[derive(Debug, clap::Parser, Clone)] @@ -156,6 +156,13 @@ fn run_bundle_internal( &moonc_opt, &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; moonc_opt.build_opt.warn_lists = module .get_all_packages() .iter() diff --git a/crates/moon/src/cli/check.rs b/crates/moon/src/cli/check.rs index d9e2416a..4ba823b3 100644 --- a/crates/moon/src/cli/check.rs +++ b/crates/moon/src/cli/check.rs @@ -37,6 +37,7 @@ use std::path::Path; use std::sync::Arc; use std::thread; +use super::pre_build::run_pre_build; use super::{get_compiler_flags, BuildFlags}; /// Check the current package, but don't build object files @@ -125,7 +126,7 @@ fn run_check_internal( target_dir: &Path, ) -> anyhow::Result { // Run moon install before build - let (resolved_modules, dir_sync_result) = auto_sync( + let (resolved_env, dir_sync_result) = auto_sync( source_dir, &cmd.auto_sync_flags, &RegistryConfig::load(), @@ -159,11 +160,18 @@ fn run_check_internal( let module = moonutil::scan::scan( false, - &resolved_modules, + &resolved_env, &dir_sync_result, &moonc_opt, &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; moonc_opt.build_opt.warn_lists = module .get_all_packages() .iter() diff --git a/crates/moon/src/cli/doc.rs b/crates/moon/src/cli/doc.rs index 1fa5ff82..e35133af 100644 --- a/crates/moon/src/cli/doc.rs +++ b/crates/moon/src/cli/doc.rs @@ -27,6 +27,7 @@ use moonutil::dirs::{mk_arch_mode_dir, PackageDirs}; use moonutil::mooncakes::sync::AutoSyncFlags; use moonutil::mooncakes::RegistryConfig; +use super::pre_build::run_pre_build; use super::UniversalFlags; /// Generate documentation @@ -108,6 +109,14 @@ pub fn run_doc(cli: UniversalFlags, cmd: DocSubcommand) -> anyhow::Result { &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; + let mut args = vec![ source_dir.display().to_string(), "-o".to_string(), diff --git a/crates/moon/src/cli/fmt.rs b/crates/moon/src/cli/fmt.rs index 178e52d8..1fb76fd1 100644 --- a/crates/moon/src/cli/fmt.rs +++ b/crates/moon/src/cli/fmt.rs @@ -24,7 +24,7 @@ use moonutil::{ mooncakes::{sync::AutoSyncFlags, RegistryConfig}, }; -use super::UniversalFlags; +use super::{pre_build::run_pre_build, UniversalFlags}; /// Format source code #[derive(Debug, clap::Parser)] @@ -81,6 +81,15 @@ pub fn run_fmt(cli: &UniversalFlags, cmd: FmtSubcommand) -> anyhow::Result &moonc_opt, &moonbuild_opt, )?; + + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; + if cli.dry_run { bail!("dry-run is not implemented for fmt"); } diff --git a/crates/moon/src/cli/generate_test_driver.rs b/crates/moon/src/cli/generate_test_driver.rs index cc5b2672..de600706 100644 --- a/crates/moon/src/cli/generate_test_driver.rs +++ b/crates/moon/src/cli/generate_test_driver.rs @@ -16,6 +16,7 @@ // // For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn. +use super::pre_build::run_pre_build; use super::BuildFlags; use anyhow::{bail, Context}; use colored::Colorize; @@ -168,6 +169,13 @@ pub fn generate_test_driver( &moonc_opt, &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; if cli.dry_run { bail!("dry-run is not implemented for generate-test-driver"); } diff --git a/crates/moon/src/cli/info.rs b/crates/moon/src/cli/info.rs index aa8d86bb..8ba0acbd 100644 --- a/crates/moon/src/cli/info.rs +++ b/crates/moon/src/cli/info.rs @@ -29,7 +29,7 @@ use moonutil::{ mooncakes::{sync::AutoSyncFlags, RegistryConfig}, }; -use super::UniversalFlags; +use super::{pre_build::run_pre_build, UniversalFlags}; /// Generate public interface (`.mbti`) files for all packages in the module #[derive(Debug, clap::Parser)] @@ -104,6 +104,13 @@ pub fn run_info(cli: UniversalFlags, cmd: InfoSubcommand) -> anyhow::Result &moonc_opt, &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; let check_result = moonbuild::entry::run_check(&moonc_opt, &moonbuild_opt, &module); match check_result { Ok(0) => {} diff --git a/crates/moon/src/cli/pre_build.rs b/crates/moon/src/cli/pre_build.rs new file mode 100644 index 00000000..312ebd10 --- /dev/null +++ b/crates/moon/src/cli/pre_build.rs @@ -0,0 +1,46 @@ +// moon: The build system and package manager for MoonBit. +// Copyright (C) 2024 International Digital Economy Academy +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn. + +use moonbuild::entry::{run_moon_generate, MoonGenerateState}; +use moonutil::{ + common::{MoonbuildOpt, MooncOpt}, + module::ModuleDB, + mooncakes::{result::ResolvedEnv, DirSyncResult}, +}; + +pub fn run_pre_build( + moonc_opt: &MooncOpt, + moonbuild_opt: &MoonbuildOpt, + module: ModuleDB, + resolved_env: &ResolvedEnv, + dir_sync_result: &DirSyncResult, +) -> anyhow::Result { + let gen_result = run_moon_generate(moonbuild_opt, &module)?; + let module = if let MoonGenerateState::WorkDone = gen_result { + moonutil::scan::scan( + false, + resolved_env, + dir_sync_result, + moonc_opt, + moonbuild_opt, + )? + } else { + module + }; + Ok(module) +} diff --git a/crates/moon/src/cli/run.rs b/crates/moon/src/cli/run.rs index b4f7cc7b..4736b497 100644 --- a/crates/moon/src/cli/run.rs +++ b/crates/moon/src/cli/run.rs @@ -36,6 +36,7 @@ use moonutil::mooncakes::sync::AutoSyncFlags; use moonutil::mooncakes::RegistryConfig; use n2::trace; +use super::pre_build::run_pre_build; use super::{BuildFlags, UniversalFlags}; /// Run a main package @@ -284,6 +285,13 @@ pub fn run_run_internal(cli: &UniversalFlags, cmd: RunSubcommand) -> anyhow::Res &moonc_opt, &moonbuild_opt, )?; + let module = run_pre_build( + &moonc_opt, + &moonbuild_opt, + module, + &resolved_env, + &dir_sync_result, + )?; moonc_opt.build_opt.warn_lists = module .get_all_packages() .iter() diff --git a/crates/moon/tests/test_cases/mod.rs b/crates/moon/tests/test_cases/mod.rs index ada543c7..058f9594 100644 --- a/crates/moon/tests/test_cases/mod.rs +++ b/crates/moon/tests/test_cases/mod.rs @@ -6812,6 +6812,13 @@ fn test_pre_build() { &get_stderr(&dir, ["check"]), expect![[r#" Executed 3 pre-build tasks, now up to date + Warning: [1002] + ╭─[$ROOT/src/lib/a.mbt:3:5] + │ + 3 │ let resource : String = + │ ────┬─── + │ ╰───── Warning: Unused toplevel variable 'resource'. Note if the body contains side effect, it will not happen. Use `fn init { .. }` to wrap the effect. + ───╯ Finished. moon: ran 2 tasks, now up to date "#]], ); diff --git a/crates/moonbuild/src/entry.rs b/crates/moonbuild/src/entry.rs index d1a938a6..a7c86a5c 100644 --- a/crates/moonbuild/src/entry.rs +++ b/crates/moonbuild/src/entry.rs @@ -284,14 +284,22 @@ fn vis_build_graph(state: &State, moonbuild_opt: &MoonbuildOpt) { eprintln!("generated build graph: {}", path.display()); } -fn run_moon_generate(moonbuild_opt: &MoonbuildOpt, module: &ModuleDB) -> anyhow::Result { +pub enum MoonGenerateState { + NoWork, + WorkDone, +} + +pub fn run_moon_generate( + moonbuild_opt: &MoonbuildOpt, + module: &ModuleDB, +) -> anyhow::Result { let generate_state = crate::generate::load_moon_generate(moonbuild_opt, module)?; if let Some(generate_state) = generate_state { let generate_result = n2_simple_run_interface(generate_state, moonbuild_opt)?; render_generate_result(generate_result, moonbuild_opt.quiet)?; - Ok(0) + Ok(MoonGenerateState::WorkDone) } else { - Ok(0) + Ok(MoonGenerateState::NoWork) } } @@ -319,8 +327,6 @@ pub fn run_check( moonbuild_opt: &MoonbuildOpt, module: &ModuleDB, ) -> anyhow::Result { - run_moon_generate(moonbuild_opt, module)?; - let state = trace::scope("moonbit::check::read", || { crate::check::normal::load_moon_proj(module, moonc_opt, moonbuild_opt) })?; @@ -341,8 +347,6 @@ pub fn run_build( moonbuild_opt: &MoonbuildOpt, module: &ModuleDB, ) -> anyhow::Result { - run_moon_generate(moonbuild_opt, module)?; - let state = trace::scope("moonbit::build::read", || { crate::build::load_moon_proj(module, moonc_opt, moonbuild_opt) })?; @@ -555,8 +559,6 @@ pub fn run_test( auto_update: bool, module: ModuleDB, ) -> anyhow::Result>> { - run_moon_generate(&moonbuild_opt, &module)?; - let moonc_opt = Arc::new(moonc_opt); let moonbuild_opt = Arc::new(moonbuild_opt); let module = Arc::new(module); @@ -1056,8 +1058,6 @@ pub fn run_bundle( moonbuild_opt: &MoonbuildOpt, moonc_opt: &MooncOpt, ) -> anyhow::Result { - run_moon_generate(moonbuild_opt, module)?; - let state = crate::bundle::load_moon_proj(module, moonc_opt, moonbuild_opt)?; let result = n2_run_interface(state, moonbuild_opt)?; match result {