Skip to content

Complete native Windows ARM64 build support - #1

Closed
RyanEwen wants to merge 18 commits into
masterfrom
feature/windows-arm64
Closed

Complete native Windows ARM64 build support#1
RyanEwen wants to merge 18 commits into
masterfrom
feature/windows-arm64

Conversation

@RyanEwen

Copy link
Copy Markdown
Owner

Fills the remaining gaps so a native Windows-on-ARM64 target configures, compiles, and ships. Most plumbing already existed upstream (deps-windows.cmake ARM64 platform, Boost winfib, OpenCV IPP-off, OpenEXR arch, prebuilt GMP/MPFR win_arm64 libs, copy_dlls ARM64 branch, build_win.bat -ARCH support).

Source (compile blockers): StackWalker.cpp (_M_ARM64 branch, was #error), BaseException.cpp (ARM64 CONTEXT uses Cpsr not EFlags, + register dump), Int128.hpp (guard x64-only _mul128 pragma).

Deps: OpenSSL.cmake (VC-WIN64-ARM), FindGLEW.cmake (ARM64 branch).

CI: build_all.yml adds {os: windows-11-arm, arch: arm64}; build_check_cache/build_deps/build_bambu handle the arm runner (VS 17 2022 generator — the arm image has no VS 2026 — with -A ARM64, runtime-resolved Win10 SDK, arch-suffixed artifacts).

All ARM64 logic is gated; x64/x86/macOS/Linux paths are unchanged. Opened to exercise the new windows-11-arm CI job.

RyanEwen added 18 commits July 17, 2026 14:40
BambuStudio already carried most Windows-on-ARM64 plumbing (deps-windows.cmake
DEP_PLATFORM/wxWidgets ARM64, Boost winfib, OpenCV IPP-off, OpenEXR arch,
prebuilt GMP/MPFR win_arm64 libs, bambustudio_copy_dlls ARM64 branch,
cross-compile detection, and full -ARCH support in build_win.bat). This fills
the remaining gaps so an ARM64 target actually configures, compiles, and ships.

Source (compile blockers on ARM64):
- StackWalker.cpp: add _M_ARM64 branch (was #error "Platform not supported!")
- BaseException.cpp: ARM64 CONTEXT has no EFlags; use Cpsr and add an ARM64
  register dump for crash diagnostics
- Int128.hpp: guard the x64-only _mul128 #pragma intrinsic (ARM64 already uses
  __umulh); silences a benign MSVC warning

Dependencies:
- OpenSSL.cmake: configure VC-WIN64-ARM (not VC-WIN64A) for Windows ARM64
- FindGLEW.cmake: ARM64 arch branch for the GLEW_ROOT binary-dist fallback

CI (folds arm64 into the existing Windows build without touching the x64 path):
- build_all.yml: add {os: windows-11-arm, arch: arm64} to the matrix
- build_check_cache.yml: startsWith(windows) so arm64 gets the Windows cache
  path/shell (distinct cache key comes from inputs.os)
- build_deps.yml / build_bambu.yml: ARM64 deps + app build steps using the
  Visual Studio 17 2022 generator (the arm runner has no VS 2026) with -A ARM64,
  runtime-resolved Win10 SDK, and arch-suffixed artifacts

All ARM64 logic is gated; the x64/x86/macOS/Linux paths are unchanged.
build_win.bat passes -A arm64 (lowercase) while CI passes -A ARM64; CMake keeps
CMAKE_GENERATOR_PLATFORM verbatim (no case normalization), so an uppercase-only
STREQUAL/MATCHES check missed the local build_win.bat path. Match ARM64 case-
insensitively and also honour CMAKE_SYSTEM_PROCESSOR on native ARM64 hosts,
matching the pattern GMP/MPFR/OpenCV already use.
The ARM64 dep prefix ships MPFR 4.x as libmpfr-6.lib, but CGAL's FindMPFR
searches a fixed name list (mpfr, libmpfr-4, libmpfr-1) that predates the -6
ABI naming, so the app configure failed with 'Could NOT find MPFR' (observed
on the windows-11-arm CI runner; GMP was found because libgmp-10 is in CGAL's
FindGMP list). Install an aliased copy under the legacy libmpfr-4.lib name;
an import library's filename does not affect runtime binding - it still
references mpfr-6.dll internally, which is installed to bin/.
OpenCVConfig.cmake's dispatcher matches CMAKE_GENERATOR_PLATFORM against
'ARM64' case-sensitively (build_win.bat passes lowercase arm64), and its
MSVC_VERSION->runtime table predates VS2022 17.10+ (19.4x), so on ARM64 it
computed ARCH=x64/RUNTIME=vc14 and failed with OpenCV_FOUND=FALSE despite the
deps prefix containing ARM64/vc17/staticlib. The dispatcher only honours
pre-set values when BOTH OpenCV_ARCH and OpenCV_RUNTIME are defined, so pin
them together for any spelling of an ARM64 target. The existing >=1950 vc17
hint (x64/VS2026) is unchanged.
minih264e.h defined MINIH264_ONLY_SIMD for _M_ARM64 ('arm64 always have
neon'), but its NEON implementation is only enabled for __ARM_NEON/__aarch64__
- GCC/Clang macros that MSVC never defines - so MSVC ARM64 fell through to
'#error MINIH264_ONLY_SIMD used, but SSE/NEON not enabled'. Keep the portable
C path available on MSVC ARM64; GCC/Clang arm64 (macOS) still uses NEON.
bambulab's ffmpeg_prebuilts 7.0.2_msvc.zip contains x64-only import libs and
DLLs; on ARM64 the link of BambuStudio.exe failed with unresolved av_*/sws_*
externals from AVVideoDecoder.obj (the import libs are machine-type x64). Pin
BtbN's FFmpeg-Builds winarm64 gpl-shared 7.1 autobuild instead: same
bin/lib/include layout and identical library majors (avcodec-61, avutil-59,
swscale-8), verified machine-type ARM64. x64 continues to use the bambulab
package unchanged.
Building x64 or ARM64EC targets on a native ARM64 host misrouted several arch
checks: the CMAKE_SYSTEM_PROCESSOR fallback (host CPU) fired even when the
generator platform (-A) said otherwise, staging ARM64 GMP/MPFR/FFmpeg blobs
into x64 dep bundles and selecting ARM64 OpenCV/runtime-DLL layouts for
non-ARM64 app targets. Give CMAKE_GENERATOR_PLATFORM precedence everywhere
(GMP, MPFR, OpenSSL, FFMPEG, bambustudio_copy_dlls, libslic3r OpenCV hints),
falling back to the host processor only when no platform is set.

ARM64EC groundwork: deps-windows.cmake maps DEP_ARCH=ARM64EC to platform
ARM64EC, and the libslic3r OpenCV hint selects the x64 dependency layout for
ARM64EC app builds (EC links the x64 dep set; EC processes load x64 DLLs,
which is what enables the closed-source x64 Bambu network plugin to work
inside an otherwise-native ARM64 build).
Boost 1.84's libs/context CMake derives its architecture from the host
processor, so an -A x64 deps build on a Windows-on-ARM machine detected
'arm64 / armasm' and failed configure (armasm absent from the x64 toolchain
env). Pass BOOST_CONTEXT_ARCHITECTURE=x86_64 explicitly for X64 targets, and
use the assembler-free winfib implementation for ARM64EC targets.
On ARM64EC the x86 SIMD headers (immintrin.h and friends) error out unless
included via <intrin.h>, which sets up the softintrin emulation layer first.
Several bundled libraries (eigen, imgui, clipper2, tinybvh, libigl, minih264)
include them directly, so add /FIintrin.h globally for ARM64EC instead of
patching each library.
Some x86 intrinsics used by bundled code (e.g. _mm_cvtsd_si64 in Clipper2)
have no native ARM64EC lowering and compile to calls into the softintrin
software-emulation library. MSBuild adds it for its own project types but not
for CMake-generated ones, leaving unresolved '(EC Symbol)' externals at link.
clipper.engine.cpp swaps fmin/fmax/nearbyint for SSE2 intrinsics whenever
_M_X64 is defined, but ARM64EC (which also defines _M_X64) has no native
lowering for _mm_cvtsd_si64 and softintrin.lib provides no fallback, leaving
an unresolved '(EC Symbol)' external. The standard functions compile to native
ARM64 rounding/min/max instructions on EC, so exclude it there.
oneTBB 2021.5 hard-codes /GL for MSVC release builds; x64 LTCG objects cannot
participate in an ARM64EC link (C1905). It also assumes TSX transactional-
memory intrinsics exist whenever _M_X64 is defined, but ARM64EC defines
_M_X64 and softintrin cannot emulate _xbegin/_xend/_xabort, so they fail to
link when TBB itself is compiled as ARM64EC. Apply both fixes via an
idempotent PATCH_COMMAND script (the version knobs for these arrived in
later oneTBB releases).
The unconditional /Zi makes every target's compiles share a per-target .pdb;
under Ninja's parallelism that fails with C1041 (the VS generator serializes
PDB access via /FS+mspdbsrv, Ninja does not) and defeats compiler-launcher
caches like sccache. Use /Z7 (debug info embedded in objects; the linker
still emits the final .pdb) and only for RelWithDebInfo/Debug: embedding into
every object of a Release build pushes libslic3r_gui.lib past the 4 GB .lib
format limit (LNK1248), and plain Release omits debug info under standard
CMake semantics anyway. VS-generator builds keep /Zi unchanged.
Configuring deps with -A ARM64EC now produces an EC bundle without manual
steps: deps-windows.cmake injects the EC compile flags into every CMake-based
dep (restating the MSVC defaults - CMAKE_ARGS replaces rather than appends -
plus /FIintrin.h for direct x86-SIMD-header includes and /wd4996 /wd4005 for
the define-before-include idiom /FI breaks); Boost excludes json/cobalt on EC
(ryu needs __shiftright128, which has no EC lowering); TBB gains a link-time
TSX stub TU (rtm code calls _xbegin unconditionally but is unreachable under
emulation); OpenSSL builds its x64 flavor under the x64 cross environment via
a generated wrapper (x64 static libs link into EC images); OpenCV treats EC
like arm64 (no IPP); JPEG disables SIMD deterministically. Binary-only deps
(GMP/MPFR/FFmpeg) keep their x64 artifacts, which EC processes load natively
through the emulation layer.
Adds {os: windows-11-arm, arch: arm64ec} to the matrix. The two Windows-on-ARM
variants share a runner label, so the deps cache key now includes the arch
(one-time cache rebuild for existing arm64 keys). The deps and app steps are
parameterized to pass -A ARM64EC for the new variant, and artifacts are
suffixed with the arch (BambuStudio_Windows_<ver>_arm64ec_portable.zip).

The arm64ec build is the fully-featured one: native ARM64 code with the
x64-compatible ABI, able to load Bambu's closed x64 network plugin in-process
(cloud login, device management, camera). The pure arm64 build remains for
comparison and as the maximum-native variant.
The forced intrin.h include makes cl warn C4163 for x86-only intrinsics
(__rdtsc, _mm_mfence) that softintrin provides at link time; oneTBB's default
TBB_STRICT=ON promotes those to errors on the ARM64EC bundle build.
The in-repo ARM64EC deps bundle installs OpenCV under ARM64/vc17 (its recipe
treats EC like arm64), while an x64 dependency prefix provides x64/vc17; an
ARM64EC app links either flavor, so probe the prefix for which layout exists
instead of assuming x64.
TBB_STRICT=OFF and the ARM64EC patch were applied on every platform. On macOS
that regressed the deps build: oneTBB's non-strict path rewrites the compiler
flags and mangles the macOS -Werror=<availability> options into bare
'=partial-availability' tokens, which clang rejects as missing files (Linux is
unaffected - it has no such flags). Both changes are only needed for the MSVC
ARM64EC build, so gate them behind if(MSVC); macOS/Linux now build TBB exactly
as before. Confirmed against CI history: macOS deps were green with the patch
alone (run 29647625275) and only went red once TBB_STRICT=OFF landed.
@RyanEwen

Copy link
Copy Markdown
Owner Author

Superseded. The Windows ARM64 and ARM64EC build support is now proposed upstream as bambulab#11599 (clean single-commit history), and the follow-on launch change is tracked in #2.

@RyanEwen RyanEwen closed this Jul 19, 2026
@RyanEwen
RyanEwen deleted the feature/windows-arm64 branch July 19, 2026 00:58
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.

1 participant