diff --git a/.buildkite/ci.mjs b/.buildkite/ci.mjs index a9fe144bdb..88e879a806 100755 --- a/.buildkite/ci.mjs +++ b/.buildkite/ci.mjs @@ -114,6 +114,8 @@ const buildPlatforms = [ { os: "linux", arch: "x64", abi: "musl", baseline: true, distro: "alpine", release: "3.22" }, { os: "windows", arch: "x64", release: "2019" }, { os: "windows", arch: "x64", baseline: true, release: "2019" }, + // TODO: Enable when Windows ARM64 CI runners are ready + // { os: "windows", arch: "aarch64", release: "2019" }, ]; /** @@ -136,6 +138,8 @@ const testPlatforms = [ { os: "linux", arch: "x64", abi: "musl", baseline: true, distro: "alpine", release: "3.22", tier: "latest" }, { os: "windows", arch: "x64", release: "2019", tier: "oldest" }, { os: "windows", arch: "x64", release: "2019", baseline: true, tier: "oldest" }, + // TODO: Enable when Windows ARM64 CI runners are ready + // { os: "windows", arch: "aarch64", release: "2019", tier: "oldest" }, ]; /** diff --git a/.buildkite/scripts/sign-windows.ps1 b/.buildkite/scripts/sign-windows.ps1 index d208c4460e..c6a858332b 100644 --- a/.buildkite/scripts/sign-windows.ps1 +++ b/.buildkite/scripts/sign-windows.ps1 @@ -36,16 +36,20 @@ function Log-Debug { } } +# Detect system architecture +$script:IsARM64 = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64 +$script:VsArch = if ($script:IsARM64) { "arm64" } else { "amd64" } + # Load Visual Studio environment if not already loaded function Ensure-VSEnvironment { if ($null -eq $env:VSINSTALLDIR) { - Log-Info "Loading Visual Studio environment..." - + Log-Info "Loading Visual Studio environment for $script:VsArch..." + $vswhere = "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" if (!(Test-Path $vswhere)) { throw "Command not found: vswhere (did you install Visual Studio?)" } - + $vsDir = & $vswhere -prerelease -latest -property installationPath if ($null -eq $vsDir) { $vsDir = Get-ChildItem -Path "C:\Program Files\Microsoft Visual Studio\2022" -Directory -ErrorAction SilentlyContinue @@ -54,20 +58,20 @@ function Ensure-VSEnvironment { } $vsDir = $vsDir.FullName } - + Push-Location $vsDir try { $vsShell = Join-Path -Path $vsDir -ChildPath "Common7\Tools\Launch-VsDevShell.ps1" - . $vsShell -Arch amd64 -HostArch amd64 + . $vsShell -Arch $script:VsArch -HostArch $script:VsArch } finally { Pop-Location } - + Log-Success "Visual Studio environment loaded" } - + if ($env:VSCMD_ARG_TGT_ARCH -eq "x86") { - throw "Visual Studio environment is targeting 32 bit, but only 64 bit is supported." + throw "Visual Studio environment is targeting 32 bit x86, but only 64-bit architectures (x64/arm64) are supported." } } @@ -186,8 +190,10 @@ function Install-KeyLocker { } # Download MSI installer - $msiUrl = "https://bun-ci-assets.bun.sh/Keylockertools-windows-x64.msi" - $msiPath = Join-Path $env:TEMP "Keylockertools-windows-x64.msi" + # Note: KeyLocker tools currently only available for x64, but works on ARM64 via emulation + $msiArch = "x64" + $msiUrl = "https://bun-ci-assets.bun.sh/Keylockertools-windows-${msiArch}.msi" + $msiPath = Join-Path $env:TEMP "Keylockertools-windows-${msiArch}.msi" Log-Info "Downloading MSI from: $msiUrl" Log-Info "Downloading to: $msiPath" diff --git a/.buildkite/scripts/upload-release.sh b/.buildkite/scripts/upload-release.sh index 746eb0a81e..4ee04ba45d 100755 --- a/.buildkite/scripts/upload-release.sh +++ b/.buildkite/scripts/upload-release.sh @@ -219,6 +219,9 @@ function create_release() { bun-windows-x64-profile.zip bun-windows-x64-baseline.zip bun-windows-x64-baseline-profile.zip + # TODO: Enable when Windows ARM64 CI runners are ready + # bun-windows-aarch64.zip + # bun-windows-aarch64-profile.zip ) function upload_artifact() { diff --git a/build.zig b/build.zig index cea24a8dfe..bf009ede5a 100644 --- a/build.zig +++ b/build.zig @@ -34,6 +34,7 @@ const BunBuildOptions = struct { enable_asan: bool, enable_fuzzilli: bool, enable_valgrind: bool, + enable_tinycc: bool, use_mimalloc: bool, tracy_callstack_depth: u16, reported_nodejs_version: Version, @@ -84,6 +85,7 @@ const BunBuildOptions = struct { opts.addOption(bool, "enable_asan", this.enable_asan); opts.addOption(bool, "enable_fuzzilli", this.enable_fuzzilli); opts.addOption(bool, "enable_valgrind", this.enable_valgrind); + opts.addOption(bool, "enable_tinycc", this.enable_tinycc); opts.addOption(bool, "use_mimalloc", this.use_mimalloc); opts.addOption([]const u8, "reported_nodejs_version", b.fmt("{f}", .{this.reported_nodejs_version})); opts.addOption(bool, "zig_self_hosted_backend", this.no_llvm); @@ -259,6 +261,7 @@ pub fn build(b: *Build) !void { .enable_asan = b.option(bool, "enable_asan", "Enable asan") orelse false, .enable_fuzzilli = b.option(bool, "enable_fuzzilli", "Enable fuzzilli instrumentation") orelse false, .enable_valgrind = b.option(bool, "enable_valgrind", "Enable valgrind") orelse false, + .enable_tinycc = b.option(bool, "enable_tinycc", "Enable TinyCC for FFI JIT compilation") orelse true, .use_mimalloc = b.option(bool, "use_mimalloc", "Use mimalloc as default allocator") orelse false, .llvm_codegen_threads = b.option(u32, "llvm_codegen_threads", "Number of threads to use for LLVM codegen") orelse 1, }; @@ -342,6 +345,7 @@ pub fn build(b: *Build) !void { const step = b.step("check-debug", "Check for semantic analysis errors on some platforms"); addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .windows, .arch = .aarch64 }, .{ .os = .mac, .arch = .aarch64 }, .{ .os = .linux, .arch = .x86_64 }, }, &.{.Debug}); @@ -352,6 +356,7 @@ pub fn build(b: *Build) !void { const step = b.step("check-all", "Check for semantic analysis errors on all supported platforms"); addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .windows, .arch = .aarch64 }, .{ .os = .mac, .arch = .x86_64 }, .{ .os = .mac, .arch = .aarch64 }, .{ .os = .linux, .arch = .x86_64 }, @@ -366,6 +371,7 @@ pub fn build(b: *Build) !void { const step = b.step("check-all-debug", "Check for semantic analysis errors on all supported platforms in debug mode"); addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .windows, .arch = .aarch64 }, .{ .os = .mac, .arch = .x86_64 }, .{ .os = .mac, .arch = .aarch64 }, .{ .os = .linux, .arch = .x86_64 }, @@ -380,12 +386,14 @@ pub fn build(b: *Build) !void { const step = b.step("check-windows", "Check for semantic analysis errors on Windows"); addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .windows, .arch = .aarch64 }, }, &.{ .Debug, .ReleaseFast }); } { const step = b.step("check-windows-debug", "Check for semantic analysis errors on Windows"); addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .windows, .arch = .aarch64 }, }, &.{.Debug}); } { @@ -422,6 +430,7 @@ pub fn build(b: *Build) !void { const step = b.step("translate-c", "Copy generated translated-c-headers.zig to zig-out"); for ([_]TargetDescription{ .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .windows, .arch = .aarch64 }, .{ .os = .mac, .arch = .x86_64 }, .{ .os = .mac, .arch = .aarch64 }, .{ .os = .linux, .arch = .x86_64 }, @@ -493,6 +502,7 @@ fn addMultiCheck( .no_llvm = root_build_options.no_llvm, .enable_asan = root_build_options.enable_asan, .enable_valgrind = root_build_options.enable_valgrind, + .enable_tinycc = root_build_options.enable_tinycc, .enable_fuzzilli = root_build_options.enable_fuzzilli, .use_mimalloc = root_build_options.use_mimalloc, .override_no_export_cpp_apis = root_build_options.override_no_export_cpp_apis, diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index bff19e1974..bf1e7f8eef 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -21,6 +21,10 @@ endforeach() if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM|arm64|ARM64|aarch64|AARCH64") if(APPLE) register_compiler_flags(-mcpu=apple-m1) + elseif(WIN32) + # Windows ARM64: use /clang: prefix for clang-cl, skip for MSVC cl.exe subprojects + # These flags are only understood by clang-cl, not MSVC cl.exe + register_compiler_flags(/clang:-march=armv8-a+crc /clang:-mtune=ampere1) else() register_compiler_flags(-march=armv8-a+crc -mtune=ampere1) endif() @@ -242,10 +246,17 @@ if(UNIX) ) endif() -register_compiler_flags( - DESCRIPTION "Set C/C++ error limit" - -ferror-limit=${ERROR_LIMIT} -) +if(WIN32) + register_compiler_flags( + DESCRIPTION "Set C/C++ error limit" + /clang:-ferror-limit=${ERROR_LIMIT} + ) +else() + register_compiler_flags( + DESCRIPTION "Set C/C++ error limit" + -ferror-limit=${ERROR_LIMIT} + ) +endif() # --- LTO --- if(ENABLE_LTO) diff --git a/cmake/Globals.cmake b/cmake/Globals.cmake index 176d15ea08..ab78654512 100644 --- a/cmake/Globals.cmake +++ b/cmake/Globals.cmake @@ -106,9 +106,9 @@ else() endif() if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64") - set(HOST_OS "aarch64") + set(HOST_ARCH "aarch64") elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64|X86_64|x64|X64|amd64|AMD64") - set(HOST_OS "x64") + set(HOST_ARCH "x64") else() unsupported(CMAKE_HOST_SYSTEM_PROCESSOR) endif() @@ -433,6 +433,33 @@ function(register_command) list(APPEND CMD_EFFECTIVE_DEPENDS ${CMD_EXECUTABLE}) endif() + # SKIP_CODEGEN: Skip commands that use BUN_EXECUTABLE if all outputs exist + # This is used for Windows ARM64 builds where x64 bun crashes under emulation + if(SKIP_CODEGEN AND CMD_EXECUTABLE STREQUAL "${BUN_EXECUTABLE}") + set(ALL_OUTPUTS_EXIST TRUE) + foreach(output ${CMD_OUTPUTS}) + if(NOT EXISTS ${output}) + set(ALL_OUTPUTS_EXIST FALSE) + break() + endif() + endforeach() + if(ALL_OUTPUTS_EXIST AND CMD_OUTPUTS) + message(STATUS "SKIP_CODEGEN: Skipping ${CMD_TARGET} (outputs exist)") + if(CMD_TARGET) + add_custom_target(${CMD_TARGET}) + endif() + return() + elseif(NOT CMD_OUTPUTS) + message(STATUS "SKIP_CODEGEN: Skipping ${CMD_TARGET} (no outputs)") + if(CMD_TARGET) + add_custom_target(${CMD_TARGET}) + endif() + return() + else() + message(FATAL_ERROR "SKIP_CODEGEN: Cannot skip ${CMD_TARGET} - missing outputs. Run codegen on x64 first.") + endif() + endif() + foreach(target ${CMD_TARGETS}) if(target MATCHES "/|\\\\") message(FATAL_ERROR "register_command: TARGETS contains \"${target}\", if it's a path add it to SOURCES instead") @@ -650,6 +677,7 @@ function(register_bun_install) ${NPM_CWD} COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} install --frozen-lockfile SOURCES @@ -757,7 +785,7 @@ function(register_cmake_command) set(MAKE_EFFECTIVE_ARGS -B${MAKE_BUILD_PATH} ${CMAKE_ARGS}) set(setFlags GENERATOR BUILD_TYPE) - set(appendFlags C_FLAGS CXX_FLAGS LINKER_FLAGS) + set(appendFlags C_FLAGS CXX_FLAGS LINKER_FLAGS STATIC_LINKER_FLAGS EXE_LINKER_FLAGS SHARED_LINKER_FLAGS MODULE_LINKER_FLAGS) set(specialFlags POSITION_INDEPENDENT_CODE) set(flags ${setFlags} ${appendFlags} ${specialFlags}) @@ -803,6 +831,14 @@ function(register_cmake_command) list(APPEND MAKE_EFFECTIVE_ARGS "-DCMAKE_${flag}=${MAKE_${flag}}") endforeach() + # Workaround for CMake 4.1.0 bug: Force correct machine type for Windows ARM64 + # Use toolchain file and set CMP0197 policy to prevent duplicate /machine: flags + if(WIN32 AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64|AARCH64") + list(APPEND MAKE_EFFECTIVE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CWD}/cmake/toolchains/windows-aarch64.cmake") + list(APPEND MAKE_EFFECTIVE_ARGS "-DCMAKE_POLICY_DEFAULT_CMP0197=NEW") + list(APPEND MAKE_EFFECTIVE_ARGS "-DCMAKE_PROJECT_INCLUDE=${CWD}/cmake/arm64-static-lib-fix.cmake") + endif() + if(DEFINED FRESH) list(APPEND MAKE_EFFECTIVE_ARGS --fresh) endif() diff --git a/cmake/Options.cmake b/cmake/Options.cmake index e54f6db166..47e8e55457 100644 --- a/cmake/Options.cmake +++ b/cmake/Options.cmake @@ -4,6 +4,7 @@ endif() optionx(BUN_LINK_ONLY BOOL "If only the linking step should be built" DEFAULT OFF) optionx(BUN_CPP_ONLY BOOL "If only the C++ part of Bun should be built" DEFAULT OFF) +optionx(SKIP_CODEGEN BOOL "Skip JavaScript codegen (for Windows ARM64 debug)" DEFAULT OFF) optionx(BUILDKITE BOOL "If Buildkite is enabled" DEFAULT OFF) optionx(GITHUB_ACTIONS BOOL "If GitHub Actions is enabled" DEFAULT OFF) @@ -49,7 +50,7 @@ else() message(FATAL_ERROR "Unsupported operating system: ${CMAKE_SYSTEM_NAME}") endif() -if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64") setx(ARCH "aarch64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|x64|AMD64") setx(ARCH "x64") @@ -57,6 +58,18 @@ else() message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") endif() +# CMake 4.0+ policy CMP0197 controls how MSVC machine type flags are handled +# Setting to NEW prevents duplicate /machine: flags being added to linker commands +if(WIN32 AND ARCH STREQUAL "aarch64") + set(CMAKE_POLICY_DEFAULT_CMP0197 NEW) + set(CMAKE_MSVC_CMP0197 NEW) + # Set linker flags for exe/shared linking + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /machine:ARM64") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /machine:ARM64") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /machine:ARM64") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /machine:ARM64") +endif() + # Windows Code Signing Option if(WIN32) optionx(ENABLE_WINDOWS_CODESIGNING BOOL "Enable Windows code signing with DigiCert KeyLocker" DEFAULT OFF) @@ -199,6 +212,16 @@ optionx(USE_WEBKIT_ICU BOOL "Use the ICU libraries from WebKit" DEFAULT ${DEFAUL optionx(ERROR_LIMIT STRING "Maximum number of errors to show when compiling C++ code" DEFAULT "100") +# TinyCC is used for FFI JIT compilation +# Disable on Windows ARM64 where it's not yet supported +if(WIN32 AND ARCH STREQUAL "aarch64") + set(DEFAULT_ENABLE_TINYCC OFF) +else() + set(DEFAULT_ENABLE_TINYCC ON) +endif() + +optionx(ENABLE_TINYCC BOOL "Enable TinyCC for FFI JIT compilation" DEFAULT ${DEFAULT_ENABLE_TINYCC}) + # This is not an `option` because setting this variable to OFF is experimental # and unsupported. This replaces the `use_mimalloc` variable previously in # bun.zig, and enables C++ code to also be aware of the option. diff --git a/cmake/arm64-static-lib-fix.cmake b/cmake/arm64-static-lib-fix.cmake new file mode 100644 index 0000000000..e2ccfe9bdf --- /dev/null +++ b/cmake/arm64-static-lib-fix.cmake @@ -0,0 +1,8 @@ +# This file is included after project() via CMAKE_PROJECT_INCLUDE +# It fixes the static library creation command to use ARM64 machine type + +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL \"aarch64\") + # Override the static library creation commands to avoid spurious /machine:x64 flags + set(CMAKE_C_CREATE_STATIC_LIBRARY \" /nologo /machine:ARM64 /out: \" CACHE STRING \"\" FORCE) + set(CMAKE_CXX_CREATE_STATIC_LIBRARY \" /nologo /machine:ARM64 /out: \" CACHE STRING \"\" FORCE) +endif() \ No newline at end of file diff --git a/cmake/scripts/DownloadZig.cmake b/cmake/scripts/DownloadZig.cmake index df5459da23..871d7c214f 100644 --- a/cmake/scripts/DownloadZig.cmake +++ b/cmake/scripts/DownloadZig.cmake @@ -21,7 +21,12 @@ if(NOT DEFINED CMAKE_HOST_SYSTEM_PROCESSOR) endif() if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64") - set(ZIG_ARCH "aarch64") + # Windows ARM64 can run x86_64 via emulation, and no native ARM64 Zig build exists yet + if(CMAKE_HOST_WIN32) + set(ZIG_ARCH "x86_64") + else() + set(ZIG_ARCH "aarch64") + endif() elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|AMD64|x86_64|X86_64|x64|X64") set(ZIG_ARCH "x86_64") else() diff --git a/cmake/scripts/llvm-lib-arm64.bat b/cmake/scripts/llvm-lib-arm64.bat new file mode 100644 index 0000000000..cea6e9d80d --- /dev/null +++ b/cmake/scripts/llvm-lib-arm64.bat @@ -0,0 +1,34 @@ +@echo off +setlocal enabledelayedexpansion + +REM Wrapper for llvm-lib that strips conflicting /machine:x64 flag for ARM64 builds +REM This is a workaround for CMake 4.1.0 bug + +REM Find llvm-lib.exe - check LLVM_LIB env var, then PATH, then known locations +if defined LLVM_LIB ( + set "LLVM_LIB_EXE=!LLVM_LIB!" +) else ( + where llvm-lib.exe >nul 2>&1 + if !ERRORLEVEL! equ 0 ( + for /f "delims=" %%i in ('where llvm-lib.exe') do set "LLVM_LIB_EXE=%%i" + ) else if exist "C:\Program Files\LLVM\bin\llvm-lib.exe" ( + set "LLVM_LIB_EXE=C:\Program Files\LLVM\bin\llvm-lib.exe" + ) else ( + echo Error: Cannot find llvm-lib.exe. Set LLVM_LIB environment variable or add LLVM to PATH. + exit /b 1 + ) +) + +set "ARGS=" + +for %%a in (%*) do ( + set "ARG=%%a" + if /i "!ARG!"=="/machine:x64" ( + REM Skip this argument + ) else ( + set "ARGS=!ARGS! %%a" + ) +) + +"!LLVM_LIB_EXE!" %ARGS% +exit /b %ERRORLEVEL% diff --git a/cmake/scripts/llvm-lib-arm64.ps1 b/cmake/scripts/llvm-lib-arm64.ps1 new file mode 100644 index 0000000000..2b18e353c0 --- /dev/null +++ b/cmake/scripts/llvm-lib-arm64.ps1 @@ -0,0 +1,18 @@ +# Wrapper for llvm-lib that strips conflicting /machine:x64 flag for ARM64 builds +# This is a workaround for CMake 4.1.0 bug where both /machine:ARM64 and /machine:x64 are added + +# Find llvm-lib.exe - check LLVM_LIB env var, then PATH, then known locations +if ($env:LLVM_LIB) { + $llvmLib = $env:LLVM_LIB +} elseif (Get-Command llvm-lib.exe -ErrorAction SilentlyContinue) { + $llvmLib = (Get-Command llvm-lib.exe).Source +} elseif (Test-Path "C:\Program Files\LLVM\bin\llvm-lib.exe") { + $llvmLib = "C:\Program Files\LLVM\bin\llvm-lib.exe" +} else { + Write-Error "Cannot find llvm-lib.exe. Set LLVM_LIB environment variable or add LLVM to PATH." + exit 1 +} + +$filteredArgs = $args | Where-Object { $_ -ne "/machine:x64" } +& $llvmLib @filteredArgs +exit $LASTEXITCODE diff --git a/cmake/scripts/llvm-lib-wrapper.bat b/cmake/scripts/llvm-lib-wrapper.bat new file mode 100644 index 0000000000..cc5c5fa507 --- /dev/null +++ b/cmake/scripts/llvm-lib-wrapper.bat @@ -0,0 +1,34 @@ +@echo off +setlocal enabledelayedexpansion + +REM Wrapper for llvm-lib that strips conflicting /machine:x64 flag for ARM64 builds +REM This is a workaround for CMake 4.1.0 bug + +REM Find llvm-lib.exe - check LLVM_LIB env var, then PATH, then known locations +if defined LLVM_LIB ( + set "LLVM_LIB_EXE=!LLVM_LIB!" +) else ( + where llvm-lib.exe >nul 2>&1 + if !ERRORLEVEL! equ 0 ( + for /f "delims=" %%i in ('where llvm-lib.exe') do set "LLVM_LIB_EXE=%%i" + ) else if exist "C:\Program Files\LLVM\bin\llvm-lib.exe" ( + set "LLVM_LIB_EXE=C:\Program Files\LLVM\bin\llvm-lib.exe" + ) else ( + echo Error: Cannot find llvm-lib.exe. Set LLVM_LIB environment variable or add LLVM to PATH. + exit /b 1 + ) +) + +set NEWARGS= + +for %%a in (%*) do ( + set "ARG=%%a" + if /i "!ARG!"=="/machine:x64" ( + REM Skip /machine:x64 argument + ) else ( + set "NEWARGS=!NEWARGS! %%a" + ) +) + +"!LLVM_LIB_EXE!" %NEWARGS% +exit /b %ERRORLEVEL% \ No newline at end of file diff --git a/cmake/targets/BuildBun.cmake b/cmake/targets/BuildBun.cmake index b3b38f4850..26d798370f 100644 --- a/cmake/targets/BuildBun.cmake +++ b/cmake/targets/BuildBun.cmake @@ -57,13 +57,17 @@ set(BUN_DEPENDENCIES LolHtml Lshpack Mimalloc - TinyCC Zlib LibArchive # must be loaded after zlib HdrHistogram # must be loaded after zlib Zstd ) +# TinyCC is optional - disabled on Windows ARM64 where it's not supported +if(ENABLE_TINYCC) + list(APPEND BUN_DEPENDENCIES TinyCC) +endif() + include(CloneZstd) # --- Codegen --- @@ -185,7 +189,7 @@ register_command( CWD ${BUN_NODE_FALLBACKS_SOURCE} COMMAND - ${BUN_EXECUTABLE} run build-fallbacks + ${BUN_EXECUTABLE} ${BUN_FLAGS} run build-fallbacks ${BUN_NODE_FALLBACKS_OUTPUT} ${BUN_NODE_FALLBACKS_SOURCES} SOURCES @@ -206,7 +210,7 @@ register_command( CWD ${BUN_NODE_FALLBACKS_SOURCE} COMMAND - ${BUN_EXECUTABLE} build + ${BUN_EXECUTABLE} ${BUN_FLAGS} build ${BUN_NODE_FALLBACKS_SOURCE}/node_modules/react-refresh/cjs/react-refresh-runtime.development.js --outfile=${BUN_REACT_REFRESH_OUTPUT} --target=browser @@ -243,6 +247,7 @@ register_command( "Generating ErrorCode.{zig,h}" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} run ${BUN_ERROR_CODE_SCRIPT} ${CODEGEN_PATH} @@ -278,6 +283,7 @@ register_command( "Generating ZigGeneratedClasses.{zig,cpp,h}" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} run ${BUN_ZIG_GENERATED_CLASSES_SCRIPT} ${BUN_ZIG_GENERATED_CLASSES_SOURCES} @@ -328,6 +334,7 @@ register_command( "Generating C++ --> Zig bindings" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} ${CWD}/src/codegen/cppbind.ts ${CWD}/src ${CODEGEN_PATH} @@ -345,6 +352,7 @@ register_command( "Generating CI info" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} ${CWD}/src/codegen/ci_info.ts ${CODEGEN_PATH}/ci_info.zig SOURCES @@ -353,24 +361,35 @@ register_command( ${BUN_CI_INFO_OUTPUTS} ) -register_command( - TARGET - bun-js-modules - COMMENT - "Generating JavaScript modules" - COMMAND - ${BUN_EXECUTABLE} - run +if(SKIP_CODEGEN) + # Skip JavaScript codegen - useful for Windows ARM64 debug builds where bun crashes + message(STATUS "SKIP_CODEGEN is ON - skipping bun-js-modules codegen") + foreach(output ${BUN_JAVASCRIPT_OUTPUTS}) + if(NOT EXISTS ${output}) + message(FATAL_ERROR "SKIP_CODEGEN is ON but ${output} does not exist. Run codegen manually first.") + endif() + endforeach() +else() + register_command( + TARGET + bun-js-modules + COMMENT + "Generating JavaScript modules" + COMMAND + ${BUN_EXECUTABLE} + ${BUN_FLAGS} + run + ${BUN_JAVASCRIPT_CODEGEN_SCRIPT} + --debug=${DEBUG} + ${BUILD_PATH} + SOURCES + ${BUN_JAVASCRIPT_SOURCES} + ${BUN_JAVASCRIPT_CODEGEN_SOURCES} ${BUN_JAVASCRIPT_CODEGEN_SCRIPT} - --debug=${DEBUG} - ${BUILD_PATH} - SOURCES - ${BUN_JAVASCRIPT_SOURCES} - ${BUN_JAVASCRIPT_CODEGEN_SOURCES} - ${BUN_JAVASCRIPT_CODEGEN_SCRIPT} - OUTPUTS - ${BUN_JAVASCRIPT_OUTPUTS} -) + OUTPUTS + ${BUN_JAVASCRIPT_OUTPUTS} + ) +endif() set(BUN_BAKE_RUNTIME_CODEGEN_SCRIPT ${CWD}/src/codegen/bake-codegen.ts) @@ -392,6 +411,7 @@ register_command( "Bundling Bake Runtime" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} run ${BUN_BAKE_RUNTIME_CODEGEN_SCRIPT} --debug=${DEBUG} @@ -415,7 +435,7 @@ string(REPLACE ";" "," BUN_BINDGENV2_SOURCES_COMMA_SEPARATED "${BUN_BINDGENV2_SOURCES}") execute_process( - COMMAND ${BUN_EXECUTABLE} run ${BUN_BINDGENV2_SCRIPT} + COMMAND ${BUN_EXECUTABLE} ${BUN_FLAGS} run ${BUN_BINDGENV2_SCRIPT} --command=list-outputs --sources=${BUN_BINDGENV2_SOURCES_COMMA_SEPARATED} --codegen-path=${CODEGEN_PATH} @@ -438,7 +458,7 @@ register_command( COMMENT "Generating bindings (v2)" COMMAND - ${BUN_EXECUTABLE} run ${BUN_BINDGENV2_SCRIPT} + ${BUN_EXECUTABLE} ${BUN_FLAGS} run ${BUN_BINDGENV2_SCRIPT} --command=generate --codegen-path=${CODEGEN_PATH} --sources=${BUN_BINDGENV2_SOURCES_COMMA_SEPARATED} @@ -469,6 +489,7 @@ register_command( "Processing \".bind.ts\" files" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} run ${BUN_BINDGEN_SCRIPT} --debug=${DEBUG} @@ -501,6 +522,7 @@ register_command( "Generating JSSink.{cpp,h}" COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} run ${BUN_JS_SINK_SCRIPT} ${CODEGEN_PATH} @@ -573,6 +595,7 @@ foreach(i RANGE 0 ${BUN_OBJECT_LUT_SOURCES_MAX_INDEX}) ${BUN_OBJECT_LUT_SOURCE} COMMAND ${BUN_EXECUTABLE} + ${BUN_FLAGS} run ${BUN_OBJECT_LUT_SCRIPT} ${BUN_OBJECT_LUT_SOURCE} @@ -656,6 +679,10 @@ endif() if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM|arm64|ARM64|aarch64|AARCH64") if(APPLE) set(ZIG_CPU "apple_m1") + elseif(WIN32) + # Windows ARM64: use a specific CPU with NEON support + # Zig running under x64 emulation would detect wrong CPU with "native" + set(ZIG_CPU "cortex_a76") else() set(ZIG_CPU "native") endif() @@ -694,6 +721,7 @@ register_command( -Denable_asan=$,true,false> -Denable_fuzzilli=$,true,false> -Denable_valgrind=$,true,false> + -Denable_tinycc=$,true,false> -Duse_mimalloc=$,true,false> -Dllvm_codegen_threads=${LLVM_ZIG_CODEGEN_THREADS} -Dversion=${VERSION} @@ -1211,7 +1239,7 @@ if(BUN_LINK_ONLY) WEBKIT_DOWNLOAD_URL=${WEBKIT_DOWNLOAD_URL} WEBKIT_VERSION=${WEBKIT_VERSION} ZIG_COMMIT=${ZIG_COMMIT} - ${BUN_EXECUTABLE} ${CWD}/scripts/create-link-metadata.mjs ${BUILD_PATH} ${bun} + ${BUN_EXECUTABLE} ${BUN_FLAGS} ${CWD}/scripts/create-link-metadata.mjs ${BUILD_PATH} ${bun} SOURCES ${BUN_ZIG_OUTPUT} ${BUN_CPP_OUTPUT} diff --git a/cmake/targets/BuildHighway.cmake b/cmake/targets/BuildHighway.cmake index 1796e8f97f..4e89416d5c 100644 --- a/cmake/targets/BuildHighway.cmake +++ b/cmake/targets/BuildHighway.cmake @@ -20,6 +20,15 @@ set(HIGHWAY_CMAKE_ARGS -DHWY_ENABLE_INSTALL=OFF ) +# On Windows ARM64 with clang-cl, the __ARM_NEON macro isn't defined by default +# but NEON intrinsics are supported. Define it so Highway can detect NEON support. +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64|AARCH64") + list(APPEND HIGHWAY_CMAKE_ARGS + -DCMAKE_C_FLAGS=-D__ARM_NEON=1 + -DCMAKE_CXX_FLAGS=-D__ARM_NEON=1 + ) +endif() + register_cmake_command( TARGET highway diff --git a/cmake/targets/BuildLolHtml.cmake b/cmake/targets/BuildLolHtml.cmake index 26fa265e70..623ae844b6 100644 --- a/cmake/targets/BuildLolHtml.cmake +++ b/cmake/targets/BuildLolHtml.cmake @@ -33,6 +33,37 @@ if (NOT WIN32) set(RUSTFLAGS "-Cpanic=abort-Cdebuginfo=0-Cforce-unwind-tables=no-Copt-level=s") endif() +# On Windows, ensure MSVC link.exe is used instead of Git's link.exe +set(LOLHTML_ENV + CARGO_TERM_COLOR=always + CARGO_TERM_VERBOSE=true + CARGO_TERM_DIAGNOSTIC=true + CARGO_ENCODED_RUSTFLAGS=${RUSTFLAGS} + CARGO_HOME=${CARGO_HOME} + RUSTUP_HOME=${RUSTUP_HOME} +) + +if(WIN32) + # On Windows, tell Rust to use MSVC link.exe directly via the target-specific linker env var. + # This avoids Git's /usr/bin/link being found first in PATH. + # Find the MSVC link.exe from Visual Studio installation + file(GLOB MSVC_VERSIONS "C:/Program Files/Microsoft Visual Studio/2022/*/VC/Tools/MSVC/*") + if(MSVC_VERSIONS) + list(GET MSVC_VERSIONS -1 MSVC_LATEST) # Get the latest version + if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64") + set(MSVC_LINK_PATH "${MSVC_LATEST}/bin/HostARM64/arm64/link.exe") + set(CARGO_LINKER_VAR "CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER") + else() + set(MSVC_LINK_PATH "${MSVC_LATEST}/bin/Hostx64/x64/link.exe") + set(CARGO_LINKER_VAR "CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER") + endif() + if(EXISTS "${MSVC_LINK_PATH}") + list(APPEND LOLHTML_ENV "${CARGO_LINKER_VAR}=${MSVC_LINK_PATH}") + message(STATUS "lolhtml: Using MSVC link.exe: ${MSVC_LINK_PATH}") + endif() + endif() +endif() + register_command( TARGET lolhtml @@ -45,12 +76,7 @@ register_command( ARTIFACTS ${LOLHTML_LIBRARY} ENVIRONMENT - CARGO_TERM_COLOR=always - CARGO_TERM_VERBOSE=true - CARGO_TERM_DIAGNOSTIC=true - CARGO_ENCODED_RUSTFLAGS=${RUSTFLAGS} - CARGO_HOME=${CARGO_HOME} - RUSTUP_HOME=${RUSTUP_HOME} + ${LOLHTML_ENV} ) target_link_libraries(${bun} PRIVATE ${LOLHTML_LIBRARY}) diff --git a/cmake/toolchains/windows-aarch64.cmake b/cmake/toolchains/windows-aarch64.cmake new file mode 100644 index 0000000000..f6fb70668f --- /dev/null +++ b/cmake/toolchains/windows-aarch64.cmake @@ -0,0 +1,20 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(CMAKE_C_COMPILER_WORKS ON) +set(CMAKE_CXX_COMPILER_WORKS ON) + +# Force ARM64 architecture ID - this is what CMake uses to determine /machine: flag +set(MSVC_C_ARCHITECTURE_ID ARM64 CACHE INTERNAL "") +set(MSVC_CXX_ARCHITECTURE_ID ARM64 CACHE INTERNAL "") + +# CMake 4.0+ policy CMP0197 controls how MSVC machine type flags are handled +set(CMAKE_POLICY_DEFAULT_CMP0197 NEW CACHE INTERNAL "") + +# Clear any inherited static linker flags that might have wrong machine types +set(CMAKE_STATIC_LINKER_FLAGS "" CACHE STRING "" FORCE) + +# Use wrapper script for llvm-lib that strips /machine:x64 flags +# This works around CMake 4.1.0 bug where both ARM64 and x64 machine flags are added +get_filename_component(_TOOLCHAIN_DIR "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY) +set(CMAKE_AR "${_TOOLCHAIN_DIR}/scripts/llvm-lib-wrapper.bat" CACHE FILEPATH "" FORCE) \ No newline at end of file diff --git a/cmake/tools/SetupBuildkite.cmake b/cmake/tools/SetupBuildkite.cmake index 367c9c8d3b..1900c3bd87 100644 --- a/cmake/tools/SetupBuildkite.cmake +++ b/cmake/tools/SetupBuildkite.cmake @@ -48,8 +48,16 @@ if(NOT BUILDKITE_BUILD_STATUS EQUAL 0) endif() file(READ ${BUILDKITE_BUILD_PATH}/build.json BUILDKITE_BUILD) -# Escape backslashes so CMake doesn't interpret JSON escape sequences (e.g., \n in commit messages) -string(REPLACE "\\" "\\\\" BUILDKITE_BUILD "${BUILDKITE_BUILD}") +# CMake's string(JSON ...) interprets escape sequences like \n, \r, \t. +# We need to escape these specific sequences while preserving valid JSON escapes like \" and \\. +# Strategy: Use a unique placeholder to protect \\ sequences, escape \n/\r/\t, then restore \\. +# This prevents \\n (literal backslash + n) from being corrupted to \\\n. +set(BKSLASH_PLACEHOLDER "___BKSLASH_PLACEHOLDER_7f3a9b2c___") +string(REPLACE "\\\\" "${BKSLASH_PLACEHOLDER}" BUILDKITE_BUILD "${BUILDKITE_BUILD}") +string(REPLACE "\\n" "\\\\n" BUILDKITE_BUILD "${BUILDKITE_BUILD}") +string(REPLACE "\\r" "\\\\r" BUILDKITE_BUILD "${BUILDKITE_BUILD}") +string(REPLACE "\\t" "\\\\t" BUILDKITE_BUILD "${BUILDKITE_BUILD}") +string(REPLACE "${BKSLASH_PLACEHOLDER}" "\\\\" BUILDKITE_BUILD "${BUILDKITE_BUILD}") string(JSON BUILDKITE_BUILD_UUID GET ${BUILDKITE_BUILD} id) string(JSON BUILDKITE_JOBS GET ${BUILDKITE_BUILD} jobs) diff --git a/cmake/tools/SetupBun.cmake b/cmake/tools/SetupBun.cmake index 3cb77ff4be..b57d29b9a1 100644 --- a/cmake/tools/SetupBun.cmake +++ b/cmake/tools/SetupBun.cmake @@ -17,6 +17,14 @@ if (NOT CI) set(BUN_EXECUTABLE ${BUN_EXECUTABLE} CACHE FILEPATH "Bun executable" FORCE) endif() +# On Windows ARM64, we need to add --smol flag to avoid crashes when running +# x64 bun under WoW64 emulation +if(WIN32 AND ARCH STREQUAL "aarch64") + set(BUN_FLAGS "--smol" CACHE STRING "Extra flags for bun executable") +else() + set(BUN_FLAGS "" CACHE STRING "Extra flags for bun executable") +endif() + # If this is not set, some advanced features are not checked. # https://github.com/oven-sh/bun/blob/cd7f6a1589db7f1e39dc4e3f4a17234afbe7826c/src/bun.js/javascript.zig#L1069-L1072 setenv(BUN_GARBAGE_COLLECTOR_LEVEL 1) diff --git a/cmake/tools/SetupLLVM.cmake b/cmake/tools/SetupLLVM.cmake index a250342018..d8849ed6f0 100644 --- a/cmake/tools/SetupLLVM.cmake +++ b/cmake/tools/SetupLLVM.cmake @@ -12,7 +12,13 @@ if(NOT ENABLE_LLVM) return() endif() -set(DEFAULT_LLVM_VERSION "19.1.7") +# LLVM 21 is required for Windows ARM64 (first version with ARM64 Windows builds) +# Other platforms use LLVM 19.1.7 +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64|AARCH64") + set(DEFAULT_LLVM_VERSION "21.1.8") +else() + set(DEFAULT_LLVM_VERSION "19.1.7") +endif() optionx(LLVM_VERSION STRING "The version of LLVM to use" DEFAULT ${DEFAULT_LLVM_VERSION}) diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index 08a4b654e5..17d211e6a7 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -5,7 +5,11 @@ if(NOT WEBKIT_VERSION) set(WEBKIT_VERSION 87c6cde57dd1d2a82bbc9caf500f70f8a7c1f249) endif() +# Use preview build URL for Windows ARM64 until the fix is merged to main +set(WEBKIT_PREVIEW_PR 140) + string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX) +string(SUBSTRING ${WEBKIT_VERSION} 0 8 WEBKIT_VERSION_SHORT) if(WEBKIT_LOCAL) set(DEFAULT_WEBKIT_PATH ${VENDOR_PATH}/WebKit/WebKitBuild/${CMAKE_BUILD_TYPE}) @@ -36,6 +40,22 @@ if(WEBKIT_LOCAL) ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders/JavaScriptCore ${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector ) + + # On Windows, add ICU include path from vcpkg + if(WIN32) + # Auto-detect vcpkg triplet + set(VCPKG_ARM64_PATH ${VENDOR_PATH}/WebKit/vcpkg_installed/arm64-windows-static) + set(VCPKG_X64_PATH ${VENDOR_PATH}/WebKit/vcpkg_installed/x64-windows-static) + if(EXISTS ${VCPKG_ARM64_PATH}) + set(VCPKG_ICU_PATH ${VCPKG_ARM64_PATH}) + else() + set(VCPKG_ICU_PATH ${VCPKG_X64_PATH}) + endif() + if(EXISTS ${VCPKG_ICU_PATH}/include) + include_directories(${VCPKG_ICU_PATH}/include) + message(STATUS "Using ICU from vcpkg: ${VCPKG_ICU_PATH}/include") + endif() + endif() endif() # After this point, only prebuilt WebKit is supported @@ -52,7 +72,7 @@ else() message(FATAL_ERROR "Unsupported operating system: ${CMAKE_SYSTEM_NAME}") endif() -if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64") set(WEBKIT_ARCH "arm64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|x64|AMD64") set(WEBKIT_ARCH "amd64") diff --git a/cmake/tools/SetupZig.cmake b/cmake/tools/SetupZig.cmake index 320a6f4e64..fcdd8721f3 100644 --- a/cmake/tools/SetupZig.cmake +++ b/cmake/tools/SetupZig.cmake @@ -1,4 +1,4 @@ -if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64") set(DEFAULT_ZIG_ARCH "aarch64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|x64|AMD64") set(DEFAULT_ZIG_ARCH "x86_64") diff --git a/docs/project/building-windows.mdx b/docs/project/building-windows.mdx index dc0b4836d3..5e50773b40 100644 --- a/docs/project/building-windows.mdx +++ b/docs/project/building-windows.mdx @@ -35,7 +35,7 @@ winget install "Visual Studio Community 2022" --override "--add Microsoft.Visual After Visual Studio, you need the following: -- LLVM 19.1.7 +- LLVM (19.1.7 for x64, 21.1.8 for ARM64) - Go - Rust - NASM @@ -47,25 +47,35 @@ After Visual Studio, you need the following: [Scoop](https://scoop.sh) can be used to install these remaining tools easily. -```ps1 Scoop +```ps1 Scoop (x64) irm https://get.scoop.sh | iex scoop install nodejs-lts go rust nasm ruby perl ccache # scoop seems to be buggy if you install llvm and the rest at the same time scoop install llvm@19.1.7 ``` +For Windows ARM64, download LLVM 21.1.8 directly from GitHub releases (first version with ARM64 Windows builds): + +```ps1 ARM64 +# Download and install LLVM for ARM64 +Invoke-WebRequest -Uri "https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.8/LLVM-21.1.8-woa64.exe" -OutFile "$env:TEMP\LLVM-21.1.8-woa64.exe" +Start-Process -FilePath "$env:TEMP\LLVM-21.1.8-woa64.exe" -ArgumentList "/S" -Wait +``` + Please do not use WinGet/other package manager for these, as you will likely install Strawberry Perl instead of a more minimal installation of Perl. Strawberry Perl includes many other utilities that get installed into `$Env:PATH` that will conflict with MSVC and break the build. -If you intend on building WebKit locally (optional), you should install these packages: +If you intend on building WebKit locally (optional, x64 only), you should install these packages: ```ps1 Scoop scoop install make cygwin python ``` +Cygwin is not required for ARM64 builds as WebKit is provided as a pre-built binary. + From here on out, it is **expected you use a PowerShell Terminal with `.\scripts\vs-shell.ps1` sourced**. This script is available in the Bun repository and can be loaded by executing it: ```ps1 diff --git a/scripts/build-jsc.ts b/scripts/build-jsc.ts index 4da6617402..df80850d67 100755 --- a/scripts/build-jsc.ts +++ b/scripts/build-jsc.ts @@ -23,7 +23,10 @@ const OS_NAME = platform().toLowerCase(); const ARCH_NAME_RAW = arch(); const IS_MAC = OS_NAME === "darwin"; const IS_LINUX = OS_NAME === "linux"; -const IS_ARM64 = ARCH_NAME_RAW === "arm64" || ARCH_NAME_RAW === "aarch64"; +const IS_WINDOWS = OS_NAME === "win32"; +// On Windows, use PROCESSOR_ARCHITECTURE env var to get native arch (Bun may run under x64 emulation) +const NATIVE_ARCH = IS_WINDOWS ? (process.env.PROCESSOR_ARCHITECTURE || ARCH_NAME_RAW).toUpperCase() : ARCH_NAME_RAW; +const IS_ARM64 = NATIVE_ARCH === "ARM64" || NATIVE_ARCH === "AARCH64" || ARCH_NAME_RAW === "arm64"; // Paths const ROOT_DIR = resolve(import.meta.dir, ".."); @@ -33,22 +36,54 @@ const WEBKIT_RELEASE_DIR = join(WEBKIT_BUILD_DIR, "Release"); const WEBKIT_DEBUG_DIR = join(WEBKIT_BUILD_DIR, "Debug"); const WEBKIT_RELEASE_DIR_LTO = join(WEBKIT_BUILD_DIR, "ReleaseLTO"); +// Windows ICU paths - use vcpkg static build +// Auto-detect triplet: prefer arm64 if it exists, otherwise x64 +const VCPKG_ARM64_PATH = join(WEBKIT_DIR, "vcpkg_installed", "arm64-windows-static"); +const VCPKG_X64_PATH = join(WEBKIT_DIR, "vcpkg_installed", "x64-windows-static"); +const VCPKG_ROOT = existsSync(VCPKG_ARM64_PATH) ? VCPKG_ARM64_PATH : VCPKG_X64_PATH; +const ICU_INCLUDE_DIR = join(VCPKG_ROOT, "include"); + +// Get ICU library paths based on build config (debug uses 'd' suffix libraries) +function getICULibraryPaths(config: BuildConfig) { + const isDebug = config === "debug"; + // vcpkg static ICU libraries: release in lib/, debug in debug/lib/ with 'd' suffix + const libDir = isDebug ? join(VCPKG_ROOT, "debug", "lib") : join(VCPKG_ROOT, "lib"); + const suffix = isDebug ? "d" : ""; + return { + ICU_LIBRARY: libDir, + ICU_DATA_LIBRARY: join(libDir, `sicudt${suffix}.lib`), + ICU_I18N_LIBRARY: join(libDir, `sicuin${suffix}.lib`), + ICU_UC_LIBRARY: join(libDir, `sicuuc${suffix}.lib`), + }; +} + // Homebrew prefix detection const HOMEBREW_PREFIX = IS_ARM64 ? "/opt/homebrew/" : "/usr/local/"; // Compiler detection function findExecutable(names: string[]): string | null { for (const name of names) { - const result = spawnSync("which", [name], { encoding: "utf8" }); - if (result.status === 0) { - return result.stdout.trim(); - } + const path = Bun.which(name); + if (path) return path; } return null; } -const CC = findExecutable(["clang-19", "clang"]) || "clang"; -const CXX = findExecutable(["clang++-19", "clang++"]) || "clang++"; +// Detect ccache +const CCACHE = findExecutable(["ccache"]); +const HAS_CCACHE = CCACHE !== null; + +// Configure compilers with ccache if available +// On Windows, use clang-cl for MSVC compatibility +const CC_BASE = IS_WINDOWS + ? findExecutable(["clang-cl.exe", "clang-cl"]) || "clang-cl" + : findExecutable(["clang-19", "clang"]) || "clang"; +const CXX_BASE = IS_WINDOWS + ? findExecutable(["clang-cl.exe", "clang-cl"]) || "clang-cl" + : findExecutable(["clang++-19", "clang++"]) || "clang++"; + +const CC = HAS_CCACHE ? CCACHE : CC_BASE; +const CXX = HAS_CCACHE ? CCACHE : CXX_BASE; // Build directory based on config const getBuildDir = (config: BuildConfig) => { @@ -63,7 +98,7 @@ const getBuildDir = (config: BuildConfig) => { }; // Common CMake flags -const getCommonFlags = () => { +const getCommonFlags = (config: BuildConfig) => { const flags = [ "-DPORT=JSCOnly", "-DENABLE_STATIC_JSC=ON", @@ -74,10 +109,20 @@ const getCommonFlags = () => { "-DENABLE_FTL_JIT=ON", "-G", "Ninja", - `-DCMAKE_C_COMPILER=${CC}`, - `-DCMAKE_CXX_COMPILER=${CXX}`, ]; + // Configure compiler with ccache if available + if (HAS_CCACHE) { + flags.push( + `-DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}`, + `-DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}`, + `-DCMAKE_C_COMPILER=${CC_BASE}`, + `-DCMAKE_CXX_COMPILER=${CXX_BASE}`, + ); + } else { + flags.push(`-DCMAKE_C_COMPILER=${CC}`, `-DCMAKE_CXX_COMPILER=${CXX}`); + } + if (IS_MAC) { flags.push( "-DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON", @@ -91,6 +136,27 @@ const getCommonFlags = () => { "-DUSE_VISIBILITY_ATTRIBUTE=1", "-DENABLE_REMOTE_INSPECTOR=ON", ); + } else if (IS_WINDOWS) { + // Find lld-link for Windows builds + const lldLink = findExecutable(["lld-link.exe", "lld-link"]) || "lld-link"; + // Get ICU library paths for this build config (debug uses 'd' suffix libraries) + const icuPaths = getICULibraryPaths(config); + + flags.push( + "-DENABLE_REMOTE_INSPECTOR=ON", + "-DUSE_VISIBILITY_ATTRIBUTE=1", + "-DUSE_SYSTEM_MALLOC=ON", + `-DCMAKE_LINKER=${lldLink}`, + `-DICU_ROOT=${VCPKG_ROOT}`, + `-DICU_LIBRARY=${icuPaths.ICU_LIBRARY}`, + `-DICU_INCLUDE_DIR=${ICU_INCLUDE_DIR}`, + // Explicitly set ICU library paths to use vcpkg static libs (debug has 'd' suffix) + `-DICU_DATA_LIBRARY_RELEASE=${icuPaths.ICU_DATA_LIBRARY}`, + `-DICU_I18N_LIBRARY_RELEASE=${icuPaths.ICU_I18N_LIBRARY}`, + `-DICU_UC_LIBRARY_RELEASE=${icuPaths.ICU_UC_LIBRARY}`, + "-DCMAKE_C_FLAGS=/DU_STATIC_IMPLEMENTATION", + "-DCMAKE_CXX_FLAGS=/DU_STATIC_IMPLEMENTATION /clang:-fno-c++-static-destructors", + ); } return flags; @@ -98,7 +164,7 @@ const getCommonFlags = () => { // Build-specific CMake flags const getBuildFlags = (config: BuildConfig) => { - const flags = [...getCommonFlags()]; + const flags = [...getCommonFlags(config)]; switch (config) { case "debug": @@ -110,20 +176,37 @@ const getBuildFlags = (config: BuildConfig) => { "-DUSE_VISIBILITY_ATTRIBUTE=1", ); - if (IS_MAC) { - // Enable address sanitizer by default on Mac debug builds + if (IS_MAC || IS_LINUX) { + // Enable address sanitizer by default on Mac/Linux debug builds flags.push("-DENABLE_SANITIZERS=address"); // To disable asan, comment the line above and uncomment: // flags.push("-DENABLE_MALLOC_HEAP_BREAKDOWN=ON"); } + + if (IS_WINDOWS) { + flags.push("-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug"); + } break; case "lto": - flags.push("-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_C_FLAGS=-flto=full", "-DCMAKE_CXX_FLAGS=-flto=full"); + flags.push("-DCMAKE_BUILD_TYPE=Release"); + if (IS_WINDOWS) { + // On Windows, append LTO flags to existing Windows-specific flags + flags.push( + "-DCMAKE_C_FLAGS=/DU_STATIC_IMPLEMENTATION -flto=full", + "-DCMAKE_CXX_FLAGS=/DU_STATIC_IMPLEMENTATION /clang:-fno-c++-static-destructors -flto=full", + "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded", + ); + } else { + flags.push("-DCMAKE_C_FLAGS=-flto=full", "-DCMAKE_CXX_FLAGS=-flto=full"); + } break; default: // release flags.push("-DCMAKE_BUILD_TYPE=RelWithDebInfo"); + if (IS_WINDOWS) { + flags.push("-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded"); + } break; } @@ -134,17 +217,6 @@ const getBuildFlags = (config: BuildConfig) => { const getBuildEnv = () => { const env = { ...process.env }; - const cflags = ["-ffat-lto-objects"]; - const cxxflags = ["-ffat-lto-objects"]; - - if (IS_LINUX && buildConfig !== "lto") { - cflags.push("-Wl,--whole-archive"); - cxxflags.push("-Wl,--whole-archive", "-DUSE_BUN_JSC_ADDITIONS=ON", "-DUSE_BUN_EVENT_LOOP=ON"); - } - - env.CFLAGS = (env.CFLAGS || "") + " " + cflags.join(" "); - env.CXXFLAGS = (env.CXXFLAGS || "") + " " + cxxflags.join(" "); - if (IS_MAC) { env.ICU_INCLUDE_DIRS = `${HOMEBREW_PREFIX}opt/icu4c/include`; } @@ -179,6 +251,9 @@ function buildJSC() { console.log(`Building JSC with configuration: ${buildConfig}`); console.log(`Build directory: ${buildDir}`); + if (HAS_CCACHE) { + console.log(`Using ccache for faster builds: ${CCACHE}`); + } // Create build directories if (!existsSync(buildDir)) { diff --git a/scripts/build.mjs b/scripts/build.mjs index 34ce12247c..3eccf7f6ba 100755 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -14,6 +14,15 @@ import { startGroup, } from "./utils.mjs"; +// Detect Windows ARM64 - bun may run under x64 emulation (WoW64), so check multiple indicators +const isWindowsARM64 = + isWindows && + (process.env.PROCESSOR_ARCHITECTURE === "ARM64" || + process.env.VSCMD_ARG_HOST_ARCH === "arm64" || + process.env.MSYSTEM_CARCH === "aarch64" || + (process.env.PROCESSOR_IDENTIFIER || "").includes("ARMv8") || + process.arch === "arm64"); + if (globalThis.Bun) { await import("./glob-sources.mjs"); } @@ -83,6 +92,23 @@ async function build(args) { generateOptions["--toolchain"] = toolchainPath; } + // Windows ARM64: automatically set required options + if (isWindowsARM64) { + // Use clang-cl instead of MSVC cl.exe for proper ARM64 flag support + if (!generateOptions["-DCMAKE_C_COMPILER"]) { + generateOptions["-DCMAKE_C_COMPILER"] = "clang-cl"; + } + if (!generateOptions["-DCMAKE_CXX_COMPILER"]) { + generateOptions["-DCMAKE_CXX_COMPILER"] = "clang-cl"; + } + // Skip codegen by default since x64 bun crashes under WoW64 emulation + // Can be overridden with -DSKIP_CODEGEN=OFF once ARM64 bun is available + if (!generateOptions["-DSKIP_CODEGEN"]) { + generateOptions["-DSKIP_CODEGEN"] = "ON"; + } + console.log("Windows ARM64 detected: using clang-cl and SKIP_CODEGEN=ON"); + } + const generateArgs = Object.entries(generateOptions).flatMap(([flag, value]) => flag.startsWith("-D") ? [`${flag}=${value}`] : [flag, value], ); diff --git a/scripts/vs-shell.ps1 b/scripts/vs-shell.ps1 index 7d61ade6c8..7ca7e0027a 100755 --- a/scripts/vs-shell.ps1 +++ b/scripts/vs-shell.ps1 @@ -3,6 +3,10 @@ $ErrorActionPreference = "Stop" +# Detect system architecture +$script:IsARM64 = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64 +$script:VsArch = if ($script:IsARM64) { "arm64" } else { "amd64" } + if($env:VSINSTALLDIR -eq $null) { Write-Host "Loading Visual Studio environment, this may take a second..." @@ -23,14 +27,14 @@ if($env:VSINSTALLDIR -eq $null) { Push-Location $vsDir try { $vsShell = (Join-Path -Path $vsDir -ChildPath "Common7\Tools\Launch-VsDevShell.ps1") - . $vsShell -Arch amd64 -HostArch amd64 + . $vsShell -Arch $script:VsArch -HostArch $script:VsArch } finally { Pop-Location } } if($env:VSCMD_ARG_TGT_ARCH -eq "x86") { - throw "Visual Studio environment is targeting 32 bit, but only 64 bit is supported." + throw "Visual Studio environment is targeting 32 bit x86, but only 64-bit architectures (x64/arm64) are supported." } if ($args.Count -gt 0) { diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index c330ba23bf..bf5b35d031 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -606,6 +606,9 @@ pub const FFI = struct { }; pub fn Bun__FFI__cc(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { + if (comptime !Environment.enable_tinycc) { + return globalThis.throw("bun:ffi cc() is not available in this build (TinyCC is disabled)", .{}); + } const arguments = callframe.arguments_old(1).slice(); if (arguments.len == 0 or !arguments[0].isObject()) { return globalThis.throwInvalidArguments("Expected object", .{}); @@ -834,6 +837,9 @@ pub const FFI = struct { } pub fn callback(globalThis: *JSGlobalObject, interface: jsc.JSValue, js_callback: jsc.JSValue) bun.JSError!JSValue { + if (comptime !Environment.enable_tinycc) { + return globalThis.throw("bun:ffi callback() is not available in this build (TinyCC is disabled)", .{}); + } jsc.markBinding(@src()); if (!interface.isObject()) { return globalThis.toInvalidArguments("Expected object", .{}); @@ -1003,6 +1009,10 @@ pub const FFI = struct { } pub fn open(global: *JSGlobalObject, name_str: ZigString, object_value: jsc.JSValue) jsc.JSValue { + if (comptime !Environment.enable_tinycc) { + global.throw("bun:ffi dlopen() is not available in this build (TinyCC is disabled)", .{}) catch {}; + return .zero; + } jsc.markBinding(@src()); const vm = VirtualMachine.get(); var name_slice = name_str.toSlice(bun.default_allocator); @@ -1169,6 +1179,10 @@ pub const FFI = struct { } pub fn linkSymbols(global: *JSGlobalObject, object_value: jsc.JSValue) jsc.JSValue { + if (comptime !Environment.enable_tinycc) { + global.throw("bun:ffi linkSymbols() is not available in this build (TinyCC is disabled)", .{}) catch {}; + return .zero; + } jsc.markBinding(@src()); const allocator = VirtualMachine.get().allocator; @@ -2417,8 +2431,13 @@ fn makeNapiEnvIfNeeded(functions: []const FFI.Function, globalThis: *JSGlobalObj const string = []const u8; +const TCC = if (Environment.enable_tinycc) @import("../../deps/tcc.zig") else struct { + pub const State = struct { + pub fn deinit(_: *State) void {} + }; +}; + const Fs = @import("../../fs.zig"); -const TCC = @import("../../deps/tcc.zig"); const napi = @import("../../napi/napi.zig"); const options = @import("../../options.zig"); const std = @import("std"); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index b228ec5c5e..e2275fdd51 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -286,20 +286,18 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c } #endif - JSC::initialize(); - { - - JSC::Options::AllowUnfinalizedAccessScope scope; - + // Use JSC::initialize with a callback to set Options during initialization. + // The callback runs BEFORE IPInt::initialize() so we can configure WASM options early. + JSC::initialize([&] { + JSC::Options::useWasm() = true; + JSC::Options::useJIT() = true; + JSC::Options::useBBQJIT() = true; JSC::Options::useConcurrentJIT() = true; // JSC::Options::useSigillCrashAnalyzer() = true; - JSC::Options::useWasm() = true; JSC::Options::useSourceProviderCache() = true; // JSC::Options::useUnlinkedCodeBlockJettisoning() = false; JSC::Options::exposeInternalModuleLoader() = true; JSC::Options::useSharedArrayBuffer() = true; - JSC::Options::useJIT() = true; - JSC::Options::useBBQJIT() = true; JSC::Options::useJITCage() = false; JSC::Options::useShadowRealm() = true; JSC::Options::useV8DateParser() = true; @@ -331,7 +329,7 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c } } JSC::Options::assertOptionsAreCoherent(); - } + }); // end JSC::initialize lambda }); // end std::call_once lambda // NOLINTEND diff --git a/src/bun.js/bindings/highway_strings.cpp b/src/bun.js/bindings/highway_strings.cpp index 3f19ac8984..4eb625a9bd 100644 --- a/src/bun.js/bindings/highway_strings.cpp +++ b/src/bun.js/bindings/highway_strings.cpp @@ -657,15 +657,15 @@ HWY_EXPORT(IndexOfNewlineOrNonASCIIOrHashOrAtImpl); HWY_EXPORT(IndexOfSpaceOrNewlineOrNonASCIIImpl); HWY_EXPORT(MemMemImpl); HWY_EXPORT(ScanCharFrequencyImpl); -} // namespace bun - // Define the C-callable wrappers that use HWY_DYNAMIC_DISPATCH. -// These need to be defined *after* the HWY_EXPORT block. +// These need to be defined *after* the HWY_EXPORT block and INSIDE namespace bun +// so that HWY_DYNAMIC_DISPATCH(FuncImpl) correctly resolves to bun::N_*::FuncImpl. +// The extern "C" only affects linkage (for C callers), not namespace resolution. extern "C" { void* highway_memmem(const uint8_t* haystack, size_t haystack_len, const uint8_t* needle, size_t needle_len) { - return HWY_DYNAMIC_DISPATCH(bun::MemMemImpl)(haystack, haystack_len, needle, needle_len); + return HWY_DYNAMIC_DISPATCH(MemMemImpl)(haystack, haystack_len, needle, needle_len); } static void highway_copy_u16_to_u8_impl( @@ -673,7 +673,7 @@ static void highway_copy_u16_to_u8_impl( size_t count, uint8_t* output) { - return HWY_DYNAMIC_DISPATCH(bun::CopyU16ToU8Impl)(input, count, output); + return HWY_DYNAMIC_DISPATCH(CopyU16ToU8Impl)(input, count, output); } void highway_copy_u16_to_u8( @@ -707,53 +707,53 @@ void highway_copy_u16_to_u8( } size_t highway_index_of_any_char(const uint8_t* HWY_RESTRICT text, size_t text_len, const uint8_t* HWY_RESTRICT chars, size_t chars_len) { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfAnyCharImpl)(text, text_len, chars, chars_len); + return HWY_DYNAMIC_DISPATCH(IndexOfAnyCharImpl)(text, text_len, chars, chars_len); } void highway_char_frequency(const uint8_t* HWY_RESTRICT text, size_t text_len, int32_t* freqs, int32_t delta) { - HWY_DYNAMIC_DISPATCH(bun::ScanCharFrequencyImpl)(text, text_len, freqs, delta); + HWY_DYNAMIC_DISPATCH(ScanCharFrequencyImpl)(text, text_len, freqs, delta); } size_t highway_index_of_char(const uint8_t* HWY_RESTRICT haystack, size_t haystack_len, uint8_t needle) { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfCharImpl)(haystack, haystack_len, needle); + return HWY_DYNAMIC_DISPATCH(IndexOfCharImpl)(haystack, haystack_len, needle); } size_t highway_index_of_interesting_character_in_string_literal(const uint8_t* HWY_RESTRICT text, size_t text_len, uint8_t quote) { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfInterestingCharacterInStringLiteralImpl)(text, text_len, quote); + return HWY_DYNAMIC_DISPATCH(IndexOfInterestingCharacterInStringLiteralImpl)(text, text_len, quote); } size_t highway_index_of_newline_or_non_ascii(const uint8_t* HWY_RESTRICT haystack, size_t haystack_len) { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfNewlineOrNonASCIIImpl)(haystack, haystack_len); + return HWY_DYNAMIC_DISPATCH(IndexOfNewlineOrNonASCIIImpl)(haystack, haystack_len); } size_t highway_index_of_newline_or_non_ascii_or_hash_or_at(const uint8_t* HWY_RESTRICT haystack, size_t haystack_len) { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfNewlineOrNonASCIIOrHashOrAtImpl)(haystack, haystack_len); + return HWY_DYNAMIC_DISPATCH(IndexOfNewlineOrNonASCIIOrHashOrAtImpl)(haystack, haystack_len); } bool highway_contains_newline_or_non_ascii_or_quote(const uint8_t* HWY_RESTRICT text, size_t text_len) { - return HWY_DYNAMIC_DISPATCH(bun::ContainsNewlineOrNonASCIIOrQuoteImpl)(text, text_len); + return HWY_DYNAMIC_DISPATCH(ContainsNewlineOrNonASCIIOrQuoteImpl)(text, text_len); } size_t highway_index_of_needs_escape_for_javascript_string(const uint8_t* HWY_RESTRICT text, size_t text_len, uint8_t quote_char) { if (quote_char == '`') { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfNeedsEscapeForJavaScriptStringImplBacktick)(text, text_len, quote_char); + return HWY_DYNAMIC_DISPATCH(IndexOfNeedsEscapeForJavaScriptStringImplBacktick)(text, text_len, quote_char); } else { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfNeedsEscapeForJavaScriptStringImplQuote)(text, text_len, quote_char); + return HWY_DYNAMIC_DISPATCH(IndexOfNeedsEscapeForJavaScriptStringImplQuote)(text, text_len, quote_char); } } size_t highway_index_of_space_or_newline_or_non_ascii(const uint8_t* HWY_RESTRICT text, size_t text_len) { - return HWY_DYNAMIC_DISPATCH(bun::IndexOfSpaceOrNewlineOrNonASCIIImpl)(text, text_len); + return HWY_DYNAMIC_DISPATCH(IndexOfSpaceOrNewlineOrNonASCIIImpl)(text, text_len); } void highway_fill_with_skip_mask( @@ -764,11 +764,13 @@ void highway_fill_with_skip_mask( size_t length, // Length of input/output bool skip_mask) // Whether to skip masking { - HWY_DYNAMIC_DISPATCH(bun::FillWithSkipMaskImpl)(mask, mask_len, output, input, length, skip_mask); + HWY_DYNAMIC_DISPATCH(FillWithSkipMaskImpl)(mask, mask_len, output, input, length, skip_mask); } } // extern "C" +} // namespace bun + #if OS(DARWIN) // On macOS, override the libc memmem with our implementation // This uses inline assembly to ensure the symbol is exported with the correct name diff --git a/src/compile_target.zig b/src/compile_target.zig index 1c3f7d54a4..a1400d0151 100644 --- a/src/compile_target.zig +++ b/src/compile_target.zig @@ -294,7 +294,7 @@ pub fn downloadToPath(this: *const CompileTarget, env: *bun.DotEnv.Loader, alloc pub fn isSupported(this: *const CompileTarget) bool { return switch (this.os) { - .windows => this.arch == .x64, + .windows => this.arch == .x64 or this.arch == .arm64, .mac => true, .linux => true, diff --git a/src/crash_handler.zig b/src/crash_handler.zig index 52033fcf18..c719549cc1 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -1103,6 +1103,7 @@ const Platform = enum(u8) { windows_x86_64 = 'w', windows_x86_64_baseline = 'e', + windows_aarch64 = 'W', const current = @field(Platform, @tagName(bun.Environment.os) ++ "_" ++ @tagName(builtin.target.cpu.arch) ++ diff --git a/src/env.zig b/src/env.zig index 528d4ef5a1..4d4fa2bbda 100644 --- a/src/env.zig +++ b/src/env.zig @@ -52,6 +52,7 @@ pub const base_path = build_options.base_path; pub const enable_logs = build_options.enable_logs; pub const enable_asan = build_options.enable_asan; pub const enable_fuzzilli = build_options.enable_fuzzilli; +pub const enable_tinycc = build_options.enable_tinycc; pub const codegen_path = build_options.codegen_path; pub const codegen_embed = build_options.codegen_embed; diff --git a/src/windows-app-info.rc b/src/windows-app-info.rc index 7537bf1db6..36f8738cf7 100644 --- a/src/windows-app-info.rc +++ b/src/windows-app-info.rc @@ -24,7 +24,7 @@ BEGIN VALUE "InternalName", "bun\0" VALUE "OriginalFilename", "bun.exe\0" VALUE "ProductName", "Bun\0" - VALUE "ProductVersion", "@Bun_VERSION_WITH_TAG@\0", + VALUE "ProductVersion", "@Bun_VERSION_WITH_TAG@\0" VALUE "CompanyName", "Oven\0" VALUE "LegalCopyright", "https://bun.com/docs/project/licensing\0" END diff --git a/test/bundler/bun-build-compile.test.ts b/test/bundler/bun-build-compile.test.ts index 555aff4ae9..8004a7bb78 100644 --- a/test/bundler/bun-build-compile.test.ts +++ b/test/bundler/bun-build-compile.test.ts @@ -48,16 +48,6 @@ describe("Bun.build compile", () => { }, }), ).toThrowErrorMatchingInlineSnapshot(`"Unknown compile target: bun-invalid-platform"`); - - expect(() => - Bun.build({ - entrypoints: [join(dir, "index.js")], - compile: { - target: "bun-windows-arm64", - outfile: join(dir, "invalid-app"), - }, - }), - ).toThrowErrorMatchingInlineSnapshot(`"Unsupported compile target: bun-windows-arm64"`); }); test("compile with relative outfile paths", async () => { using dir = tempDir("build-compile-relative-paths", {