diff --git a/.github/workflows/build-deps-ci-action.yml b/.github/workflows/build-deps-ci-action.yml
index 0e4957cb20cc..2cd933025d18 100644
--- a/.github/workflows/build-deps-ci-action.yml
+++ b/.github/workflows/build-deps-ci-action.yml
@@ -250,7 +250,7 @@ jobs:
windows-dependencies:
name: Windows
- runs-on: windows-latest
+ runs-on: ${{ matrix.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
if: ${{ toJSON(fromJSON(inputs.matrix)['windows']) != '[]' }}
env:
USE_S3_CACHE: 'false'
diff --git a/.github/workflows/build-packages.yml b/.github/workflows/build-packages.yml
index ac0caa430d96..f50bd279c6e4 100644
--- a/.github/workflows/build-packages.yml
+++ b/.github/workflows/build-packages.yml
@@ -482,7 +482,7 @@ jobs:
matrix:
include: ${{ fromJSON(inputs.matrix)['windows'] }}
runs-on:
- - windows-latest
+ - ${{ matrix.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
env:
SM_HOST: "${{ secrets.WIN_SIGN_HOST_PROD }}"
SM_API_KEY: "${{ secrets.WIN_SIGN_API_KEY }}"
@@ -585,6 +585,10 @@ jobs:
fi
- name: Upload ${{ matrix.arch }} NSIS Packages
+ # TEMPORARY: build.ps1 skips NSIS for arm64 (installer.nsi's own
+ # architecture detection doesn't support it yet, and NSIS was
+ # never actually requested for this target) - see build.ps1.
+ if: ${{ matrix.arch != 'arm64' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: ${{ steps.set-artifact-name.outputs.artifact-name-nsis }}
diff --git a/.github/workflows/build-salt-onedir.yml b/.github/workflows/build-salt-onedir.yml
index 992c1e809296..b20472e92485 100644
--- a/.github/workflows/build-salt-onedir.yml
+++ b/.github/workflows/build-salt-onedir.yml
@@ -167,7 +167,7 @@ jobs:
max-parallel: 2
matrix:
include: ${{ fromJSON(inputs.matrix)['windows'] }}
- runs-on: windows-latest
+ runs-on: ${{ matrix.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
env:
PIP_INDEX_URL: https://pypi.org/simple
USE_S3_CACHE: 'false'
@@ -196,6 +196,28 @@ jobs:
with:
salt-version: "${{ inputs.salt-version }}"
+ # TEMPORARY: arm64 has no released relenv build to fetch yet (see
+ # setup-relenv), so this job compiles CPython from source here
+ # instead, which needs the VC++ toolchain present. Remove alongside
+ # the setup-relenv arm64 branch once a real release exists.
+ - name: Install VS Build Tools
+ if: ${{ matrix.arch == 'arm64' }}
+ shell: pwsh
+ run: |
+ pkg\windows\install_vs_buildtools.ps1 -CICD
+
+ - name: Install ARM64 VC++ Tools
+ if: ${{ matrix.arch == 'arm64' }}
+ shell: pwsh
+ run: |
+ $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
+ $vsPath = & $vswhere -latest -products * -property installationPath
+ $installer = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vs_installer.exe"
+ & $installer modify --installPath "$vsPath" `
+ --add Microsoft.VisualStudio.Component.VC.Tools.ARM64 `
+ --quiet --norestart --nocache
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
+
- name: Setup Relenv
id: setup-relenv
uses: ./.github/actions/setup-relenv
diff --git a/pkg/windows/build.ps1 b/pkg/windows/build.ps1
index 70c0400a0885..71bd9c9d0aa4 100644
--- a/pkg/windows/build.ps1
+++ b/pkg/windows/build.ps1
@@ -30,10 +30,11 @@ param(
[String] $Version,
[Parameter(Mandatory=$false)]
- [ValidateSet("x86", "x64", "amd64")]
+ [ValidateSet("x86", "x64", "amd64", "arm64")]
[Alias("a")]
# The System Architecture to build. "x86" will build a 32-bit installer.
- # "x64" will build a 64-bit installer. Default is: x64
+ # "x64" will build a 64-bit installer. "arm64" will build a native
+ # ARM64 installer. Default is: x64
$Architecture = "x64",
[Parameter(Mandatory=$false)]
@@ -250,11 +251,22 @@ if ( $CICD ) {
$KeywordArguments["CICD"] = $true
}
-& "$SCRIPT_DIR\nsis\build_pkg.ps1" @KeywordArguments
-
-if ( ! $? ) {
- Write-Host "Failed to build NSIS package"
- exit 1
+# TEMPORARY: the .nsi script's own architecture detection (CPUARCH,
+# separate from this script's) only recognizes x64/AMD64/x86 and
+# silently falls back to x86 for anything else, producing an installer
+# whose filename build_pkg.ps1 then can't find. NSIS was never actually
+# requested for arm64 - skip it there rather than widen scope into
+# auditing/fixing the .nsi script for a component nobody asked for.
+# $KeywordArguments is reused below for the MSI build either way.
+if ( $Architecture -eq "arm64" ) {
+ Write-Host "Skipping NSIS package for arm64 (not yet supported by installer.nsi)"
+} else {
+ & "$SCRIPT_DIR\nsis\build_pkg.ps1" @KeywordArguments
+
+ if ( ! $? ) {
+ Write-Host "Failed to build NSIS package"
+ exit 1
+ }
}
#-------------------------------------------------------------------------------
diff --git a/pkg/windows/build_python.ps1 b/pkg/windows/build_python.ps1
index cc5971580877..fd2cfcfbde25 100644
--- a/pkg/windows/build_python.ps1
+++ b/pkg/windows/build_python.ps1
@@ -28,10 +28,11 @@ param(
[String] $RelenvVersion,
[Parameter(Mandatory=$false)]
- [ValidateSet("x64", "x86", "amd64")]
+ [ValidateSet("x64", "x86", "amd64", "arm64")]
[Alias("a")]
# The System Architecture to build. "x86" will build a 32-bit installer.
- # "x64" will build a 64-bit installer. Default is: x64
+ # "x64" will build a 64-bit installer. "arm64" will build a native
+ # ARM64 installer. Default is: x64
[String] $Architecture = "x64",
[Parameter(Mandatory=$false)]
@@ -175,6 +176,8 @@ $BLD_PY_BIN = "$BUILD_DIR\Scripts\python.exe"
if ( $Architecture -eq "x64" ) {
$ARCH = "amd64"
+} elseif ( $Architecture -eq "arm64" ) {
+ $ARCH = "arm64"
} else {
$ARCH = "x86"
}
diff --git a/pkg/windows/install_salt.ps1 b/pkg/windows/install_salt.ps1
index bb31b6c6e57f..38b09d8d2ba2 100644
--- a/pkg/windows/install_salt.ps1
+++ b/pkg/windows/install_salt.ps1
@@ -257,14 +257,23 @@ if ( ! $SkipInstall ) {
New-Item -Path .\doc\man\salt-cp.1 -Type File -Force | Out-Null
New-Item -Path .\doc\man\salt-minion.1 -Type File -Force | Out-Null
}
+ # Start-Process -WindowStyle Hidden discards pip's output entirely, so a
+ # failure here used to show only "Failed" with no indication of why.
+ # Push-Location/call-operator streams pip's real output to the log
+ # instead, and $LASTEXITCODE lets us fail on the actual pip error
+ # rather than only inferring failure from a missing salt-minion.exe.
+ Push-Location "$PROJECT_DIR"
try {
$env:RELENV_PIP_DIR = "yes"
- Start-Process -FilePath $SCRIPTS_DIR\pip3.exe `
- -ArgumentList "install", $InstallPath `
- -WorkingDirectory "$PROJECT_DIR" `
- -Wait -WindowStyle Hidden
+ & "$SCRIPTS_DIR\pip3.exe" install $InstallPath
+ $pipExitCode = $LASTEXITCODE
} finally {
Remove-Item env:\RELENV_PIP_DIR
+ Pop-Location
+ }
+ if ( $pipExitCode -ne 0 ) {
+ Write-Result "Failed" -ForegroundColor Red
+ exit 1
}
if ( Test-Path -Path "$BUILD_DIR\salt-minion.exe" ) {
Write-Result "Success" -ForegroundColor Green
diff --git a/pkg/windows/install_vs_buildtools.ps1 b/pkg/windows/install_vs_buildtools.ps1
index 5988ae5a1aeb..6b10c7a89a10 100644
--- a/pkg/windows/install_vs_buildtools.ps1
+++ b/pkg/windows/install_vs_buildtools.ps1
@@ -97,8 +97,23 @@ try {
$VS_INST_LOC = $(Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs).InstallLocation
$MSBUILD_BIN = $(Get-ChildItem "$VS_INST_LOC\MSBuild\*\Bin\msbuild.exe").FullName
} catch {
- # If VS is not installed, this is the fallback for this installation
- $MSBUILD_BIN = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\msbuild.exe"
+ # The MSFT_VSInstance CIM class isn't registered on every runner image
+ # (confirmed absent on windows-11-arm even though VS 2022 ships
+ # pre-installed there) -- before assuming VS needs to be installed
+ # from scratch, fall back to vswhere.exe, which is present on every
+ # GitHub-hosted Windows image regardless of CIM provider support.
+ $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
+ $VS_INST_LOC = $null
+ if ( Test-Path -Path $vswhere ) {
+ $VS_INST_LOC = & $vswhere -latest -products * -property installationPath
+ }
+ if ( $VS_INST_LOC ) {
+ $MSBUILD_BIN = $(Get-ChildItem "$VS_INST_LOC\MSBuild\*\Bin\msbuild.exe").FullName
+ } else {
+ # Genuinely no VS install found by either method - this is the
+ # fallback for a from-scratch installation.
+ $MSBUILD_BIN = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\msbuild.exe"
+ }
}
#-------------------------------------------------------------------------------
diff --git a/pkg/windows/msi/Product.wxs b/pkg/windows/msi/Product.wxs
index 6190dba297f6..05b8eb20a75f 100644
--- a/pkg/windows/msi/Product.wxs
+++ b/pkg/windows/msi/Product.wxs
@@ -22,11 +22,20 @@ IMCAC - Immediate Custom Action - It's immediate
Language = "1033">
+
@@ -246,6 +255,11 @@ IMCAC - Immediate Custom Action - It's immediate
WIX_UPGRADE_DETECTED
WIX_UPGRADE_DETECTED
+
+
+ (NOT VCREDIST_INSTALLED) AND (NOT Installed)
+
+
@@ -271,14 +285,26 @@ IMCAC - Immediate Custom Action - It's immediate
+
+
-
+
@@ -286,15 +312,29 @@ IMCAC - Immediate Custom Action - It's immediate
+
+
+
+
+
+
+
+
diff --git a/pkg/windows/msi/build_pkg.ps1 b/pkg/windows/msi/build_pkg.ps1
index eaa612c0666c..33c8167fe8d7 100644
--- a/pkg/windows/msi/build_pkg.ps1
+++ b/pkg/windows/msi/build_pkg.ps1
@@ -82,12 +82,18 @@ $SCRIPTS_DIR = "$BUILDENV_DIR\Scripts"
$SITE_PKGS_DIR = "$BUILDENV_DIR\Lib\site-packages"
$BUILD_SALT_DIR = "$SITE_PKGS_DIR\salt"
$PYTHON_BIN = "$SCRIPTS_DIR\python.exe"
-$BUILD_ARCH = $(. $PYTHON_BIN -c "import platform; print(platform.architecture()[0])")
+# platform.architecture()[0] only reports pointer width (64bit/32bit),
+# which can't distinguish arm64 from amd64 - both are "64bit". Use
+# platform.machine() instead, which reports the actual ISA the running
+# interpreter was built for.
+$BUILD_ARCH = $(. $PYTHON_BIN -c "import platform; print(platform.machine())")
$SCRIPT_DIR = (Get-ChildItem "$($myInvocation.MyCommand.Definition)").DirectoryName
$RUNTIME_DIR = [System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()
$CSC_BIN = "$RUNTIME_DIR\csc.exe"
-if ( $BUILD_ARCH -eq "64bit" ) {
+if ( $BUILD_ARCH -eq "ARM64" ) {
+ $BUILD_ARCH = "ARM64"
+} elseif ( $BUILD_ARCH -eq "AMD64" ) {
$BUILD_ARCH = "AMD64"
} else {
$BUILD_ARCH = "x86"
@@ -169,6 +175,17 @@ $RUNTIMES | ForEach-Object {
VerifyOrDownload "$WEBCACHE_DIR\$name" "$DEPS_URL/$name" "$hash"
}
+if ( $BUILD_ARCH -eq "ARM64" ) {
+ # Merge modules enforce exact architecture matching at build time
+ # (a Windows Installer rule, not a WiX limitation) - an x64 merge
+ # module cannot be merged into an arm64-declared product even
+ # though the resulting DLLs run fine under Windows 11 on Arm's x64
+ # emulation. No native arm64 merge module is published anywhere
+ # yet, so arm64 launches the standalone installer EXE via a
+ # CustomAction (see Product.wxs) instead of merging an .msm.
+ VerifyOrDownload "$WEBCACHE_DIR\vcredist_x64_2022.exe" "$DEPS_URL/vcredist_x64_2022.exe" "1AD7988C17663CC742B01BEF1A6DF2ED1741173009579AD50A94434E54F56073"
+}
+
#-------------------------------------------------------------------------------
# Converting to MSI Version
#-------------------------------------------------------------------------------
@@ -195,15 +212,19 @@ $MANUFACTURER = "Salt Project"
$PRODUCT = "Salt Minion"
$PRODUCTFILE = "Salt-Minion-$Version"
$PRODUCTDIR = "Salt"
-$DISCOVER_INSTALLDIR = "$BUILDENV_DIR", "$BUILDENV_DIR"
+$DISCOVER_INSTALLDIR = "$BUILDENV_DIR", "$BUILDENV_DIR", "$BUILDENV_DIR"
$DISCOVER_CONFDIR = Get-Item "$BUILDENV_DIR\configs"
-# MSI related arrays for 64 and 32 bit values, selected by BUILD_ARCH
-if ($BUILD_ARCH -eq "AMD64") {$i = 0} else {$i = 1}
-$WIN64 = "yes", "no" # Used in wxs
-$ARCHITECTURE = "x64", "x86" # WiX dictionary values
-$ARCH_AKA = "AMD64", "x86" # For filename
-$PROGRAMFILES = "ProgramFiles64Folder", "ProgramFilesFolder" # msi dictionary values
+# MSI related arrays for 64, 32, and arm64 bit values, selected by BUILD_ARCH.
+# arm64 reuses the amd64 WIN64/PROGRAMFILES values (it's still a native
+# 64-bit package installing under the 64-bit Program Files) but needs its
+# own WiX -arch tag and filename tag so the resulting MSI is correctly
+# identified as ARM64 rather than mislabeled as AMD64.
+if ($BUILD_ARCH -eq "ARM64") {$i = 2} elseif ($BUILD_ARCH -eq "AMD64") {$i = 0} else {$i = 1}
+$WIN64 = "yes", "no", "yes" # Used in wxs
+$ARCHITECTURE = "x64", "x86", "arm64" # WiX dictionary values
+$ARCH_AKA = "AMD64", "x86", "ARM64" # For filename
+$PROGRAMFILES = "ProgramFiles64Folder", "ProgramFilesFolder", "ProgramFiles64Folder" # msi dictionary values
function CheckExitCode() { # Exit on failure
if ($LastExitCode -ne 0) {
@@ -521,6 +542,7 @@ Write-Host "Compiling *.wxs to $($ARCHITECTURE[$i]) *.wixobj: " -NoNewline
Push-Location $SCRIPT_DIR
& "$($ENV:WIX)bin\candle.exe" -nologo -sw1150 `
-arch $ARCHITECTURE[$i] `
+ -dARCHITECTURE="$($ARCHITECTURE[$i])" `
-dWIN64="$($WIN64[$i])" `
-dPROGRAMFILES="$($PROGRAMFILES[$i])" `
-dMANUFACTURER="$MANUFACTURER" `
diff --git a/pkg/windows/nsis/build_pkg.ps1 b/pkg/windows/nsis/build_pkg.ps1
index 1734e068e003..b6c01711eb1b 100644
--- a/pkg/windows/nsis/build_pkg.ps1
+++ b/pkg/windows/nsis/build_pkg.ps1
@@ -63,9 +63,15 @@ $PYTHON_BIN = "$SCRIPTS_DIR\python.exe"
$PY_VERSION = [Version]((Get-Command $PYTHON_BIN).FileVersionInfo.ProductVersion)
$PY_VERSION = "$($PY_VERSION.Major).$($PY_VERSION.Minor)"
$NSIS_BIN = "$( ${env:ProgramFiles(x86)} )\NSIS\makensis.exe"
-$ARCH = $(. $PYTHON_BIN -c "import platform; print(platform.architecture()[0])")
-
-if ( $ARCH -eq "64bit" ) {
+# platform.architecture()[0] only reports pointer width (64bit/32bit),
+# which can't distinguish arm64 from amd64 - both are "64bit". Use
+# platform.machine() instead, which reports the actual ISA the running
+# interpreter was built for.
+$ARCH = $(. $PYTHON_BIN -c "import platform; print(platform.machine())")
+
+if ( $ARCH -eq "ARM64" ) {
+ $ARCH = "ARM64"
+} elseif ( $ARCH -eq "AMD64" ) {
$ARCH = "AMD64"
} else {
$ARCH = "x86"
diff --git a/pkg/windows/prep_salt.ps1 b/pkg/windows/prep_salt.ps1
index 7dea332a91c7..ff9192adfc8e 100644
--- a/pkg/windows/prep_salt.ps1
+++ b/pkg/windows/prep_salt.ps1
@@ -69,15 +69,31 @@ $SITE_PKGS_DIR = "$BUILD_DIR\Lib\site-packages"
$PYTHON_BIN = "$SCRIPTS_DIR\python.exe"
$PY_VERSION = [Version]((Get-Command $PYTHON_BIN).FileVersionInfo.ProductVersion)
$PY_VERSION = "$($PY_VERSION.Major).$($PY_VERSION.Minor)"
-$PY_ARCH = $(. $PYTHON_BIN -c "import platform; print(platform.architecture()[0])")
+# platform.architecture()[0] only reports pointer width (64bit/32bit),
+# which can't distinguish arm64 from amd64 - both are "64bit". Use
+# platform.machine() instead, which reports the actual ISA the running
+# interpreter was built for.
+$PY_MACHINE = $(. $PYTHON_BIN -c "import platform; print(platform.machine())")
$DEPS_URL = "https://github.com/saltstack/salt-windows-deps/raw/refs/heads/main"
-if ( $PY_ARCH -eq "64bit" ) {
+if ( $PY_MACHINE -eq "ARM64" ) {
+ $ARCH = "arm64"
+ # No native arm64 build of ssm.exe or vcredist exists in
+ # salt-windows-deps yet. Windows 11 on Arm runs x64 binaries under
+ # emulation, so fall back to the x64 builds until native ones are
+ # published upstream. DOWNLOAD_ARCH tracks the artifact to fetch,
+ # separately from ARCH (the true target architecture).
+ $DOWNLOAD_ARCH = "x64"
+ $SSM_URL = "$DEPS_URL/ssm/64/ssm-2.24-103-gdee49fc.exe"
+ $VCREDIST_URL = "$DEPS_URL/vcredist"
+} elseif ( $PY_MACHINE -eq "AMD64" ) {
$ARCH = "x64"
+ $DOWNLOAD_ARCH = "x64"
$SSM_URL = "$DEPS_URL/ssm/64/ssm-2.24-103-gdee49fc.exe"
$VCREDIST_URL = "$DEPS_URL/vcredist"
} else {
$ARCH = "x86"
+ $DOWNLOAD_ARCH = "x86"
$SSM_URL = "$DEPS_URL/ssm/32/ssm-2.24-103-gdee49fc.exe"
$VCREDIST_URL = "$DEPS_URL/vcredist"
}
@@ -155,7 +171,7 @@ if ( $PKG ) {
# Make sure ssm.exe is present. This is needed for VMtools
if ( ! (Test-Path -Path "$BUILD_DIR\ssm.exe") ) {
- Write-Host "Copying SSM $ARCH to Root: " -NoNewline
+ Write-Host "Copying SSM $DOWNLOAD_ARCH to Root: " -NoNewline
Invoke-WebRequest -Uri "$SSM_URL" -OutFile "$BUILD_DIR\ssm.exe"
if ( Test-Path -Path "$BUILD_DIR\ssm.exe" ) {
Write-Result "Success" -ForegroundColor Green
@@ -185,8 +201,8 @@ $scripts | ForEach-Object {
# Copy VCRedist 2022 to the prereqs directory
New-Item -Path $PREREQ_DIR -ItemType Directory | Out-Null
-Write-Host "Copying VCRedist 2022 $ARCH to prereqs: " -NoNewline
-$file = "vcredist_$ARCH`_2022.exe"
+Write-Host "Copying VCRedist 2022 $DOWNLOAD_ARCH to prereqs: " -NoNewline
+$file = "vcredist_$DOWNLOAD_ARCH`_2022.exe"
Invoke-WebRequest -Uri "$VCREDIST_URL\$file" -OutFile "$PREREQ_DIR\$file"
if ( Test-Path -Path "$PREREQ_DIR\$file" ) {
Write-Result "Success" -ForegroundColor Green
diff --git a/requirements/base.txt b/requirements/base.txt
index fc22f9c4b27f..3f78d7a23849 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -77,9 +77,13 @@ pycparser>=2.23,<3.0; python_version < '3.10'
pycparser>=3.0; python_version >= '3.10'
# pymssql 2.3.12+ dropped win32 (32-bit Windows) wheels; 3008.x still
# builds a Windows x86 onedir so keep the pin at the last release that
-# ships cp3X-win32 wheels.
-pymssql>=2.2.1,<=2.3.11; sys_platform == 'win32' and python_version < '3.11'
-pymssql==2.3.11; sys_platform == 'win32' and python_version >= '3.11'
+# ships cp3X-win32 wheels. No win_arm64 wheel exists at all (from any
+# version) and the build forbids compiling it from source (it links
+# FreeTDS), so exclude it there entirely rather than fail the build -
+# the mssql execution/state module is simply unavailable on arm64 until
+# pymssql publishes an arm64 build.
+pymssql>=2.2.1,<=2.3.11; sys_platform == 'win32' and python_version < '3.11' and platform_machine != 'ARM64'
+pymssql==2.3.11; sys_platform == 'win32' and python_version >= '3.11' and platform_machine != 'ARM64'
# pyopenssl 26.3.0 requires cryptography>=49 which drops Python 3.9; keep the
# last 3.9-compatible release there and let py>=3.10 float forward.
pyopenssl>=26.2.0,<26.3.0; python_version < '3.10'
diff --git a/requirements/static/pkg/py3.14/windows.lock b/requirements/static/pkg/py3.14/windows.lock
index 330b830ddff0..5bb39777e1d7 100644
--- a/requirements/static/pkg/py3.14/windows.lock
+++ b/requirements/static/pkg/py3.14/windows.lock
@@ -168,8 +168,10 @@ pycryptodomex==3.23.0
# -r requirements/crypto.txt
pygments==2.19.2
# via rich
-pymssql==2.3.11
+pymssql==2.3.11; platform_machine != 'ARM64'
# via -r requirements/base.txt
+ # No win_arm64 wheel exists and the build forbids compiling it from
+ # source (links FreeTDS) - see requirements/base.txt.
pyopenssl==26.2.0
# via -r requirements/base.txt
python-dateutil==2.9.0.post0
diff --git a/tools/ci.py b/tools/ci.py
index 1439f4c3e606..2f2bab324a97 100644
--- a/tools/ci.py
+++ b/tools/ci.py
@@ -160,6 +160,7 @@ def _build_matrix(os_kind, linux_arm_runner):
_matrix = [
{"arch": "amd64"},
{"arch": "x86"},
+ {"arch": "arm64"},
]
elif os_kind == "macos":
_matrix.append({"arch": "arm64"})
diff --git a/tools/pkg/build.py b/tools/pkg/build.py
index 8fa97d1773bf..58633cedc7d5 100644
--- a/tools/pkg/build.py
+++ b/tools/pkg/build.py
@@ -526,7 +526,7 @@ def macos(
},
"arch": {
"help": "The architecture to build the package for",
- "choices": ("x86", "amd64"),
+ "choices": ("x86", "amd64", "arm64"),
"required": True,
},
"sign": {
@@ -763,7 +763,9 @@ def onedir_dependencies(
if platform == "darwin":
platform = "macos"
- if platform != "macos" and arch == "arm64":
+ if platform == "linux" and arch == "arm64":
+ # relenv's linux arches use "aarch64"; macos and windows both use
+ # "arm64" literally (confirmed against relenv's arches dict).
arch = "aarch64"
shared_constants = tools.utils.get_cicd_shared_context()
@@ -845,6 +847,14 @@ def onedir_dependencies(
# Cryptography needs openssl dir set to link to the proper openssl libs.
if platform == "macos":
env["OPENSSL_DIR"] = f"{dest}"
+ elif platform == "windows" and arch == "arm64":
+ # No prebuilt wheel exists for cryptography on this target yet,
+ # so pip falls back to compiling it, and openssl-sys has no
+ # other way to find an OpenSSL to link against. relenv bundles a
+ # copy of the OpenSSL dev tree it built from source for arm64
+ # into the onedir at OpenSSL/ for exactly this. amd64/x86 always
+ # have a prebuilt wheel and never reach this build path.
+ env["OPENSSL_DIR"] = str(dest / "OpenSSL")
if platform == "linux":
# This installs the ppbt package. We'll remove it after installing all