diff --git a/crates/moon/tests/test_cases/mod.rs b/crates/moon/tests/test_cases/mod.rs index aecb8eb6..fd92ec1d 100644 --- a/crates/moon/tests/test_cases/mod.rs +++ b/crates/moon/tests/test_cases/mod.rs @@ -8065,11 +8065,29 @@ fn test_moon_install_bin() { let top_dir = TestDir::new("moon_install_bin.in"); let dir = top_dir.join("user.in"); - let _1 = top_dir.join("author2.in").join("author2-native.exe"); - let _2 = top_dir.join("author2.in").join("author2-js.js"); - let _3 = top_dir.join("author2.in").join("author2-wasm.wasm"); - let _4 = top_dir.join("author1.in").join("this-is-wasm.wasm"); - let _5 = top_dir.join("author1.in").join("main-js.js"); + let mut _1 = PathBuf::from(""); + let mut _2 = PathBuf::from(""); + let mut _3 = PathBuf::from(""); + let mut _4 = PathBuf::from(""); + let mut _5 = PathBuf::from(""); + + #[cfg(unix)] + { + _1 = top_dir.join("author2.in").join("author2-native"); + _2 = top_dir.join("author2.in").join("author2-js"); + _3 = top_dir.join("author2.in").join("author2-wasm"); + _4 = top_dir.join("author1.in").join("this-is-wasm"); + _5 = top_dir.join("author1.in").join("main-js"); + } + + #[cfg(target_os = "windows")] + { + _1 = top_dir.join("author2.in").join("author2-native.ps1"); + _2 = top_dir.join("author2.in").join("author2-js.ps1"); + _3 = top_dir.join("author2.in").join("author2-wasm.ps1"); + _4 = top_dir.join("author1.in").join("this-is-wasm.ps1"); + _5 = top_dir.join("author1.in").join("main-js.ps1"); + } // moon check should auto install bin deps get_stdout(&dir, ["check"]); @@ -8103,13 +8121,13 @@ fn test_moon_install_bin() { assert!(_5.exists()); check( - get_stderr(&dir, ["build"]), + get_stderr(&dir, ["build", "--sort-input"]), expect![[r#" - main-js - lib Hello, world! - () - Executed 1 pre-build task, now up to date - Finished. moon: ran 17 tasks, now up to date - "#]], + main-js + lib Hello, world! + () + Executed 1 pre-build task, now up to date + Finished. moon: ran 17 tasks, now up to date + "#]], ); } diff --git a/crates/moonbuild/src/gen/gen_build.rs b/crates/moonbuild/src/gen/gen_build.rs index d8d77578..d6322842 100644 --- a/crates/moonbuild/src/gen/gen_build.rs +++ b/crates/moonbuild/src/gen/gen_build.rs @@ -16,7 +16,7 @@ // // For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn. -use anyhow::{bail, Ok}; +use anyhow::{bail, Context, Ok}; use moonutil::module::ModuleDB; use moonutil::package::{JsFormat, Package}; @@ -26,7 +26,9 @@ use crate::gen::MiAlias; use std::path::{Path, PathBuf}; use std::rc::Rc; -use moonutil::common::{BuildOpt, MoonbuildOpt, MooncOpt, MOONBITLANG_CORE, MOON_PKG_JSON}; +use moonutil::common::{ + BuildOpt, MoonbuildOpt, MooncOpt, TargetBackend, MOONBITLANG_CORE, MOON_PKG_JSON, +}; use n2::graph::{self as n2graph, Build, BuildIns, BuildOuts, FileLoc}; use n2::load::State; use n2::smallmap::SmallMap; @@ -476,28 +478,64 @@ pub fn gen_n2_build_state( // if we need to install the artifact to a specific path if let Some(install_path) = item.install_path.as_ref() { - let artifact_output_path = install_path - .join(if let Some(bin_name) = &item.bin_name { - bin_name.clone() - } else { - PathBuf::from(&item.out) - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string() - }) + let bin_script_content = if cfg!(target_os = "windows") { + include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../moonbuild/template/moon_bin_script_template/windows.ps1" + )) + } else { + include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../moonbuild/template/moon_bin_script_template/unix.sh" + )) + }; + + let bin_script_name = item.bin_name.clone().unwrap_or( + PathBuf::from(&item.out) + .file_stem() + .unwrap() + .to_str() + .unwrap() + .to_string(), + ); + #[cfg(target_os = "windows")] + let bin_script_name = PathBuf::from(&bin_script_name) + .with_extension("ps1") .display() .to_string(); - let link_item_to_install = BuildLinkDepItem { - out: artifact_output_path, - ..item.clone() - }; - - let (build, fid) = gen_link_command(&mut graph, &link_item_to_install, moonc_opt); - default.push(fid); - graph.add_build(build)?; + let bin_script_path = install_path.join(bin_script_name); + + if !bin_script_path.exists() { + let artifact_output_path = PathBuf::from(&item.out) + .with_extension(moonc_opt.link_opt.output_format.to_str()) + .display() + .to_string(); + + let runtime = match moonc_opt.link_opt.target_backend { + TargetBackend::Native => "".to_string(), + TargetBackend::Wasm | TargetBackend::WasmGC => "moonrun".to_string(), + TargetBackend::Js => "node".to_string(), + }; + + let bin_script_content = bin_script_content + .replace("$runtime", &runtime) + .replace("$artifact_output_path", &artifact_output_path); + + std::fs::write(&bin_script_path, bin_script_content).with_context(|| { + format!("Failed to write bin script to {:?}", bin_script_path) + })?; + #[cfg(unix)] + { + std::fs::set_permissions( + &bin_script_path, + std::os::unix::fs::PermissionsExt::from_mode(0o755), + ) + .with_context(|| { + format!("Failed to set permissions for {:?}", bin_script_path) + })?; + } + } } } diff --git a/crates/moonbuild/src/pre_build.rs b/crates/moonbuild/src/pre_build.rs index 604ddbdf..d5f3b4b8 100644 --- a/crates/moonbuild/src/pre_build.rs +++ b/crates/moonbuild/src/pre_build.rs @@ -119,6 +119,21 @@ pub fn load_moon_pre_build( .replace(MOD_DIR, &moonbuild_opt.source_dir.display().to_string()) .replace(PKG_DIR, &cwd.display().to_string()); + #[cfg(target_os = "windows")] + let command = { + let maybe_ps1 = command.trim_start().split(" ").next().unwrap(); + let ps1_path = moonbuild_opt + .source_dir + .join(maybe_ps1) + .with_extension("ps1"); + let ps1_path = dunce::canonicalize(ps1_path).unwrap(); + if ps1_path.exists() { + format!("powershell {}", ps1_path.display()) + } else { + command + } + }; + let command = command .replace("$input", &inputs.join(" ")) .replace("$output", &outputs.join(" ")); diff --git a/crates/moonbuild/template/moon_bin_script_template/unix.sh b/crates/moonbuild/template/moon_bin_script_template/unix.sh new file mode 100755 index 00000000..2143d494 --- /dev/null +++ b/crates/moonbuild/template/moon_bin_script_template/unix.sh @@ -0,0 +1,2 @@ +#!/bin/sh +$runtime $artifact_output_path "$@" diff --git a/crates/moonbuild/template/moon_bin_script_template/windows.ps1 b/crates/moonbuild/template/moon_bin_script_template/windows.ps1 new file mode 100755 index 00000000..deed7c39 --- /dev/null +++ b/crates/moonbuild/template/moon_bin_script_template/windows.ps1 @@ -0,0 +1 @@ +$runtime $artifact_output_path $args