Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 76 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,20 @@ jobs:
mdbook build docs/manual-zh

nightly-test:
name: nightly-test (${{ matrix.os }} / msvc:${{ matrix.msvc }})
needs: [typo-check, license-header-check]
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
include:
- os: ubuntu-latest
msvc: disabled
- os: macos-latest
msvc: disabled
- os: windows-latest
msvc: enabled
- os: windows-latest
msvc: disabled
runs-on: ${{ matrix.os }}
steps:
- name: Configure git
Expand Down Expand Up @@ -163,7 +169,7 @@ jobs:
"$env:GITHUB_WORKSPACE\target\debug" | Out-File -FilePath $env:GITHUB_PATH -Append

- name: Setup MSVC
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-latest' && matrix.msvc == 'enabled' }}
uses: ilammy/msvc-dev-cmd@v1

- name: Build
Expand Down Expand Up @@ -249,14 +255,20 @@ jobs:
cargo run --bin moon -- -Z rupes_recta -C ~/.moon/lib/core build --target wasm-gc

stable-test:
name: stable-test (${{ matrix.os }} / msvc:${{ matrix.msvc }})
needs: [typo-check, license-header-check]
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
include:
- os: ubuntu-latest
msvc: disabled
- os: macos-latest
msvc: disabled
- os: windows-latest
msvc: enabled
- os: windows-latest
msvc: disabled
runs-on: ${{ matrix.os }}
steps:
- name: Configure git
Expand Down Expand Up @@ -286,7 +298,7 @@ jobs:
"C:\Users\runneradmin\.moon\bin" | Out-File -FilePath $env:GITHUB_PATH -Append

- name: Setup MSVC
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-latest' && matrix.msvc == 'enabled' }}
uses: ilammy/msvc-dev-cmd@v1

- name: Build
Expand Down Expand Up @@ -350,6 +362,60 @@ jobs:
cargo run --bin moon -- -C "$env:USERPROFILE\.moon\lib\core" test --release --target native
cargo run --bin moon -- -C "$env:USERPROFILE\.moon\lib\core" test --doc

windows-tcc-first-test:
name: windows tcc first test (${{ matrix.msvc }})
needs: [typo-check, license-header-check]
strategy:
fail-fast: false
matrix:
msvc:
- enabled
- disabled
runs-on: windows-latest
steps:
- name: Configure git
run: git config --global core.autocrlf false

- uses: actions/checkout@v4
with:
submodules: true

- uses: dtolnay/rust-toolchain@1.90.0
with:
components: rustfmt, clippy

- name: Cargo cache
uses: Swatinem/rust-cache@v2

- name: install MoonBit(Windows)
run: |
$env:MOONBIT_INSTALL_VERSION="nightly"
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser; irm https://cli.moonbitlang.com/install/powershell.ps1 | iex
"$env:USERPROFILE\.moon\bin" | Out-File -FilePath $env:GITHUB_PATH -Append
"$env:GITHUB_WORKSPACE\target\debug" | Out-File -FilePath $env:GITHUB_PATH -Append

- name: Setup MSVC
if: ${{ matrix.msvc == 'enabled' }}
uses: ilammy/msvc-dev-cmd@v1

- name: Build moon binary
run: cargo build -p moon --bin moon

- name: Set built binary to PATH (Windows)
run: Add-Content $env:GITHUB_PATH "$env:GITHUB_WORKSPACE\target\debug"

- name: Bundle core (Windows)
run: cargo run --bin moon -- -C "$env:USERPROFILE\.moon\lib\core" bundle --all

- name: Verify windows tcc-run default gate
run: cargo test -p moon --test mod test_cases::native_backend::tcc_run::test_native_backend_tcc_run_windows_disabled_by_default -- --exact

- name: Verify windows tcc-run experimental path
run: cargo test -p moon --test mod test_cases::native_backend::tcc_run::test_native_backend_tcc_run_windows_experimental -- --exact

- name: Verify windows tcc-run with MOON_CC=tcc (msvc runtime)
run: cargo test -p moon --test mod test_cases::native_backend::tcc_run::test_native_backend_tcc_run_windows_with_env_tcc_cc_uses_msvc_runtime -- --exact

# coverage:
# needs: bleeding-test
# runs-on: macos-latest
Expand Down
16 changes: 14 additions & 2 deletions crates/moon/src/rr_build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,20 @@ fn check_tcc_availability(
return false;
}

// Check platform availability
if !(cfg!(target_os = "linux") || cfg!(target_os = "macos")) {
// Check platform availability.
//
// On Windows this is currently experimental and opt-in only, so we can
// collect first-round test signals before enabling it by default.
if cfg!(target_os = "windows") {
let enabled = std::env::var("MOON_ENABLE_WINDOWS_TCC_RUN")
.is_ok_and(|x| matches!(x.as_str(), "1" | "true" | "TRUE" | "yes" | "on"));
if !enabled {
info!(
"Disabling `tcc -run`: Windows support is experimental (set MOON_ENABLE_WINDOWS_TCC_RUN=1 to enable)"
);
return false;
}
} else if !(cfg!(target_os = "linux") || cfg!(target_os = "macos")) {
info!("`tcc -run` is only supported on Linux and macOS");
return false;
}
Expand Down
58 changes: 58 additions & 0 deletions crates/moon/tests/test_cases/native_backend/tcc_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::TestDir;
use expect_test::expect_file;

use super::assert_native_backend_graph_no_env;
#[cfg(windows)]
use crate::get_stdout_with_envs;

#[test]
#[cfg(unix)]
Expand All @@ -21,3 +23,59 @@ fn test_native_backend_tcc_run() {
expect_file!["tcc_run/test_native_linux_graph.jsonl.snap"],
);
}

#[test]
#[cfg(windows)]
fn test_native_backend_tcc_run_windows_disabled_by_default() {
let dir = TestDir::new("native_backend/tcc_run");
let out = get_stdout_with_envs(
&dir,
["test", "--target", "native", "--dry-run", "--sort-input"],
[] as [(&str, &str); 0],
);
assert!(
!out.contains("write-tcc-rsp-file"),
"unexpected tcc-run graph on Windows without opt-in:\n{out}"
);
}

#[test]
#[cfg(windows)]
fn test_native_backend_tcc_run_windows_experimental() {
let dir = TestDir::new("native_backend/tcc_run");
let out = get_stdout_with_envs(
&dir,
["test", "--target", "native", "--dry-run", "--sort-input"],
[("MOON_ENABLE_WINDOWS_TCC_RUN", "1")],
);
assert!(
out.contains("write-tcc-rsp-file"),
"expected tcc-run graph on Windows experimental path:\n{out}"
);
}

#[test]
#[cfg(windows)]
fn test_native_backend_tcc_run_windows_with_env_tcc_cc_uses_msvc_runtime() {
let dir = TestDir::new("native_backend/tcc_run");
let out = get_stdout_with_envs(
&dir,
["test", "--target", "native", "--dry-run", "--sort-input"],
[
("MOON_ENABLE_WINDOWS_TCC_RUN", "1"),
("MOON_CC", "x86_64-unknown-fake_os-fake_libc-tcc"),
],
);
assert!(
out.contains("write-tcc-rsp-file"),
"expected tcc-run graph on Windows with MOON_CC=tcc:\n{out}"
);
assert!(
!out.contains("-lm"),
"unexpected math library linkage for Windows tcc msvc-runtime path:\n{out}"
);
assert!(
out.contains("libruntime.lib"),
"expected msvc-style runtime import lib for Windows tcc path:\n{out}"
);
}
24 changes: 16 additions & 8 deletions crates/moon/tests/test_cases/prebuild_config_script/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,22 @@ fn test_prebuild_config_common(dir: TestDir) {
assert!(line.contains("-l______this_is_added_by_config_script_______"));
assert!(line.contains("-lmylib"));
assert!(line.contains("-L/my-search-path"));
} else if line.contains("cl.exe") // cl.exe might be quoted
&& line.contains("/Fe./_build/native/debug/build/main/main.exe")
&& cfg!(windows)
{
found_link_flags.set(()).expect("final linking found twice");
assert!(line.contains("-l______this_is_added_by_config_script_______"));
assert!(line.contains("mylib"));
assert!(line.contains("/LIBPATH:/my-search-path"));
} else if cfg!(windows) {
let is_msvc_link = line.contains("cl.exe") // cl.exe might be quoted
&& line.contains("/Fe./_build/native/debug/build/main/main.exe");
let is_gnu_link = line.contains("-o ./_build/native/debug/build/main/main.exe")
&& (line.contains("cc ") || line.contains("cc.exe"));
if is_msvc_link || is_gnu_link {
found_link_flags.set(()).expect("final linking found twice");
assert!(line.contains("-l______this_is_added_by_config_script_______"));
if is_msvc_link {
assert!(line.contains("mylib"));
assert!(line.contains("/LIBPATH:/my-search-path"));
} else {
assert!(line.contains("-lmylib"));
assert!(line.contains("-L/my-search-path"));
}
}
}
}
found_c_flags_replacement
Expand Down
24 changes: 16 additions & 8 deletions crates/moon/tests/test_cases/prebuild_link_config_self/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@ fn test_prebuild_link_config_self() {
assert!(line.contains("-l__prebuild_self_link_flag__"));
assert!(line.contains("-lprebuildselflib"));
assert!(line.contains("-L/prebuild-self-path"));
} else if line.contains("cl.exe")
&& line.contains("/Fe./_build/native/debug/build/main/main.exe")
&& cfg!(windows)
{
found_final_link.set(()).expect("final linking found twice");
assert!(line.contains("-l__prebuild_self_link_flag__"));
assert!(line.contains("prebuildselflib"));
assert!(line.contains("/LIBPATH:/prebuild-self-path"));
} else if cfg!(windows) {
let is_msvc_link = line.contains("cl.exe")
&& line.contains("/Fe./_build/native/debug/build/main/main.exe");
let is_gnu_link = line.contains("-o ./_build/native/debug/build/main/main.exe")
&& (line.contains("cc ") || line.contains("cc.exe"));
if is_msvc_link || is_gnu_link {
found_final_link.set(()).expect("final linking found twice");
assert!(line.contains("-l__prebuild_self_link_flag__"));
if is_msvc_link {
assert!(line.contains("prebuildselflib"));
assert!(line.contains("/LIBPATH:/prebuild-self-path"));
} else {
assert!(line.contains("-lprebuildselflib"));
assert!(line.contains("-L/prebuild-self-path"));
}
}
}
}

Expand Down
67 changes: 63 additions & 4 deletions crates/moonutil/src/compiler_flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,12 +537,24 @@ fn add_linker_common_libraries<P: AsRef<Path>>(
config: &LinkerConfig<P>,
) {
if cc.is_gcc_like() {
if cc.is_full_featured_gcc_like() {
if should_link_math_library(cc) {
buf.push("-lm".to_string());
}
if let Some(dyn_lib_path) = config.link_shared_runtime.as_ref() {
buf.push("-lruntime".to_string());
buf.push(format!("-Wl,-rpath,{}", dyn_lib_path.as_ref().display()));
if should_use_msvc_style_tcc_runtime_linking(cc) {
buf.push(
dyn_lib_path
.as_ref()
.join("libruntime.lib")
.display()
.to_string(),
);
} else {
buf.push("-lruntime".to_string());
if should_add_runtime_rpath() {
buf.push(format!("-Wl,-rpath,{}", dyn_lib_path.as_ref().display()));
}
}
}
}
}
Expand Down Expand Up @@ -824,11 +836,29 @@ fn add_cc_moonbitrun_with_warnings(cc: &CC, buf: &mut Vec<String>, config: &CCCo
}

fn add_cc_common_libraries(cc: &CC, buf: &mut Vec<String>, config: &CCConfig) {
if cc.is_full_featured_gcc_like() && config.output_ty != OutputType::Object {
if should_link_math_library(cc) && config.output_ty != OutputType::Object {
buf.push("-lm".to_string());
}
}

fn should_link_math_library(cc: &CC) -> bool {
if cfg!(target_os = "windows") && cc.is_tcc() {
// Windows tcc path is modeled as MSVC-style linking only.
false
} else {
cc.is_full_featured_gcc_like()
}
}

fn should_use_msvc_style_tcc_runtime_linking(cc: &CC) -> bool {
cfg!(target_os = "windows") && cc.is_tcc()
}

fn should_add_runtime_rpath() -> bool {
// PE/COFF loaders do not use ELF rpath semantics.
!cfg!(target_os = "windows")
}

fn add_cc_msvc_linker_flags(cc: &CC, buf: &mut Vec<String>, config: &CCConfig, lpath: &str) {
if cc.is_msvc() && config.output_ty != OutputType::Object {
buf.push("/link".to_string());
Expand Down Expand Up @@ -904,3 +934,32 @@ where

buf
}

#[cfg(all(test, windows))]
mod tests {
use super::*;

#[test]
fn windows_tcc_does_not_link_math_library() {
let cc = CC {
cc_kind: CCKind::Tcc,
cc_path: "tcc".to_string(),
ar_kind: ARKind::TccAr,
ar_path: "tcc".to_string(),
is_env_override: false,
};
assert!(!should_link_math_library(&cc));
}

#[test]
fn windows_tcc_runtime_link_style_is_msvc() {
let cc = CC {
cc_kind: CCKind::Tcc,
cc_path: "tcc".to_string(),
ar_kind: ARKind::TccAr,
ar_path: "tcc".to_string(),
is_env_override: false,
};
assert!(should_use_msvc_style_tcc_runtime_linking(&cc));
}
}
Loading