Skip to content

feat: Add Windows ARM64 (MSVC) support#2050

Open
FixFlare wants to merge 3 commits intoopenfl:8.4.0-devfrom
FixFlare:windows-arm64-support
Open

feat: Add Windows ARM64 (MSVC) support#2050
FixFlare wants to merge 3 commits intoopenfl:8.4.0-devfrom
FixFlare:windows-arm64-support

Conversation

@FixFlare
Copy link
Copy Markdown

Add Windows ARM64 build support

Description

This PR adds native compilation support for Windows ARM64 targets, allowing Lime projects to be cross-compiled for devices with ARM64 processors (Snapdragon X Elite laptops, Surface Pro X, Windows Dev Kit 2023, etc).

Usage follows the same convention as other platforms:

lime rebuild windows -arm64          # Rebuild Lime native libraries for ARM64
lime build windows -arm64            # Build a project targeting ARM64
lime rebuild windows -arm64 -static  # Static linking (single .exe output)

This should match the -arm64 flag behavior on macOS, iOS, and Android.

Prerequisites

Developers cross-compiling from x64 must install the MSVC ARM64 build tools via the Visual Studio Installer:

  • Open Visual Studio Installer → Modify → Individual Components
  • Check "MSVC Build Tools for ARM64/ARM64EC (Latest)"

Changes

Tools

tools/platforms/WindowsPlatform.hx

  • Added isArm flag to detect Architecture.ARM64 targets
  • Updated output directory logic to use WindowsArm64 paths (consistent with MacArm64, LinuxArm64)
  • Adjusted the rebuild() method which was unconditionally passing -DHXCPP_M64 for all 64-bit targets, ignoring the -arm64 flag entirely. Now it passes -DHXCPP_ARM64 when ARM64 is targeted
  • Injects -DHXCPP_ARM64 into the hxcpp compiler flags for both HL and cpp target types

tools/CommandLineTools.hx

  • Added WindowsArm64/ to the Neko module loader path resolution for Windows ARM64 hosts (matching the existing MacArm64/ and LinuxArm64/ pattern)
  • Updated the -arm64 help text to include windows alongside mac|ios|android

Native dependencies

project/Build.xml

  • Decoupled LIME_OPENALSOFT from the static_link restriction: Removed unless="static_link" from the desktop platform OpenAL Soft selection logic. This allows static binaries to use the more stable OpenAL Soft backend instead of being forced into MojoAL. Prior to this change, running a Windows ARM build on Linux via wine would freeze.
  • Implemented Priority-Based Audio Logic:
    • Updated LIME_MOJOAL to only trigger for static builds unless="LIME_OPENALSOFT || LIME_OPENAL".
    • This ensures that if a stable/native OpenAL backend is available (like OpenAL Soft for Windows ARM64), it is selected over the MojoAL shim.
    • Added an unset safety for LIME_OPENALSOFT when LIME_MOJOAL is explicitly selected (e.g., for Switch) to prevent duplicate symbol linker errors.
  • Consolidated the selection of the generic LIME_OPENAL flag to trigger based on either backend, this should simplify downstream feature detection in the build script.

project/lib/custom/openal/include/config-windows-arm64.h [NEW]

  • New OpenAL Soft configuration header for Windows ARM64 targets
  • Defines appropriate API attributes, available backends (WinMM, DirectSound, WaveFile), and processor feature flags

project/lib/custom/openal/include/config.h

  • Added conditional include of config-windows-arm64.h when HXCPP_ARM64 is defined on Windows

project/lib/openal-files.xml

  • Excluded mixer_neon.cpp on Windows (unless="windows"). This file uses GCC/Clang-specific NEON struct initialization syntax ({ a, b, c, d } on float32x4_t) that MSVC rejects with error C2078: too many initializers. OpenAL cleanly falls back to mixer_c.cpp, which MSVC auto-vectorizes for ARM64

project/lib/custom/pixman/config.h

  • Disabled USE_SSE2, USE_SSE3, and X86_MMX when HXCPP_ARM64 is defined on Windows. These are x86-specific SIMD intrinsics that are unavailable on ARM64

project/lib/custom/mojoal/mojoal.c [NEW]

  • Added a patched version of mojoal.c to resolve MSVC ARM64 compatibility issues:
    • Added _alloca shim for MSVC.
    • Fixed ARMv8 NEON detection to exclude MSVC (forcing the scalar path which MSVC auto-vectorizes, avoiding MSVC-incompatible GCC vector operators).
    • This allows the project/lib/mojoal submodule to remain clean and untouched.

project/lib/mojoal-files.xml

  • Updated to use the custom patched mojoal.c specifically when building for ARM64 (if="HXCPP_ARM64"), ensuring the build succeeds without requiring modifications to subprojects.

Testing

  • lime rebuild tools — CLI rebuilds successfully
  • lime rebuild windows -arm64 -verbose — Native libraries (ndll) compile and link for ARM64 with zero errors
  • lime rebuild windows -arm64 -static -verbose — Static library variant compiles successfully
  • Verified output goes to ndll/WindowsArm64/ directory (not Windows64/)
  • Verified linker uses -machine:ARM64 (not -machine:x64)
  • Existing lime rebuild windows -verbose (x64) is unaffected
  • Tested my WIP game and was able to run on Windows ARM w/ sound working.

Notes

  • The NEON-related changes (mixer_neon.cpp exclusion, mojoal.c fix) only affect Windows ARM64 builds. All other platforms (Linux ARM64, macOS ARM64, iOS, Android) continue to use their existing NEON code paths via GCC/Clang, which fully support the vector subscript syntax
  • No changes that should affect Raspberry Pi, Android, macOS, iOS, or standard Windows x64 builds

@joshtynjala
Copy link
Copy Markdown
Member

Decoupled LIME_OPENALSOFT from the static_link restriction: Removed unless="static_link" from the desktop platform OpenAL Soft selection logic. This allows static binaries to use the more stable OpenAL Soft backend instead of being forced into MojoAL. Prior to this change, running a Windows ARM build on Linux via wine would freeze.

Just adding some additional context here. As I understand it, this restriction exists for legal reasons, rather than technical reasons. OpenAL-Soft is LGPL licensed, which can be dynamically linked without affecting the license of an application. However, if you want to statically link it, the application must be LGPL too, or the application must be distributed with symbols for relinking with a modified version of the library. That's not a requirement that we want to force on all users of Lime.

@tobil4sk
Copy link
Copy Markdown
Member

The mojoal.c change should happen upstream rather than by overriding it here

Reverted manual patches to mojoal.c to maintain clean submodules.
Fixed OGG decoder metadata corruption on ARM64-MSVC by applying the /Zp8 alignment flag in the build script.
Updated Build.xml to prioritize MojoAL for static ARM64 builds to satisfy legal requirements.
@FixFlare
Copy link
Copy Markdown
Author

FixFlare commented Apr 16, 2026

Hey guys - thanks for the feedback on this.

I hadn't considered any of the legal aspects of this. Trying to get mojoal working though really sent me down a rabbit hole with debugging the sdl sound playback.

In my original post I mentioned needing to force OpenAL Soft because static ARM64 builds would freeze on launch via Wine

After adding way too many log statements, I found the true cause of that freeze - it was actually a memory alignment mismatch in the OGG decoder (stb_vorbis) on ARM64-MSVC. The structs were being padded incorrectly which caused the sample_rate to be read back as 0. That 0 was what was actually hanging the audio initialization and making it look like a MojoAL stall. (divide by 0 problem)

@tobil4sk: I reverted all manual source-code patches to mojoal.c since I found the true cause of the freeze and was able to resolve the alignment mismatch by just using a /Zp8 compiler flag in the sdl_sound build script. This ensures the structs are packed correctly on ARM64 without tainting the submodule code.

@joshtynjala: Now that the decoder bug is resolved and MojoAL is stable, I updated the logic to prioritize MojoAL for static ARM64 builds. I believe this should resolve the legal issue but let me know if you believe otherwise.

Comment thread project/lib/custom/pixman/config.h Outdated
Copy link
Copy Markdown

@MRK2009 MRK2009 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants