Skip to content

Commit a051819

Browse files
Enable windows arm64 builds for vision (#6352)
Add scripts and workflow for enabling windows arm64 builds
1 parent b3a792a commit a051819

File tree

4 files changed

+234
-13
lines changed

4 files changed

+234
-13
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
3+
echo "Dependency MSVC Build Tools with C++ with ARM64/ARM64EC components installation started."
4+
5+
# Pre-check for downloads and dependencies folders
6+
mkdir -p "$DOWNLOADS_DIR"
7+
mkdir -p "$DEPENDENCIES_DIR"
8+
9+
# Set download URL for the Visual Studio Installer
10+
DOWNLOAD_URL="https://aka.ms/vs/17/release/vs_BuildTools.exe"
11+
INSTALLER_FILE="$DOWNLOADS_DIR/vs_BuildTools.exe"
12+
13+
# Download installer
14+
echo "Downloading Visual Studio Build Tools with C++ installer..."
15+
curl -L -o "$INSTALLER_FILE" "$DOWNLOAD_URL"
16+
17+
# Install the Visual Studio Build Tools with C++ components
18+
echo "Installing Visual Studio Build Tools with C++ components..."
19+
echo "Installing MSVC $MSVC_VERSION"
20+
"$INSTALLER_FILE" --norestart --quiet --wait --installPath "$DEPENDENCIES_DIR/VSBuildTools" \
21+
--add Microsoft.VisualStudio.Workload.VCTools \
22+
--add Microsoft.VisualStudio.Component.Windows10SDK \
23+
--add Microsoft.VisualStudio.Component.Windows11SDK.22621 \
24+
--add Microsoft.VisualStudio.Component.VC.ASAN \
25+
--add Microsoft.VisualStudio.Component.VC.CMake.Project \
26+
--add Microsoft.VisualStudio.Component.VC.CoreBuildTools \
27+
--add Microsoft.VisualStudio.Component.VC.CoreIde \
28+
--add Microsoft.VisualStudio.Component.VC.Redist.14.Latest \
29+
--add Microsoft.VisualStudio.Component.VC.Tools.ARM64EC \
30+
--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 \
31+
--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64
32+
33+
# Check if installation was successful
34+
if [[ $? -ne 0 ]]; then
35+
echo "Failed to install Visual Studio Build Tools with C++ components."
36+
exit 1
37+
fi
38+
39+
echo "Dependency Visual Studio Build Tools with C++ installation finished."

.github/workflows/build_wheels_windows.yml

Lines changed: 129 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ on:
6868
description: 'Timeout for the job (in minutes)'
6969
default: 60
7070
type: number
71+
architecture:
72+
description: 'CPU architecture to build for'
73+
default: "x64"
74+
type: string
7175

7276
permissions:
7377
id-token: write
@@ -107,45 +111,112 @@ jobs:
107111
activate-with-label: false
108112
instructions: "SSH with rdesktop using ssh -L 3389:localhost:3389 %%username%%@%%hostname%%"
109113
- name: Add Conda scripts to GitHub path
114+
if: inputs.architecture == 'x64'
110115
run: |
111116
echo "C:/Jenkins/Miniconda3/Scripts" >> $GITHUB_PATH
117+
- name: Setup Git for Windows' minimal SDK
118+
env:
119+
DEPENDENCIES_DIR: c:\temp\dependencies\
120+
if: inputs.architecture == 'arm64'
121+
uses: git-for-windows/setup-git-for-windows-sdk@v1
122+
with:
123+
architecture: aarch64
124+
path: "${{env.DEPENDENCIES_DIR}}\\git"
112125
- uses: ./test-infra/.github/actions/set-channel
113126
- name: Set PYTORCH_VERSION
114-
if: ${{ env.CHANNEL == 'test' }}
127+
if: env.CHANNEL == 'test'
115128
run: |
116129
# When building RC, set the version to be the current candidate version,
117130
# otherwise, leave it alone so nightly will pick up the latest
118131
echo "PYTORCH_VERSION=${{ matrix.stable_version }}" >> "${GITHUB_ENV}"
119132
- uses: ./test-infra/.github/actions/setup-binary-builds
133+
if: inputs.architecture == 'x64'
120134
with:
121135
repository: ${{ inputs.repository }}
122136
ref: ${{ inputs.ref }}
123137
submodules: ${{ inputs.submodules }}
124138
setup-miniconda: false
125139
python-version: ${{ env.PYTHON_VERSION }}
126140
cuda-version: ${{ env.CU_VERSION }}
127-
arch: ${{ env.ARCH }}
141+
arch: ${{ inputs.architecture }}
128142
- name: Install XPU support package
129143
if: ${{ matrix.gpu_arch_type == 'xpu' }}
130144
env:
131145
XPU_VERSION: '2025.1'
132146
run: |
133147
cmd //c .\\test-infra\\.github\\scripts\\install_xpu.bat
148+
- name: Checkout Target Repository (${{ env.REPOSITORY }})
149+
if: inputs.architecture == 'arm64'
150+
uses: actions/checkout@v4
151+
with:
152+
repository: ${{ env.REPOSITORY }}
153+
ref: ${{ env.REF }}
154+
path: ${{ env.REPOSITORY }}
155+
submodules: recursive
156+
- name: Bootstrap python
157+
if: inputs.architecture == 'arm64'
158+
uses: actions/setup-python@v5
159+
with:
160+
python-version: ${{ matrix.python_version }}
161+
architecture: arm64
162+
- name: Bootstrap Build Tools
163+
if: inputs.architecture == 'arm64'
164+
env:
165+
DOWNLOADS_DIR: c:\temp\downloads\
166+
DEPENDENCIES_DIR: c:\temp\dependencies\
167+
SCRIPTS_DIR: test-infra\\.github\\scripts\\winarm64
168+
run: |
169+
"${{ env.SCRIPTS_DIR }}\bootstrap_buildtools.sh"
134170
- name: Install torch dependency
171+
if: inputs.architecture == 'x64'
135172
run: |
136173
source "${BUILD_ENV_FILE}"
137174
# shellcheck disable=SC2086
138175
${CONDA_RUN} ${PIP_INSTALL_TORCH}
139176
- name: Run Pre-Script with Caching
140-
if: ${{ inputs.pre-script != '' }}
177+
if: ${{ inputs.pre-script != '' && inputs.architecture == 'x64' }}
141178
uses: ./test-infra/.github/actions/run-script-with-cache
142179
with:
143180
cache-path: ${{ inputs.cache-path }}
144181
cache-key: ${{ inputs.cache-key }}
145182
repository: ${{ inputs.repository }}
146183
script: ${{ inputs.pre-script }}
147184
is_windows: 'enabled'
185+
- name: Run Pre-Script Arm64
186+
if: ${{ inputs.pre-script != '' && inputs.architecture == 'arm64' }}
187+
env:
188+
DOWNLOADS_DIR: c:\temp\downloads\
189+
DEPENDENCIES_DIR: c:\temp\dependencies\
190+
SCRIPTS_DIR: test-infra\\.github\\scripts\\winarm64
191+
SRC_DIR: ${{ inputs.repository }}
192+
PRE_SCRIPT: ${{ inputs.pre-script }}
193+
shell: cmd
194+
run: |
195+
set VS_PATH=%DEPENDENCIES_DIR%\VSBuildTools\VC\Auxiliary\Build\vcvarsall.bat
196+
set GIT_BASH=%DEPENDENCIES_DIR%\git\usr\bin\bash.exe
197+
198+
cd %SRC_DIR%
199+
200+
call "%VS_PATH%" arm64
201+
"%GIT_BASH%" -c "bash --noprofile --norc %PRE_SCRIPT%"
202+
- name: Install certificates for Arm64 runner
203+
if: ${{ inputs.architecture == 'arm64' }}
204+
working-directory: ${{ inputs.repository }}
205+
shell: cmd
206+
run: |
207+
call .\.venv\Scripts\activate.bat
208+
209+
pip install --upgrade certifi==2025.04.26
210+
for /f "delims=" %%A in ('python -m certifi') do set CERT_PATH=%%A
211+
echo Using cert bundle at: %CERT_PATH%
212+
213+
set SSL_CERT_FILE=%CERT_PATH%
214+
set REQUESTS_CA_BUNDLE=%CERT_PATH%
215+
216+
echo SSL_CERT_FILE=%CERT_PATH% >> %GITHUB_ENV%
217+
echo REQUESTS_CA_BUNDLE=%CERT_PATH% >> %GITHUB_ENV%
148218
- name: Build clean
219+
if: inputs.architecture == 'x64'
149220
working-directory: ${{ inputs.repository }}
150221
env:
151222
ENV_SCRIPT: ${{ inputs.env-script }}
@@ -161,7 +232,8 @@ jobs:
161232
${CONDA_RUN} ${ENV_SCRIPT} python setup.py clean
162233
fi
163234
fi
164-
- name: Build the wheel (bdist_wheel)
235+
- name: Build the wheel (bdist_wheel) X64
236+
if: inputs.architecture == 'x64'
165237
working-directory: ${{ inputs.repository }}
166238
env:
167239
ENV_SCRIPT: ${{ inputs.env-script }}
@@ -182,17 +254,36 @@ jobs:
182254
else
183255
${CONDA_RUN} ${ENV_SCRIPT} python setup.py bdist_wheel ${BUILD_PARAMS}
184256
fi
257+
- name: Build the wheel (bdist_wheel) Arm64
258+
if: inputs.architecture == 'arm64'
259+
env:
260+
SRC_DIR: ${{ inputs.repository }}
261+
DEPENDENCIES_DIR: c:\temp\dependencies\
262+
shell: cmd
263+
run: |
264+
set CONDA_PREFIX=%DEPENDENCIES_DIR%
265+
set PATH=%PATH%;%DEPENDENCIES_DIR%\Library\bin
266+
set DISTUTILS_USE_SDK=1
267+
set VS_PATH=%DEPENDENCIES_DIR%\VSBuildTools\VC\Auxiliary\Build\vcvarsall.bat
268+
269+
call "%VS_PATH%" arm64
270+
cd %SRC_DIR%
271+
call .venv\Scripts\activate.bat
272+
273+
pip install --upgrade setuptools==72.1.0
274+
python setup.py bdist_wheel
185275
- name: Run post-script
186276
working-directory: ${{ inputs.repository }}
187277
env:
188278
POST_SCRIPT: ${{ inputs.post-script }}
189279
ENV_SCRIPT: ${{ inputs.env-script }}
190-
if: ${{ inputs.post-script != '' }}
280+
if: ${{ inputs.post-script != '' && inputs.architecture == 'x64'}}
191281
run: |
192282
set -euxo pipefail
193283
source "${BUILD_ENV_FILE}"
194284
${CONDA_RUN} ${ENV_SCRIPT} ${POST_SCRIPT}
195-
- name: Smoke Test
285+
- name: Smoke Test X64
286+
if: inputs.architecture == 'x64'
196287
env:
197288
ENV_SCRIPT: ${{ inputs.env-script }}
198289
PACKAGE_NAME: ${{ inputs.package-name }}
@@ -209,15 +300,44 @@ jobs:
209300
echo "${{ inputs.repository }}/${SMOKE_TEST_SCRIPT} found"
210301
${CONDA_RUN} "${{ inputs.repository }}/${ENV_SCRIPT}" python "${{ inputs.repository }}/${SMOKE_TEST_SCRIPT}"
211302
fi
303+
- name: Smoke Test ARM64
304+
if: inputs.architecture == 'arm64'
305+
env:
306+
PACKAGE_NAME: ${{ inputs.package-name }}
307+
SMOKE_TEST_SCRIPT: ${{ inputs.smoke-test-script }}
308+
SRC_DIR: ${{ inputs.repository }}
309+
run: |
310+
cd $SRC_DIR
311+
source .venv/Scripts/activate
312+
whl=$(find dist -name "${{env.PACKAGE_NAME}}-*.whl" | head -n 1)
313+
pip install $whl
314+
315+
if [[ ! -f ${SMOKE_TEST_SCRIPT} ]]; then
316+
echo "${SMOKE_TEST_SCRIPT} not found"
317+
python -c "import ${PACKAGE_NAME}; print('package version is ', ${PACKAGE_NAME}.__version__)"
318+
else
319+
echo "${SMOKE_TEST_SCRIPT} found"
320+
python "$SMOKE_TEST_SCRIPT"
321+
fi
212322
# NB: Only upload to GitHub after passing smoke tests
323+
- name: Get Artifact name
324+
if: inputs.architecture == 'arm64'
325+
env:
326+
REPOSITORY: ${{ inputs.repository }}
327+
REF: ${{ inputs.ref }}
328+
PYTHON_VERSION: ${{ matrix.python_version }}
329+
CU_VERSION: ${{ env.CU_VERSION }}
330+
ARCH: ${{ inputs.architecture }}
331+
run: |
332+
echo "ARTIFACT_NAME=${REPOSITORY//\//_}_${REF//\//_}_${PYTHON_VERSION}_${CU_VERSION}_${ARCH}" >> "${GITHUB_ENV}"
213333
- name: Upload wheel to GitHub
214334
continue-on-error: true
215335
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
216336
with:
217337
name: ${{ env.ARTIFACT_NAME }}
218338
path: ${{ inputs.repository }}/dist/
219339
- uses: ./test-infra/.github/actions/teardown-windows
220-
if: always()
340+
if: inputs.architecture == 'x64'
221341
name: Teardown Windows
222342

223343
upload:
@@ -231,7 +351,8 @@ jobs:
231351
test-infra-ref: ${{ inputs.test-infra-ref }}
232352
build-matrix: ${{ inputs.build-matrix }}
233353
trigger-event: ${{ inputs.trigger-event }}
354+
architecture: ${{ inputs.architecture }}
234355

235356
concurrency:
236357
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ inputs.repository }}-${{ github.event_name == 'workflow_dispatch' }}
237-
cancel-in-progress: true
358+
cancel-in-progress: true
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Test Build Windows Wheels ARM64
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- .github/workflows/test_build_wheels_windows_arm64.yml
7+
- .github/workflows/build_wheels_windows.yml
8+
- .github/workflows/generate_binary_build_matrix.yml
9+
- tools/scripts/generate_binary_build_matrix.py
10+
workflow_dispatch:
11+
12+
permissions:
13+
id-token: write
14+
contents: read
15+
16+
jobs:
17+
generate-matrix:
18+
uses: ./.github/workflows/generate_binary_build_matrix.yml
19+
with:
20+
package-type: wheel
21+
os: windows-arm64
22+
test-infra-repository: ${{ github.repository }}
23+
test-infra-ref: ${{ github.ref }}
24+
with-cuda: disable
25+
test:
26+
needs: generate-matrix
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
include:
31+
- repository: pytorch/vision
32+
pre-script: packaging/pre_build_script_arm64.sh
33+
smoke-test-script: test/smoke_test.py
34+
package-name: torchvision
35+
architecture: "arm64"
36+
uses: ./.github/workflows/build_wheels_windows.yml
37+
name: ${{ matrix.repository }}
38+
with:
39+
repository: ${{ matrix.repository }}
40+
ref: nightly
41+
test-infra-repository: ${{ github.repository }}
42+
test-infra-ref: ${{ github.ref }}
43+
pre-script: ${{ matrix.pre-script }}
44+
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
45+
smoke-test-script: ${{ matrix.smoke-test-script }}
46+
package-name: ${{ matrix.package-name }}
47+
trigger-event: "${{ github.event_name }}"
48+
architecture: ${{ matrix.architecture }}

tools/scripts/generate_binary_build_matrix.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
LINUX_AARCH64 = "linux-aarch64"
6565
MACOS_ARM64 = "macos-arm64"
6666
WINDOWS = "windows"
67+
WINDOWS_ARM64 = "windows-arm64"
6768

6869
# Accelerator architectures
6970
CPU = "cpu"
@@ -94,9 +95,11 @@
9495
LINUX_AARCH64_GPU_RUNNER = "linux.arm64.m7g.4xlarge"
9596
WIN_GPU_RUNNER = "windows.g4dn.xlarge"
9697
WIN_CPU_RUNNER = "windows.4xlarge"
98+
WIN_ARM64_RUNNER = "windows-11-arm64"
9799
MACOS_M1_RUNNER = "macos-m1-stable"
98100

99101
PACKAGES_TO_INSTALL_WHL = "torch torchvision torchaudio"
102+
PACKAGES_TO_INSTALL_WHL_WIN_ARM64 = "torch"
100103
WHL_INSTALL_BASE = "pip3 install"
101104
DOWNLOAD_URL_BASE = "https://download.pytorch.org"
102105

@@ -135,6 +138,8 @@ def validation_runner(arch_type: str, os: str) -> str:
135138
return WIN_GPU_RUNNER
136139
else:
137140
return WIN_CPU_RUNNER
141+
elif os == WINDOWS_ARM64:
142+
return WIN_ARM64_RUNNER
138143
elif os == MACOS_ARM64:
139144
return MACOS_M1_RUNNER
140145
else: # default to linux cpu runner
@@ -296,11 +301,16 @@ def get_wheel_install_command(
296301
):
297302
return f"{WHL_INSTALL_BASE} {PACKAGES_TO_INSTALL_WHL}"
298303
else:
299-
whl_install_command = (
300-
f"{WHL_INSTALL_BASE} --pre {PACKAGES_TO_INSTALL_WHL}"
301-
if channel == "nightly"
302-
else f"{WHL_INSTALL_BASE} {PACKAGES_TO_INSTALL_WHL}"
303-
)
304+
whl_install_command = ""
305+
if os == WINDOWS_ARM64:
306+
# winarm64 has only nightly torch package for now
307+
whl_install_command = (
308+
f"{WHL_INSTALL_BASE} --pre {PACKAGES_TO_INSTALL_WHL_WIN_ARM64}" # noqa: E501
309+
)
310+
elif channel == "nightly":
311+
whl_install_command = f"{WHL_INSTALL_BASE} --pre {PACKAGES_TO_INSTALL_WHL}"
312+
else:
313+
whl_install_command = f"{WHL_INSTALL_BASE} {PACKAGES_TO_INSTALL_WHL}"
304314
return f"{whl_install_command} --index-url {get_base_download_url_for_repo('whl', channel, gpu_arch_type, desired_cuda)}" # noqa: E501
305315

306316

@@ -416,6 +426,9 @@ def generate_wheels_matrix(
416426
# Define default python version
417427
python_versions = list(PYTHON_ARCHES)
418428

429+
if os == WINDOWS_ARM64:
430+
python_versions = ["3.11", "3.12", "3.13"] # only versions for now
431+
419432
if os == LINUX:
420433
# NOTE: We only build manywheel packages for linux
421434
package_type = "manywheel"

0 commit comments

Comments
 (0)