-
Notifications
You must be signed in to change notification settings - Fork 3
feat: Windows ARM64 support and tool installation fixes #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -196,36 +196,41 @@ runs: | |||||
| - name: Install build dependencies (Windows) | ||||||
| shell: bash | ||||||
| if: ${{ runner.os == 'Windows' && steps.check_build.outputs.build_nss }} | ||||||
| run: | | ||||||
| env: | ||||||
| RUNNER_ARCH: ${{ runner.arch }} | ||||||
| run: | # zizmor: ignore[github-env] | ||||||
| # shellcheck disable=SC2028 | ||||||
| { | ||||||
| echo C:/msys64/usr/bin | ||||||
| echo C:/msys64/mingw64/bin | ||||||
| # mingw64/bin provides x86_64 MinGW toolchain binaries; not used on ARM64 | ||||||
| # where the build uses MSVC exclusively. | ||||||
| [ "$RUNNER_ARCH" != "ARM64" ] && echo C:/msys64/mingw64/bin || true | ||||||
| } >> "$GITHUB_PATH" | ||||||
| /c/msys64/usr/bin/pacman -S --noconfirm python3-pip nsinstall | ||||||
| mkdir -p "$HOME/bin" | ||||||
| # renovate: depName=firefox datasource=custom.firefox versioning=loose | ||||||
| curl --proto '=https' --tlsv1.2 -o "$HOME/bin/nsinstall.py" -sSf https://hg-edge.mozilla.org/releases/mozilla-release/raw-file/FIREFOX_149_0_2_RELEASE/config/nsinstall.py | ||||||
| echo "f88df5591ee50d6e86625efd6e5f9c7b0dd4cba61e27ab533b1990115e100caf $HOME/bin/nsinstall.py" | sha256sum -c - | ||||||
| echo "#! /usr/bin/env python3" | cat - "$HOME/bin/nsinstall.py" > "$HOME/bin/nsinstall" | ||||||
| chmod +x "$HOME/bin/nsinstall" | ||||||
| echo "$HOME/bin" >> "$GITHUB_PATH" | ||||||
| # gyp-next>=0.22.0 added Windows ARM64 target support (nodejs/gyp-next#331). | ||||||
| # renovate: depName=gyp-next datasource=pypi | ||||||
| echo "gyp-next==0.22.2" > req.txt | ||||||
| echo "mozfile" >> req.txt # required by nsinstall.py | ||||||
|
larseggert marked this conversation as resolved.
larseggert marked this conversation as resolved.
larseggert marked this conversation as resolved.
larseggert marked this conversation as resolved.
|
||||||
| python3 -m pip install -r req.txt | ||||||
|
larseggert marked this conversation as resolved.
|
||||||
|
|
||||||
| - name: Set up MSVC (Windows) | ||||||
| if: ${{ runner.os == 'Windows' && steps.check_build.outputs.build_nss }} | ||||||
| uses: ilammy/msvc-dev-cmd@v1 # zizmor: ignore[unpinned-uses] | ||||||
| # TODO: Would like to pin this, but the Mozilla org allowlist requires "ilammy/msvc-dev-cmd@v1*" | ||||||
| # uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 | ||||||
| with: | ||||||
| arch: ${{ runner.arch == 'ARM64' && 'arm64' || 'amd64' }} | ||||||
|
larseggert marked this conversation as resolved.
|
||||||
|
|
||||||
| - name: Set up build environment (Windows) | ||||||
| shell: bash | ||||||
| if: ${{ runner.os == 'Windows' && steps.check_build.outputs.build_nss }} | ||||||
| run: | | ||||||
| # Work around NSS's coreconf/msvc.sh bug with MSVC 18 (VS 2026): | ||||||
| # Set VSPATH so msvc.sh skips its setup branch, and configure the gyp overrides ourselves. | ||||||
| if [ "${VSCMD_VER%%.*}" = "18" ]; then | ||||||
| { | ||||||
| echo "VSPATH=$VSINSTALLDIR" | ||||||
| echo "GYP_MSVS_OVERRIDE_PATH=$VSINSTALLDIR" | ||||||
| echo "GYP_MSVS_VERSION=2026" | ||||||
| } >> "$GITHUB_ENV" | ||||||
| fi | ||||||
| # See https://github.com/ilammy/msvc-dev-cmd#name-conflicts-with-shell-bash | ||||||
| rm /usr/bin/link.exe || true | ||||||
|
larseggert marked this conversation as resolved.
|
||||||
|
|
||||||
|
|
@@ -255,6 +260,7 @@ runs: | |||||
| env: | ||||||
| TARGET_PLATFORM: ${{ inputs.target }} | ||||||
| RUNNER_OS: ${{ runner.os }} | ||||||
| RUNNER_ARCH: ${{ runner.arch }} | ||||||
| run: | | ||||||
| # We want to do an optimized build for accurate CPU profiling, but | ||||||
| # we also want debug symbols and frame pointers for that, which the normal optimized NSS | ||||||
|
|
@@ -312,7 +318,25 @@ runs: | |||||
| cp -vaL "$LIB_DIR"/* "dist/Release/lib" | ||||||
| else | ||||||
| [ "$SCCACHE_CC" ] && [ "$SCCACHE_CXX" ] && export CC="$SCCACHE_CC" CXX="$SCCACHE_CXX" | ||||||
| $NSS_DIR/build.sh -g -Ddisable_tests=1 -Ddisable_dbm=1 -Ddisable_libpkix=1 -Ddisable_ckbi=1 -Ddisable_fips=1 --opt --static | ||||||
| NSS_EXTRA="" | ||||||
| if [ "$RUNNER_OS" == "Windows" ]; then | ||||||
| # nss-msvc-arm64.patch also fixes VS 2026 compatibility on all Windows | ||||||
| # targets, so it is applied unconditionally. | ||||||
| patch -p1 < "$GITHUB_ACTION_PATH/patches/nss-msvc-arm64.patch" | ||||||
|
larseggert marked this conversation as resolved.
larseggert marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tip Consider adding
Suggested change
|
||||||
| fi | ||||||
| if [ "$RUNNER_OS" == "Windows" ] && [ "$RUNNER_ARCH" == "ARM64" ]; then | ||||||
| # Apply ARM64-specific patches to NSPR and NSS. | ||||||
| # Each patch file can be removed individually as upstream adds support, | ||||||
| # except nss-arm64-gyp-and-aes.patch which bundles two coupled changes. | ||||||
| for p in "$GITHUB_ACTION_PATH/patches/"*.patch; do | ||||||
|
larseggert marked this conversation as resolved.
|
||||||
| [ "$p" = "$GITHUB_ACTION_PATH/patches/nss-msvc-arm64.patch" ] && continue | ||||||
| patch -p1 < "$p" | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tip Same
Suggested change
|
||||||
| done | ||||||
|
|
||||||
| NSS_EXTRA="--target=arm64" | ||||||
| fi | ||||||
| # shellcheck disable=SC2086 | ||||||
| $NSS_DIR/build.sh -g -Ddisable_tests=1 -Ddisable_dbm=1 -Ddisable_libpkix=1 -Ddisable_ckbi=1 -Ddisable_fips=1 --opt --static $NSS_EXTRA | ||||||
| fi | ||||||
|
|
||||||
| - name: Save NSS cache | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Fix CPU architecture detection in NSPR configure for Windows ARM64. | ||
| # | ||
| # When NSS builds NSPR with --target=arm64, nspr.sh passes | ||
| # --host=aarch64-pc-mingw32 which activates configure's cross-compile path. | ||
| # That path hardcoded CPU_ARCH=x86 for all mingw* targets regardless of | ||
| # target_cpu. Use target_cpu instead so aarch64 cross-compile targets are | ||
| # handled correctly. | ||
| # | ||
| # Removable once NSPR configure handles ARM64 in the mingw* cross-compile case. | ||
| --- a/nspr/configure | ||
| +++ b/nspr/configure | ||
| @@ -6647,7 +6647,12 @@ | ||
| linux*) OS_ARCH=Linux ;; | ||
| solaris*) OS_ARCH=SunOS OS_RELEASE=5 ;; | ||
| - mingw*) OS_ARCH=WINNT CPU_ARCH=x86 ;; | ||
| + mingw*) | ||
| + OS_ARCH=WINNT | ||
| + case "$target_cpu" in | ||
| + aarch64) CPU_ARCH=aarch64; USE_64=1 ;; | ||
| + *) CPU_ARCH=x86 ;; | ||
| + esac ;; | ||
| cygwin*) OS_ARCH=WINNT ;; | ||
| darwin*) OS_ARCH=Darwin ;; | ||
| riscos*) OS_ARCH=RISCOS ;; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Add MSVC ARM64 implementations for PR_StackPush and PR_StackPop in ntmisc.c. | ||
| # | ||
| # The existing MSVC code path uses x86 inline assembly (__asm { ... }) which | ||
| # the ARM64 MSVC compiler does not support. Add a _M_ARM64 branch using | ||
| # _InterlockedExchangePointer (ARM64 compiler intrinsic, available via | ||
| # <intrin.h> already included by _winnt.h) to implement the same spin-lock | ||
| # semantics as the x86 xchg instruction. | ||
| # | ||
| # Removable once NSPR provides ARM64 implementations upstream. | ||
| --- a/nspr/pr/src/md/windows/ntmisc.c | ||
| +++ b/nspr/pr/src/md/windows/ntmisc.c | ||
| @@ -1075,6 +1075,15 @@ | ||
| *(void**)stack_elem = tmp; | ||
| __asm__("" : : : "memory"); | ||
| *tos = stack_elem; | ||
| +# elif defined(_M_ARM64) | ||
| + void* volatile* tos = (void* volatile*)stack; | ||
| + void* tmp; | ||
| +retry: | ||
| + if (*tos == (void*)-1) goto retry; | ||
|
larseggert marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note The ARM64 |
||
| + tmp = _InterlockedExchangePointer(tos, (void*)-1); | ||
| + if (tmp == (void*)-1) goto retry; | ||
| + *(void**)stack_elem = tmp; | ||
| + _InterlockedExchangePointer(tos, stack_elem); | ||
| # else | ||
| __asm | ||
| { | ||
| @@ -1119,6 +1128,21 @@ | ||
| *tos = tmp; | ||
| } | ||
|
|
||
| + return tmp; | ||
| +# elif defined(_M_ARM64) | ||
| + void* volatile* tos = (void* volatile*)stack; | ||
| + void* tmp; | ||
| +retry: | ||
| + if (*tos == (void*)-1) goto retry; | ||
| + tmp = _InterlockedExchangePointer(tos, (void*)-1); | ||
| + if (tmp == (void*)-1) goto retry; | ||
| + if (tmp != (void*)0) { | ||
| + void* next = *(void**)tmp; | ||
| + _InterlockedExchangePointer(tos, next); | ||
| + *(void**)tmp = 0; | ||
| + } else { | ||
| + _InterlockedExchangePointer(tos, tmp); | ||
| + } | ||
| return tmp; | ||
| # else | ||
| __asm | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Skip NSPR resource file compilation on Windows ARM64. | ||
| # | ||
| # NSPR's Makefile builds nspr.rc into a .res file via rc.exe. On ARM64, | ||
| # rc.exe's preprocessor cannot parse ARM64-specific constructs in NSPR's | ||
| # headers and fails. The resource file is only needed for shared-library | ||
| # version metadata and is not required for the static build we produce. | ||
| # Suppressing it on ARM64 only (via CPU_ARCH=aarch64) leaves x64/x86 | ||
| # builds unaffected. | ||
| # | ||
| # Removable once NSPR's Windows Makefile handles ARM64 resource compilation. | ||
| --- a/nspr/pr/src/Makefile.in | ||
| +++ b/nspr/pr/src/Makefile.in | ||
| @@ -245,7 +245,11 @@ | ||
| endif | ||
|
|
||
| ifeq ($(OS_ARCH), WINNT) | ||
| -RES=$(OBJDIR)/nspr.res | ||
| +ifeq ($(CPU_ARCH), aarch64) | ||
| +RES= | ||
| +else | ||
| +RES=$(OBJDIR)/nspr.res | ||
| +endif | ||
| RESNAME=nspr.rc | ||
| endif # WINNT | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Add ARM64 to _PR_SI_ARCHITECTURE detection in _winnt.h. | ||
| # | ||
| # _winnt.h defines _PR_SI_ARCHITECTURE for x86, x86-64, and ia64, but | ||
| # has a #error fallthrough for any other architecture. Without this patch | ||
| # every ARM64 compilation fails with "unknown processor architecture". | ||
| # | ||
| # Removable once NSPR adds ARM64 support to _winnt.h upstream. | ||
| --- a/nspr/pr/include/md/_winnt.h | ||
| +++ b/nspr/pr/include/md/_winnt.h | ||
| @@ -45,6 +45,8 @@ | ||
| #elif defined(_M_IA64) || defined(_IA64_) | ||
| #define _PR_SI_ARCHITECTURE "ia64" | ||
| +#elif defined(_M_ARM64) || defined(_ARM64_) | ||
| +#define _PR_SI_ARCHITECTURE "aarch64" | ||
| #else | ||
| #error unknown processor architecture | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Extend the 64-bit platform branch in _winnt.cfg to cover ARM64. | ||
| # | ||
| # NSPR's _winnt.cfg uses _M_X64 / _M_AMD64 / _AMD64_ to select the 64-bit | ||
| # configuration (IS_64, pointer sizes, etc.). ARM64 uses the same LLP64 ABI | ||
| # as x64 (64-bit pointers, 32-bit long) and belongs on the same branch. | ||
| # | ||
| # Removable once NSPR adds _M_ARM64 / _ARM64_ support upstream. | ||
| --- a/nspr/pr/include/md/_winnt.cfg | ||
| +++ b/nspr/pr/include/md/_winnt.cfg | ||
| @@ -68,7 +68,7 @@ | ||
| #define PR_BYTES_PER_WORD_LOG2 2 | ||
| #define PR_BYTES_PER_DWORD_LOG2 2 | ||
|
|
||
| -#elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) | ||
| +#elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) || defined(_M_ARM64) || defined(_ARM64_) | ||
|
|
||
| #define IS_LITTLE_ENDIAN 1 | ||
| #undef IS_BIG_ENDIAN |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Redirect Win32 Interlocked* exports to _Interlocked* compiler intrinsics. | ||
| # | ||
| # On ARM64 Windows, kernel32.lib does not export the Win32 Interlocked* | ||
| # functions as callable symbols; they are only available as compiler | ||
| # intrinsics (underscore-prefixed). Placing redirects immediately after | ||
| # <windows.h> rewrites every call site in NSPR via the preprocessor: | ||
| # | ||
| # - _MD_ATOMIC_* macros in _winnt.h (all builds) | ||
| # - _MD_LOCK lock-contention counters in _winnt.h (#ifdef PROFILE_LOCKS) | ||
| # - InterlockedCompareExchange called directly in ntio.c and prmwait.c | ||
| # | ||
| # Removable once NSPR uses compiler intrinsics unconditionally on Windows. | ||
| --- a/nspr/pr/include/md/_winnt.h | ||
| +++ b/nspr/pr/include/md/_winnt.h | ||
| @@ -17,6 +17,13 @@ | ||
| #endif /* _WIN32_WINNT */ | ||
|
|
||
| #include <windows.h> | ||
| +/* ARM64 kernel32.lib does not export Interlocked* as callable symbols; | ||
| + * redirect all call sites to the equivalent compiler intrinsics. */ | ||
| +#define InterlockedCompareExchange _InterlockedCompareExchange | ||
| +#define InterlockedIncrement _InterlockedIncrement | ||
| +#define InterlockedDecrement _InterlockedDecrement | ||
| +#define InterlockedExchange _InterlockedExchange | ||
| +#define InterlockedExchangeAdd _InterlockedExchangeAdd | ||
| #include <winsock.h> | ||
|
larseggert marked this conversation as resolved.
|
||
| #ifdef __MINGW32__ | ||
|
larseggert marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note The redirect list covers the five Interlocked functions NSPR uses ( |
||
| #include <mswsock.h> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # Add ARM64 MSVC support to NSS's gyp configuration and AES implementation. | ||
| # | ||
| # These two changes are coupled and must be applied or removed together: | ||
| # aes-armv8.c has a `#ifndef __ARM_FEATURE_CRYPTO / #error` guard; that | ||
| # macro is only defined via the PreprocessorDefinitions added to config.gypi. | ||
| # | ||
| # config.gypi: NSS's config.gypi has per-arch MSVS settings for ia32 and x64 | ||
| # but not ARM64. Without this block, gyp leaves msvs_configuration_platform | ||
| # unset for ARM64 (defaults to x86), causing ninja to use the wrong environment | ||
| # and tool paths. gyp-next >= 0.22.0 handles ARM64 toolchain discovery | ||
| # (environment.arm64, armasm64.exe), but NSS still needs its own preprocessor | ||
| # definitions here. /EHsc matches what the ia32 and x64 blocks already set. | ||
| # | ||
| # aes-armv8.c: guards its entire body with a preprocessor condition that only | ||
| # matches GCC/Clang. MSVC ARM64 supports the same NEON AES intrinsics | ||
| # (vaeseq_u8, vaesdq_u8, etc.) but does not define __clang__ or __GNUC__. | ||
| # IS_LITTLE_ENDIAN is included for consistency with the ghash patch — Windows | ||
| # ARM64 is always little-endian, but the explicit guard matches intent. | ||
| # Also adds a no-op __builtin_assume_aligned compat macro. | ||
| # | ||
| # Removable once NSS adds ARM64 MSVC support to config.gypi and aes-armv8.c. | ||
| --- a/nss/coreconf/config.gypi | ||
| +++ b/nss/coreconf/config.gypi | ||
| @@ -589,6 +589,19 @@ | ||
| }, | ||
| }, | ||
| }], | ||
| + [ 'target_arch=="arm64"', { | ||
| + 'msvs_configuration_platform': 'ARM64', | ||
| + 'msvs_settings': { | ||
| + 'VCCLCompilerTool': { | ||
| + 'PreprocessorDefinitions': [ | ||
| + 'WIN64', | ||
| + '_ARM64_', | ||
| + '__ARM_FEATURE_CRYPTO', | ||
| + ], | ||
| + 'AdditionalOptions': [ '/EHsc' ], | ||
| + }, | ||
| + }, | ||
| + }], | ||
| ], | ||
| }], | ||
|
larseggert marked this conversation as resolved.
|
||
| [ 'disable_dbm==1', { | ||
| --- a/nss/lib/freebl/aes-armv8.c | ||
| +++ b/nss/lib/freebl/aes-armv8.c | ||
| @@ -5,10 +5,15 @@ | ||
| #include "secerr.h" | ||
| #include "rijndael.h" | ||
|
|
||
| -#if ((defined(__clang__) || \ | ||
| - (defined(__GNUC__) && defined(__GNUC_MINOR__) && \ | ||
| - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)))) && \ | ||
| - defined(IS_LITTLE_ENDIAN)) | ||
| +#if (((defined(__clang__) || \ | ||
| + (defined(__GNUC__) && defined(__GNUC_MINOR__) && \ | ||
| + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)))) && \ | ||
| + defined(IS_LITTLE_ENDIAN)) || \ | ||
| + (defined(_MSC_VER) && defined(_M_ARM64) && defined(IS_LITTLE_ENDIAN))) | ||
| + | ||
| +#ifdef _MSC_VER | ||
| +#define __builtin_assume_aligned(ptr, align) (ptr) | ||
| +#endif | ||
|
|
||
| #ifndef __ARM_FEATURE_CRYPTO | ||
| #error "Compiler option is invalid" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Extend __aarch64__ guards in blinit.c to cover MSVC ARM64 (_M_ARM64). | ||
| # | ||
| # blinit.c uses __aarch64__ in three places where MSVC ARM64 needs to be | ||
| # included: | ||
| # 1. The _WIN64 + __aarch64__ guard for including <windows.h> (needed for | ||
| # IsProcessorFeaturePresent used inside CheckARMSupport on Windows). | ||
| # 2. The standalone #if defined(__aarch64__) that gates the ARM64-specific | ||
| # CheckARMSupport function definition. | ||
| # 3. The FreeblInit() dispatch that calls CheckARMSupport(). | ||
| # | ||
| # Removable once NSS adds _M_ARM64 checks to blinit.c upstream. | ||
| --- a/nss/lib/freebl/blinit.c | ||
| +++ b/nss/lib/freebl/blinit.c | ||
| @@ -17,7 +17,7 @@ | ||
| #include <intrin.h> /* for _xgetbv() */ | ||
| #endif | ||
|
|
||
| -#if defined(_WIN64) && defined(__aarch64__) | ||
| +#if defined(_WIN64) && (defined(__aarch64__) || defined(_M_ARM64)) | ||
| #include <windows.h> | ||
| #endif | ||
|
|
||
| @@ -186,7 +186,7 @@ | ||
| #endif /* defined(__aarch64__) || defined(__arm__) */ | ||
| /* clang-format on */ | ||
|
|
||
| -#if defined(__aarch64__) | ||
| +#if defined(__aarch64__) || defined(_M_ARM64) | ||
|
|
||
| #if defined(__linux__) | ||
| // Defines from hwcap.h in Linux kernel - ARM64 | ||
| @@ -557,7 +557,7 @@ | ||
| { | ||
| #ifdef NSS_X86_OR_X64 | ||
| CheckX86CPUSupport(); | ||
| -#elif (defined(__aarch64__) || defined(__arm__)) | ||
| +#elif (defined(__aarch64__) || defined(__arm__) || defined(_M_ARM64)) | ||
| CheckARMSupport(); | ||
| #elif (defined(__powerpc__)) | ||
| CheckPPCSupport(); |
Uh oh!
There was an error while loading. Please reload this page.