Tickering with Node.js Core on ARM64 Windows
A while back, I wrote about Building Node.js on Windows using the new ClangCL support, which was done on an actual x64 Windows machine. While on vacation with my ARM64 MacBook, I installed Parallels to play Age of Empires II in an ARM64 Windows VM (which worked great by the way). Then I took the opportunity to test my hobby project in Node.js in the VM. The building process was smoother than I expected, though there were still some gotchas.
I also noticed that the steps I use when hacking on Node.js on Windows tend to differ quite a lot from what’s recommended in the Node.js documentation, because I try to skip as many unnecessary commands as possible to reduce the wait time. I haven’t been able to upstream my tips, as they don’t apply universally, but I figure a write-up may still be useful for those who are also tinkering with Node.js on Windows, especially on ARM64, so here it is.
Installing the Toolchain
Installing Visual Studio
I ended up installing VS 2026 from the official website without realizing it, and anticipated problems because Node.js is only tested up to VS 2022 in the CI, but it worked just fine.
After Node.js 25, the Clang+LLVM toolchain is now mandatory (V8 has dropped support for MSVC and now newer versions of V8 tend to use syntaxes that MSVC cannot parse), so the following components must be selected in the installer:
- “Desktop development with C++” workload
- C++ Clang Compiler for Windows
- MSBuild support for LLVM toolset
Installing Git for Windows
Just install from Git - Install for Windows - they already offer ARM64 builds.
Installing Python
This is currently the tricky part on ARM64 Windows.
I initially just used the official installer manager from the Python downloads page, which turned out to install the x64 version by default on ARM64 Windows because ARM64 Windows support is still experimental. However, using x64 Python to build Node.js would confuse the build scripts - which was why I initially ended up using an x64 host toolchain running under emulation to cross-compile for ARM64, even when I was already on ARM64 Windows. This setup isn’t utterly broken (it worked for statically linked builds), but it’s slower, and not all Node.js build targets support cross-compilation on Windows - for example, I only realized that I was using the x64 toolchain when I noticed that linking dynamically to libnode.dll failed, because the manifest building tool built for x64 cannot load the cross-compiled ARM64 DLL properly.
While the Python Installer Manager is expected to start installing ARM64 Python by default on ARM64 Windows in October 2026, until then, the simplest workaround I found was to install “Python Install Manager” from the Microsoft Store, and then run this from cmd or PowerShell:
1 | py install 3-arm64 |
Then verify that the installed Python is indeed ARM64 by entering the Python REPL. If it says ARM64 then it’s good.
Tools to Skip
On ARM64 Windows, I skipped installing the following tools that I normally install on x64 Windows:
- The NetWide Assembler - that’s for x64. At the time of writing, no one seems to be getting the Node.js build scripts to support the OpenSSL assembly modules on ARM64 yet. But then they are just optimizations one can build without, and
vcbuild.batautomatically configures without them on ARM64 anyway. - ccache - it doesn’t yet support ARM64 Windows. I could run the x64 build under emulation, but I suspect the overhead wouldn’t be worth it, so I skipped it.
Enabling Developer Mode
Previously, I used a work laptop and I wasn’t sure whether I could do this, but this time I’m using a VM on my personal laptop, so I just enabled Developer Mode on Windows - without it, the tests that set up symlinks would fail due to permission issues.
Entering the Developer Command Prompt
Neither MSBuild nor SignTool (for signing binaries) is on %PATH% by default in cmd or PowerShell after installation, so they would need to be added manually. What I do instead usually is to just start the Developer Command Prompt from Visual Studio to get them:
In cmd, with VS 2026, I do this to enter the Developer Command Prompt:
1 | cmd /k ""C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\VsDevCmd.bat"" |
In PowerShell, no need to escape the quotes:
1 | cmd /k "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\VsDevCmd.bat" |
Generating the Solution
The build instructions in the Node.js documentation usually couple the solution generation and the build steps together into a single vcbuild.bat command, but I prefer to separate them so that I can have more control over the build process, and easily debug the generated projects when tweaking the build configurations.
To generate the solution without building it, run this in the Developer Command Prompt (I discovered that I needed to set arm64 explicitly to avoid accidentally cross-compiling for x64):
1 | .\vcbuild.bat clang-cl arm64 nobuild projgen |
This generates node.sln in the current directory, which can be opened in Visual Studio or built via MSBuild directly. It also generates .vcxproj files directly in the project directory, which can be inspected to debug build issues.
To generate a solution for a build dynamically linking to libnode.dll instead of the default static library build, add dll to the mix:
1 | .\vcbuild.bat clang-cl arm64 nobuild projgen dll |
Building Node.js via MSBuild
While the supported way to build Node.js on Windows is via vcbuild.bat, I prefer to use MSBuild directly as it gives a lot more control over what to build and what to skip to reduce the wait time. Also occasionally I could edit the project files directly to debug build issues.
After generating the solution as mentioned before, to build node.exe via MSBuild:
1 | MSBuild.exe node.sln /t:node /p:Configuration=Release /p:Platform=ARM64 /m /v:m |
To build a single target directly, specify the project file instead of the solution file. For example, to build only cctest:
1 | MSBuild.exe cctest.vcxproj /t:Build /p:Configuration=Release /p:Platform=ARM64 /m /v:m |
When the target is dynamically linked, and if only the source code for the target executable has changed, using BuildProjectReferences=false allows skipping the build (or the checks to see if builds are needed) for the DLL:
1 | MSBuild.exe shared_embedtest.vcxproj /t:Build /p:Configuration=Release /p:Platform=ARM64 /p:BuildProjectReferences=false /m /v:m |
Using vcbuild.bat for Testing
For running the tests, going back to vcbuild.bat is often more convenient.
To build the addon tests via vcbuild.bat while skipping the executable build:
1 | .\vcbuild.bat clang-cl arm64 nobuild build-node-api-tests |
To run the JavaScript tests without building anything:
1 | .\vcbuild.bat clang-cl arm64 noprojgen nobuild ignore-flaky test-ci-js |
Debugging Node.js via Visual Studio
Visual Studio is quite a beast but it has a lot of debugging features, so this is what I normally use when I have to do some serious debugging on Windows. Here are some tips on how to use it to debug Node.js:
- The Developer Command Prompt can be opened in a panel.
- When opening
node.slnfor the first time, the Startup Project defaults to the lexicographically smallest project, which is usuallycctest. That’s not very useful if I want to use keyboard shortcuts.- I usually just set the Startup Project to
node(which builds the Node.js binary): In the Solution Explorer panel, right-click onnodeand chooseSet as Startup Project. - To configure keyboard shortcuts for debugging, again right-click on
nodein the Solution Explorer panel, chooseProperties, go toDebugging, and set theCommand Argumentsto e.g..\test.js. Then I can just pressF5whenever I need to rebuild and debug a reproduction in.\test.js.
- I usually just set the Startup Project to
Check out the Visual Studio Documentation for more information.