Skip to content

Commit d532ed8

Browse files
authored
fix: Fix native build on Windows without Visual Studio (#99)
* fix: Fix Windoes setup * fix: Fix clean of MOONBIT_LIB_DIR and include dir * feat: Add --patch-runtime flag for windows patch * ci skip
1 parent e9b0a30 commit d532ed8

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

nu/moonbit.nu

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,39 @@ def fetch-core [ version: string ] {
6060
}
6161
}
6262

63+
# Patch runtime.c to guard `#include <windows.h>` behind MOONBIT_NATIVE_NO_SYS_HEADER.
64+
# The bundled TCC doesn't ship with winapi headers and the moon build tool compiles with
65+
# -DMOONBIT_NATIVE_NO_SYS_HEADER, but the runtime still includes <windows.h> unconditionally
66+
# for GetConsoleOutputCP/SetConsoleOutputCP used in moonbit_println. Without Visual Studio
67+
# installed TCC can't discover system headers, causing the native target build to fail.
68+
def patch-runtime-windows-header [libDir: string] {
69+
let runtime = [$libDir runtime.c] | path join
70+
if not ($runtime | path exists) { return }
71+
let content = open $runtime
72+
let old = "#ifdef _WIN32\n#include <windows.h>\n#endif"
73+
if ($content | str contains $old) {
74+
let new = [
75+
'#ifdef _WIN32'
76+
'#ifndef MOONBIT_NATIVE_NO_SYS_HEADER'
77+
'#include <windows.h>'
78+
'#else'
79+
'#define CP_UTF8 65001'
80+
'unsigned int GetConsoleOutputCP(void);'
81+
'int SetConsoleOutputCP(unsigned int);'
82+
'#endif'
83+
'#endif'
84+
] | str join "\n"
85+
$content | str replace $old $new | save --force $runtime
86+
print $'(ansi g)Patched runtime.c: guarded <windows.h> behind MOONBIT_NATIVE_NO_SYS_HEADER(ansi reset)'
87+
}
88+
}
89+
6390
# Download moonbit binary files to local
6491
export def 'setup moonbit' [
6592
version?, # The version of moonbit toolchain to setup, and `latest` by default
6693
--setup-core(-c), # Setup moonbit core
6794
--core-version(-V): string = 'latest', # The version of moonbit core to setup, `latest` by default
95+
--patch-runtime(-p), # Patch runtime.c to fix native build on Windows without Visual Studio
6896
] {
6997
let version = $version | default $env.MOONBIT_INSTALL_VERSION? | default 'latest'
7098
if ($version not-in $VALID_VERSION_TAG) and not (is-semver $version) {
@@ -85,10 +113,24 @@ export def 'setup moonbit' [
85113
print $'(char nl)Setup moonbit toolchain of version: (ansi g)($version)(ansi reset)'; hr-line
86114
print $'Current moon home: (ansi g)($MOONBIT_HOME)(ansi reset)'
87115

116+
# Clean up old lib and include directories before extraction to
117+
# avoid stale files, matching the behavior of the official install scripts
118+
let includeDir = [$MOONBIT_HOME include] | path join
119+
if ($includeDir | path exists) { rm -rf $includeDir }
120+
if ($MOONBIT_LIB_DIR | path exists) { rm -rf $MOONBIT_LIB_DIR }
121+
88122
if (windows?) {
89123
fetch-release $version $'moonbit-($archive).zip'
90124
unzip -qo $'moonbit-($archive).zip' -d $MOONBIT_HOME
91125
rm moonbit*.zip
126+
if $patch_runtime {
127+
# Workaround: runtime.c includes <windows.h> without guarding it
128+
# behind MOONBIT_NATIVE_NO_SYS_HEADER. When TCC has no winapi headers
129+
# and Visual Studio is not installed, this causes the native build to
130+
# fail. Patch runtime.c to guard the include and provide manual
131+
# declarations for the required Windows API functions.
132+
patch-runtime-windows-header $MOONBIT_LIB_DIR
133+
}
92134
} else {
93135
fetch-release $version $'moonbit-($archive).tar.gz'
94136
tar xf $'moonbit-($archive).tar.gz' --directory $MOONBIT_HOME

0 commit comments

Comments
 (0)