forked from opencv/opencv-python
-
Notifications
You must be signed in to change notification settings - Fork 0
286 lines (276 loc) · 11.6 KB
/
build_wheels_windows.yml
File metadata and controls
286 lines (276 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# GitHub Actions Workflow: Build opencv-python with CUDA support on Windows
#
# This workflow compiles opencv-python from source with CUDA enabled on a
# GitHub-hosted Windows runner. The resulting Python wheel is then uploaded
# as a build artifact.
#
# This is a complex and long-running process. It is configured to run only
# on manual trigger (workflow_dispatch).
name: Windows CUDA x64
on:
workflow_dispatch:
inputs:
# TODO: Add cuda_version input to allow running only CUDA 12 or 13 builds for debugging
# TODO: Right now we don't correctly determine when things have changed and we require a
# rebuild, so for now we just manually trigger rebuilds between runs.
restore_build_cache:
description: "Restore build cache. Uncheck to force re-build."
required: false
type: boolean
default: true
save_build_cache:
description: "Save build cache."
required: false
type: boolean
default: false
rolling_build:
description: "Use latest commit from upstream OpenCV repo. Cache settings will be ignored."
required: false
type: boolean
default: false
jobs:
Build:
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
python-version: ['3.13']
platform: [x64]
cuda-version: ['12']
include:
# CUDA 12: Supports Maxwell (5.0) through Blackwell (10.0)
- cuda-version: '12'
runs-on: 'windows-2025'
cuda-installer: 'cuda_12.9.1_windows_network.exe'
cuda-path-version: 'v12.9'
cudnn-archive: 'cudnn-windows-x86_64-9.18.1.3_cuda12-archive.zip'
cudnn-folder: 'cudnn-windows-x86_64-9.18.1.3_cuda12-archive'
video-codec-sdk-archive: 'Video_Codec_SDK_13.0.37.zip'
video-codec-sdk-folder: 'Video_Codec_SDK_13.0.37'
cuda-arch-bin: '5.0;5.2;6.0;6.1;7.0;7.5;8.0;8.6;8.9;9.0;10.0'
cuda-arch-ptx: '10.0'
cache-key: 'nvidia-deps-cuda-12.9.1-cudnn-9.18.1.3'
# TODO: Re-enable CUDA 13 after updating to OpenCV 4.13+
# CUDA 13: Supports Turing (7.5) through Blackwell (12.0)
# - cuda-version: '13'
# runs-on: 'windows-2025'
# cuda-installer: 'cuda_13.1.1_windows_network.exe'
# cuda-path-version: 'v13.1'
# cudnn-archive: 'cudnn-windows-x86_64-9.18.1.3_cuda13-archive.zip'
# cudnn-folder: 'cudnn-windows-x86_64-9.18.1.3_cuda13-archive'
# video-codec-sdk-archive: 'Video_Codec_SDK_13.0.37.zip'
# video-codec-sdk-folder: 'Video_Codec_SDK_13.0.37'
# cuda-arch-bin: '7.5;8.0;8.6;8.9;9.0;10.0;12.0'
# cuda-arch-ptx: '12.0'
# cache-key: 'nvidia-deps-cuda-13.1.1-cudnn-9.18.1.3'
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
SDIST: 0
ENABLE_HEADLESS: 0
ENABLE_CONTRIB: 1
ENABLE_ROLLING: ${{ inputs.rolling_build && 1 || 0 }}
OPENCV_TEST_DATA_PATH: ${{ github.workspace }}\opencv_extra\testdata
CUDA_ARCH_BIN: ${{ matrix.cuda-arch-bin }}
CUDA_ARCH_PTX: ${{ matrix.cuda-arch-ptx }}
steps:
- name: Cleanup
shell: bash
run: |
rm -rf ./* || true
rm -rf ./.??* || true
working-directory: ${{ github.workspace }}
- name: Checkout
uses: actions/checkout@v4
with:
submodules: false
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.platform }}
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.1
- name: Setup NASM
uses: ilammy/setup-nasm@v1
- name: Cache NVIDIA dependencies
id: cache-nvidia-deps
uses: actions/cache@v3
with:
path: .deps/Nvidia
key: ${{ matrix.cache-key }}
- name: Clone NVIDIA dependencies
if: steps.cache-nvidia-deps.outputs.cache-hit != 'true'
env:
SSH_PRIVATE_KEY: ${{ secrets.DEPS_REPO_SSH_KEY }}
run: |
eval "$(ssh-agent -s)"
ssh-add - <<< "${SSH_PRIVATE_KEY}"
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
git clone git@github.com:Breakthrough/opencv-python-cuda-deps.git .deps
shell: bash
- name: 🔧 Install NVIDIA CUDA Toolkit
run: |
$installer_path = ".deps/Nvidia/${{ matrix.cuda-installer }}"
if (-not (Test-Path $installer_path)) {
throw "CUDA Toolkit installer not found at $installer_path"
}
echo "Installing CUDA ${{ matrix.cuda-version }} Toolkit silently..."
Start-Process -FilePath $installer_path -ArgumentList "-s" -Wait -NoNewWindow
echo "Adding CUDA to PATH..."
$CUDA_PATH = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\${{ matrix.cuda-path-version }}"
echo "CUDA_PATH=$CUDA_PATH" | Out-File -FilePath $env:GITHUB_ENV -Append
Copy-Item -Path "$CUDA_PATH\bin\*.dll" -Destination .
shell: pwsh
- name: 🔧 Install NVIDIA CuDNN
run: |
$cudnn_path = ".deps/Nvidia/${{ matrix.cudnn-archive }}"
if (-not (Test-Path $cudnn_path)) {
throw "CuDNN archive not found at $cudnn_path"
}
echo "Installing CuDNN for CUDA ${{ matrix.cuda-version }}..."
7z x $cudnn_path
$CUDNN_PATH = "D:/a/opencv-python-cuda/opencv-python-cuda/${{ matrix.cudnn-folder }}"
echo "CUDNN_LIBRARY=$CUDNN_PATH/lib/x64/cudnn.lib" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CUDNN_INCLUDE_DIR=$CUDNN_PATH/include" | Out-File -FilePath $env:GITHUB_ENV -Append
Copy-Item -Path "$CUDNN_PATH/bin/x64/*" -Destination . -Include "*.dll"
shell: pwsh
- name: 🔧 Install NVIDIA Video Codec SDK
run: |
$sdk_path = ".deps/Nvidia/${{ matrix.video-codec-sdk-archive }}"
if (-not (Test-Path $sdk_path)) {
throw "Video Codec SDK archive not found at $sdk_path"
}
echo "Installing Video Codec SDK..."
7z x $sdk_path
$SDK_PATH = "D:/a/opencv-python-cuda/opencv-python-cuda/${{ matrix.video-codec-sdk-folder }}"
echo "CUDA_nvcuvid_LIBRARY=$SDK_PATH/Lib/win/x64/nvcuvid.lib" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CUDA_nvencodeapi_LIBRARY=$SDK_PATH/Lib/win/x64/nvencodeapi.lib" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "NVCUVID_INCLUDE_DIR=$SDK_PATH/Interface" | Out-File -FilePath $env:GITHUB_ENV -Append
shell: pwsh
- name: Restore build artifacts
uses: actions/cache/restore@v3
if: ${{ inputs.restore_build_cache && !inputs.rolling_build }}
with:
path: _skbuild
key: ${{ runner.os }}-${{ matrix.python-version }}-cuda${{ matrix.cuda-version }}-${{ hashFiles('**/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-cuda${{ matrix.cuda-version }}-
- name: Remove unused CUDA DLLs
# Only bundle CUDA DLLs that cv2.pyd actually needs (determined via PE import analysis).
# This removes ~1.3 GB of unused libraries (cusparse, cusolver, curand, nvrtc, etc.)
run: |
$keep = @(
"cublas64_*", "cublasLt64_*", "cudart64_*", "cudnn*", "cufft64_*",
"nppc64_*", "nppial64_*", "nppicc64_*", "nppidei64_*", "nppif64_*",
"nppig64_*", "nppim64_*", "nppist64_*", "nppitc64_*"
)
# Remove from project root (where setup.py picks up *.dll)
# and recursively from _skbuild (cmake-install and setuptools staging dirs)
foreach ($dir in @(".", "_skbuild")) {
Get-ChildItem -Path $dir -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Where-Object {
$name = $_.Name
$is_cuda = $name -match '^\w+64_\d'
$is_kept = $false
foreach ($pattern in $keep) {
if ($name -like $pattern) { $is_kept = $true; break }
}
$is_cuda -and -not $is_kept
} | ForEach-Object {
$size = [math]::Round($_.Length / 1MB)
$rel = Resolve-Path -Relative $_.FullName
echo "Removing $rel (${size} MB)"
Remove-Item $_.FullName
}
}
shell: pwsh
- name: Build a package
# CMake 3.25 regression fix. See https://stackoverflow.com/questions/74162633/problem-compiling-from-source-opencv-with-mvsc2019-in-64-bit-version
run: |
python --version
python -m pip install --upgrade pip
python -m pip install --upgrade setuptools
python -m pip install cmake==3.24.2
python -m pip install toml && python -c "import toml; c = toml.load('pyproject.toml'); print('\n'.join(c['build-system']['requires']))" >> requirements.txt | python -m pip install -r requirements.txt
$CI_BUILD = 1
if (Test-Path _skbuild) {
$SKIP_CMAKE = "--skip-cmake"
}
python setup.py $SKIP_CMAKE bdist_wheel --py-limited-api=cp37 --dist-dir="$PWD\wheelhouse" -v
shell: pwsh
# TODO(@Breakthrough): This seems to not work with `uv`...
- name: Repack wheel with LZMA compression
run: |
for whl in wheelhouse/opencv*.whl; do
src_size=$(stat -c%s "$whl")
echo "Repacking $(basename "$whl") ($(numfmt --to=iec $src_size))..."
tmpdir=$(mktemp -d)
7z x -o"$tmpdir" "$whl" -y > /dev/null
rm "$whl"
(cd "$tmpdir" && 7z a -tzip -mm=LZMA -mx=5 "$OLDPWD/$whl" . > /dev/null)
rm -rf "$tmpdir"
dst_size=$(stat -c%s "$whl")
saved=$((src_size - dst_size))
echo "Done: $(numfmt --to=iec $dst_size) (saved $(numfmt --to=iec $saved))"
done
shell: bash
- name: Save build artifacts to cache
uses: actions/cache/save@v3
if: ${{ inputs.save_build_cache && !inputs.rolling_build }}
with:
path: _skbuild
key: ${{ runner.os }}-${{ matrix.python-version }}-cuda${{ matrix.cuda-version }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Saving all wheels
uses: actions/upload-artifact@v4
with:
name: wheel-cuda${{ matrix.cuda-version }}-${{ matrix.platform }}
path: wheelhouse/opencv*
Test:
needs: [Build]
runs-on: windows-2025
defaults:
run:
shell: cmd
strategy:
fail-fast: false
matrix:
python-version: ['3.12']
platform: [x64]
cuda-version: ['12'] # TODO: Re-enable '13' after updating to OpenCV 4.13+
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
OPENCV_TEST_DATA_PATH: ${{ github.workspace }}\opencv_extra\testdata
PlatformToolset: v143
steps:
- name: Cleanup
shell: bash
run: |
rm -rf ./* || true
rm -rf ./.??* || true
working-directory: ${{ github.workspace }}
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.platform }}
- name: Download a wheel accordingly to matrix
uses: actions/download-artifact@v4
with:
name: wheel-cuda${{ matrix.cuda-version }}-${{ matrix.platform }}
path: wheelhouse/
- name: Package installation
run: |
cd ${{ github.workspace }}/tests
&python -m pip install --user --no-warn-script-location (ls "../wheelhouse/opencv*.whl")
if ($LastExitCode -ne 0) {throw $LastExitCode}
python get_build_info.py
shell: powershell
- name: Run tests
run: |
cd ${{ github.workspace }}/tests
python test.py