Complete native Windows ARM64 build support - #1
Closed
RyanEwen wants to merge 18 commits into
Closed
Conversation
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.
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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_ARM64branch, was#error), BaseException.cpp (ARM64 CONTEXT uses Cpsr not EFlags, + register dump), Int128.hpp (guard x64-only_mul128pragma).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-armCI job.