feat: native Windows ARM64 (Snapdragon X Elite) support — full feature parity#422
Open
abehrman wants to merge 22 commits into
Open
feat: native Windows ARM64 (Snapdragon X Elite) support — full feature parity#422abehrman wants to merge 22 commits into
abehrman wants to merge 22 commits into
Conversation
- Detect ARM64 in deps/CMakeLists.txt and deps-windows.cmake; set DEPS_ARCH=arm64 and DEP_PLATFORM=ARM64 / wxWidgets TARGET_CPU=ARM64 - OpenSSL: use VC-WIN64-ARM arch on ARM64 Windows - FindGLEW: prevent Win32 fallthrough on ARM64 - build_release_vs2022.bat: accept 'arm64' arg; pass -A ARM64 to cmake - Add SLIC3R_ENABLE_STEP option (default OFF on ARM64 Windows) to gate OpenCASCADE/STEP support; OCCT 7.6 has no Windows ARM64 support - Gate GMP/MPFR DLL copies and OCCT deps behind SLIC3R_ENABLE_STEP / ARM64 checks in CMakeLists.txt - Guard Format/STEP.hpp and its Model.hpp include with SLIC3R_ENABLE_STEP - CGAL.cmake: build without GMP/MPFR on ARM64 (CGAL_DISABLE_GMP=ON) - Add .github/workflows/build_windows_arm64.yml: native build on windows-11-arm runner; installs MSYS2 clangarm64 GMP/MPFR packages, generates MSVC-compatible import libs via llvm-dlltool, caches deps, uploads artifact Known limitations (follow-up work): - STEP import disabled (needs OCCT 7.7+ for ARM64) - Exact-arithmetic CGAL ops unavailable (MeshBoolean uses floating-point) - GMP/MPFR provided by CI MSYS2; local arm64 builds need manual setup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the broken llvm-dlltool/dumpbin PowerShell approach with MSYS2's native gendef + dlltool running in the CLANGARM64 shell. - gendef produces a proper .def from the mingw DLL - dlltool -m arm64 produces a COFF import .lib MSVC link.exe accepts - Use cygpath to convert $GITHUB_WORKSPACE instead of hardcoded path - Add mingw-w64-clang-aarch64-binutils to MSYS2 install (provides dlltool) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gendef is not in mingw-w64-clang-aarch64-binutils. Use objdump -p
(which IS in binutils) to parse PE DLL export tables instead:
objdump -p <dll> | awk '/^\[/{print $NF}' -> EXPORTS .def
dlltool -m arm64 -D <dll> -d <def> -l <lib>
No additional packages needed beyond binutils.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CLANGARM64 is LLVM-based — GNU objdump/dlltool don't exist there.
Switch to LLVM equivalents that ship with the clang toolchain:
llvm-readobj --coff-exports <dll> | awk '/Name: /{print $2}'
llvm-dlltool -m arm64 -D <dll> -d <def> -l <lib>
Also drop the explicit binutils install (not needed, not GNU).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
llvm-readobj/llvm-dlltool are not transitive deps of the GMP package. Add mingw-w64-clang-aarch64-llvm explicitly. Also add a diagnostic listing /clangarm64/bin/llvm-* so we can see what's actually available if future tool lookups fail. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MPFR 4.x ships as libmpfr-6.dll in MSYS2 CLANGARM64 (soname bump),
not libmpfr-4.dll. Discover the actual filename with a glob, generate
the import lib for whatever is present, then copy to libmpfr-4.{dll,lib}
so cmake's win-arm64 blob lookup finds the expected names.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ect builds CMake 4.x dropped compatibility with cmake_minimum_required(VERSION < 3.5). Some bundled deps have old cmake minimums. Pass CMAKE_POLICY_VERSION_MINIMUM=3.5 via ExternalProject CMAKE_ARGS in Snapmaker_Orca_add_cmake_project (all three branches) and to the top-level deps configure in the ARM64 CI workflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OpenEXR 2.5.5 cmake SSE2 detection succeeds on MSVC 14.44 ARM64 (emmintrin.h now lists ARM64 as supported) but IlmImf SIMD code fails to compile. Force all SSE/SIMD flags off on arm64: OPENEXR_IMF_HAVE_SSE2=OFF OPENEXR_IMF_HAVE_SSSE3=OFF ILMBASE_HAVE_SSE=OFF ILMBASE_FORCE_DISABLE_INTEL_SSE=ON Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ARM64 CMAKE_ARGS cannot override a variable already in the cmake cache, so the SSE2 auto-detection was silently winning. Switch to a direct ExternalProject_Add for Windows ARM64 using CMAKE_CACHE_ARGS (which sets with FORCE), suppressing all SIMD detection flags unconditionally: OPENEXR_IMF_HAVE_SSE2/SSSE3/SSE4_1 = OFF ILMBASE_HAVE_SSE / ILMBASE_FORCE_DISABLE_INTEL_SSE = ON Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CMAKE_CACHE_ARGS/CMAKE_ARGS cannot override check_cxx_source_compiles results because the detection test runs on the x64 configure-phase host (where emmintrin.h compiles fine), then the ARM64 compile fails. Only reliable fix: patch the OpenEXR CMakeLists.txt files *before* cmake runs to FORCE all SSE variables to OFF via a cmake -P script applied as PATCH_COMMAND. Covers IlmImf and IlmBase/Half CMakeLists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OpenEXR SSE patch worked (no more C1189). Next blocker: Boost.Context fails with "Could not find cmake module file: CMakeASM_ARMASMLinkerInformation.cmake". Root cause: the windows-11-arm runner ships CMake 4.x, which (a) removed pre-3.5 policy compatibility and (b) has incomplete ASM_ARMASM linker information modules that Boost.Context needs for ARM64 assembly. CLAUDE.md documents the project requires CMake <= 3.31 on Windows. Pin the runner to CMake 3.31.6 (windows-arm64) before any configure step, addressing the root cause behind multiple CMake-4 symptoms at once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two root causes found in the 20-min run:
Boost: Boost.Context's fcontext impl assembles .asm via armasm64, which
hits a CMake ASM_ARMASM linker-module bug under the VS generator. The
slicer references neither boost::context nor boost::coroutine (0 hits in
src/), so exclude context|coroutine|coroutine2 on ARM64.
OpenEXR: the earlier CMake-variable patch was ineffective because the SSE
decision is hard-coded in OpenEXR/IlmImf/ImfSimd.h:
#if defined __SSE2__ || (_MSC_VER >= 1300 && !_M_CEE_PURE)
#define IMF_HAVE_SSE2 1
The _MSC_VER arm is true on ARM64 MSVC too, forcing <emmintrin.h> (x86
only) -> C1189. Rewrite the patch to add an x86-arch guard to that #if,
which is the only thing all downstream SSE paths key off of.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…g it Excluding Boost.Context broke Boost.Asio, whose link interface hard-requires the Boost::context target (stackful coroutines) -- "target was not found". Asio is needed by the slicer, so it can't be dropped. Instead, switch Boost.Context to the winfib implementation (Windows Fiber API) on ARM64 via BOOST_CONTEXT_IMPLEMENTATION=winfib. This builds Context without any armasm64 assembly (avoiding the CMake ASM_ARMASM linker-module bug) while keeping the Boost::context target intact for Asio. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… GMP
All deps now build; failure moved to the slicer configure:
"Could NOT find GMP" -- CGAL's installed config does find_dependency(GMP),
which we'd skipped installing on ARM64.
The CI workflow already stages real MSYS2 clangarm64 GMP/MPFR blobs into
deps/{GMP,MPFR}/.../win-arm64 + headers. GMP.cmake / MPFR.cmake's MSVC
branch copies win-${DEPS_ARCH} into the dep prefix exactly like x64, so the
right fix is to STOP skipping GMP/MPFR/CGAL on ARM64 and let that path run.
This also restores real exact-arithmetic CGAL (no CGAL_DISABLE_GMP needed).
- deps/CMakeLists.txt: always include GMP/MPFR/CGAL (drop arm64 skip)
- deps/CGAL/CGAL.cmake: drop arm64 branch; always DEPENDS dep_GMP dep_MPFR
- CMakeLists.txt: drop arm64 gating on GMP/MPFR DLL copies
- workflow: rename libmpfr-6.dll -> libmpfr-4.dll BEFORE generating the
import lib so the baked-in runtime DLL name is libmpfr-4.dll (previously
the .lib referenced libmpfr-6.dll, which we never ship -> runtime load fail)
OCCT/STEP remains disabled on ARM64 (no OCCT 7.6 ARM64 support).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
All deps now build and install (incl. real GMP/MPFR); slicer compile reached. Two ARM64 source errors: - Int128.hpp: _mul128 is an x64-only MSVC intrinsic but was guarded by _WIN64 (also true on ARM64). Guard on _M_X64 so ARM64 uses the existing portable 64x64->128 multiply fallback. - imgui_widgets.cpp TextCentered(): va_start(vaList, &text) passed the address of the parameter instead of the parameter itself. MSVC x64's va_start macro tolerated it; ARM64's does not (C2101/C2102/C2059). Fixed to va_start(vaList, text). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
libslic3r build failed with "syntax error: identifier 'ImportStepProgressFn'" because Model.hpp/Model.cpp reference STEP types that my earlier #ifdef had removed. STEP/OCCT is woven through libslic3r and the GUI (StepMeshDialog, Plater, emboss gizmo), so guarding every call site is impractical. Instead, keep the full public API always declared and provide OCCT-free stub implementations when OCCT is unavailable (Windows ARM64 / OCCT 7.6): - STEP.hpp: always declares ImportStepProgressFn/StepIsUtf8Fn typedefs, the Step class, load_step and StepPreProcessor; only OCCT members/types are guarded by SLIC3R_ENABLE_STEP. - STEP_stub.cpp: stub Step/load_step/StepPreProcessor (compiled when STEP off). - TextShape.cpp / svg.cpp: guard the OCCT body; stub the OCCT-free public functions (init_occt_fonts, load_text_shape, get_occt_fonts_maps, load_svg) in the #else branch. Their headers are already OCCT-free. - libslic3r/CMakeLists.txt: compile STEP.cpp when enabled, STEP_stub.cpp when not. All call sites and the GUI compile and link unchanged; STEP import, SVG-to-3D and text emboss simply report unavailable on ARM64. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The whole slicer + GUI now compile; failure is in the app executable's dev-utils crash reporter, which hardcoded x86/x64 CPU internals: - StackWalker.cpp: added an _M_ARM64 branch (IMAGE_FILE_MACHINE_ARM64, CONTEXT Pc/Fp/Sp) so it no longer hits #error "Platform not supported!". - BaseException.cpp: ContextRecord->EFlags is x86/x64-only (C2039 on ARM64). Guard it and use Cpsr on ARM64; add an _M_ARM64 register dump (PC/SP/FP/LR/Cpsr) to ShowRegistorInformation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The whole slicer + GUI compiled; the executable link failed with LNK1104 "cannot open file 'JPEG::JPEG.lib'". When I wrapped the OCCT section in if(SLIC3R_ENABLE_STEP), I accidentally removed the adjacent find_package(JPEG REQUIRED), so the JPEG::JPEG imported target was never defined and CMake emitted it as a literal library name. libslic3r links JPEG::JPEG unconditionally, so restore the find_package outside the guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The JPEG fix cleared; the executable link then failed with 198 unresolved externals, ALL ippicv* symbols. Intel IPP / IPP-ICV is x86/x64 only — there is no ARM64 build — but OpenCV.cmake forced WITH_IPP=ON for all MSVC targets, so OpenCV's code referenced ippicv routines that don't exist on ARM64. Gate WITH_IPP=ON to non-arm64 MSVC; disable it on ARM64 (and keep it on for x64 where it provides the SIMD-accelerated image routines). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…uild
The ARM64 build, link, install and artifact upload all SUCCEED, but the job
was marked failed because the 'Post Cache deps' step re-evaluates the cache
key, and hashFiles('deps/**') scans the entire built dependency tree
(millions of files) and exceeds the 120s hashFiles limit.
Hash only the dependency cmake definitions with fixed-depth globs
(deps/CMakeLists.txt, deps/*.cmake, deps/*/*.cmake). This is fast, correctly
invalidates on dependency-config changes, and lets the deps cache finally
persist (so subsequent builds skip the ~24min dependency rebuild).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6 tasks
The base ARM64 build is validated working on real Snapdragon X Elite hardware (PR Snapmaker#422). Now restore the OCCT-backed features (STEP import, SVG-to-3D, text emboss) that were stubbed out. Because all OCCT usage is gated behind SLIC3R_ENABLE_STEP, re-enabling is just two flips plus building the dep: - deps/CMakeLists.txt: build dep_OCCT on ARM64 (drop the arm64 skip) - CMakeLists.txt: SLIC3R_ENABLE_STEP defaults ON on all platforms - workflow: pass -DSLIC3R_ENABLE_STEP=ON This is an empirical test of whether OCCT 7.6 compiles on Windows ARM64 MSVC. If it fails (most likely on SSE intrinsics, as OpenEXR did), the errors will pinpoint what to patch or whether to bump OCCT to 7.8+. The OCCT-free stubs remain in place and reactivate automatically if STEP is turned off again. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…picker) Surfaces the printer's IP address (MachineObject::dev_ip, populated from local network discovery) so users can read it without digging through the router or printer screen. - Device tab: add an "IP: x.x.x.x" readout in the monitoring page title bar, updated each refresh in StatusPanel::update(); hidden when no IP is known. - Send-to-printer device picker: append the IP to each device entry when known. Implements the UI side of Snapmaker#445. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
Adds native Windows on ARM64 build support (Snapdragon X Elite and other WoA devices) for Snapmaker OrcaSlicer. Produces a fully native ARM64 binary — not x64-under-emulation — via a new GitHub Actions workflow on the
windows-11-armhosted runner.Confirmed working on physical Snapdragon X Elite hardware (launches and slices). CI artifact:
Snapmaker-OrcaSlicer-Windows-ARM64(~140 MB).✅ Full feature parity with x64
This build is feature-complete — there are no ARM64 feature gaps:
SLIC3R_ENABLE_STEPis retained as a clean build toggle (default ON). When off, OCCT-free stubs keep the app building/linking — useful for any future platform lacking OCCT — but ARM64 ships with it ON and full OCCT support.How it's built (CI)
.github/workflows/build_windows_arm64.ymlruns onwindows-11-armand:clangarm64, generating MSVC import libs viallvm-dlltoolKey changes
DEPS_ARCH=arm64→ARM64platform / wxWidgetsTARGET_CPU=ARM64; OpenSSLVC-WIN64-ARM; FindGLEW ARM64 path;build_release_vs2022.bat arm64winfibimplementation (avoids armasm); OpenEXRImfSimd.hSSE2 guard fixed; OpenCV built with IPP off (Intel IPP is x86/x64-only); GMP/MPFR consumed from staged arm64 blobs; OCCT/OpenVDB/CGAL all build nativelyInt128.hpp_mul128guarded to x64 (ARM64 uses the portable path); imguiva_startbug fixed; crash reporter (StackWalker,BaseException) made ARM64-awarehashFilesdoesn't time out post-buildTesting
windows-11-armFor maintainers — distribution checklist
🤖 Generated with Claude Code