Skip to content

Commit 4558fdc

Browse files
authored
Qualcomm AI Engine Direct - Add QNN Windows MSVC Build to CI (#20802)
### Summary - This PR adds a CI workflow that validates the QNN Windows MSVC build. - Fix Linux-specific file path to Windows-compatible. - Add helper function in `backends/qualcomm/scripts/build.ps1` to validate the CMake version after dev-shell activation. ### Test plan Passing `.github/workflows/qnn-windows-msvc.yml`.
1 parent 8daa7f8 commit 4558fdc

4 files changed

Lines changed: 261 additions & 34 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright (c) Qualcomm Innovation Center, Inc.
2+
# All rights reserved
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
$ErrorActionPreference = "Stop"
8+
9+
conda create --yes --quiet -n et python=3.12
10+
conda activate et
11+
12+
# Install CI requirements
13+
pip install -r .ci/docker/requirements-ci.txt
14+
15+
# Provision the QNN SDK
16+
if ($env:QNN_SDK_ROOT -and (Test-Path -Path $env:QNN_SDK_ROOT)) {
17+
Write-Host "Using existing QNN SDK at $env:QNN_SDK_ROOT"
18+
} else {
19+
# Resolve the QNN_VERSION and QNN_ZIP_URL
20+
$qnnInfo = python -c "import sys; sys.path.insert(0, r'backends\qualcomm\scripts'); import download_qnn_sdk as d; print(d.QNN_VERSION); print(d.QNN_ZIP_URL)"
21+
if ($LASTEXITCODE -ne 0 -or $qnnInfo.Count -lt 2) {
22+
Write-Error "Failed to read QNN_VERSION and QNN_ZIP_URL from download_qnn_sdk.py."
23+
exit 1
24+
}
25+
$qnnVersion = $qnnInfo[0].Trim()
26+
$qnnZipUrl = $qnnInfo[1].Trim()
27+
28+
$qnnInstallDir = Join-Path $env:TEMP "qnn"
29+
New-Item -Path $qnnInstallDir -ItemType Directory -Force | Out-Null
30+
$qnnZip = Join-Path $env:TEMP "qnn_sdk.zip"
31+
Write-Host "Downloading QNN SDK v$qnnVersion ..."
32+
$ProgressPreference = "SilentlyContinue"
33+
Invoke-WebRequest -Uri $qnnZipUrl -OutFile $qnnZip
34+
Write-Host "Extracting QNN SDK ..."
35+
Expand-Archive -Path $qnnZip -DestinationPath $qnnInstallDir -Force
36+
Remove-Item -Path $qnnZip -Force
37+
38+
$env:QNN_SDK_ROOT = Join-Path $qnnInstallDir "qairt\$qnnVersion"
39+
Write-Host "Set QNN_SDK_ROOT=$env:QNN_SDK_ROOT"
40+
}
41+
42+
if (-not (Test-Path -Path (Join-Path $env:QNN_SDK_ROOT "include\QNN"))) {
43+
Write-Error "QNN SDK layout unexpected: missing include\QNN under $env:QNN_SDK_ROOT"
44+
exit 1
45+
}
46+
47+
# Test x86_64 Windows host build
48+
.\backends\qualcomm\scripts\build.ps1 -SkipArm64Windows -Release
49+
50+
$x86Artifacts = @(
51+
"build-x86_64-windows\backends\qualcomm\Release\PyQnnManagerAdaptor*.pyd",
52+
"build-x86_64-windows\backends\qualcomm\Release\qnn_executorch_backend.dll",
53+
"build-x86_64-windows\examples\qualcomm\executor_runner\Release\qnn_executor_runner.exe"
54+
)
55+
foreach ($artifact in $x86Artifacts) {
56+
if (-not (Get-ChildItem -Path $artifact -ErrorAction SilentlyContinue)) {
57+
Write-Error "ERROR: x86_64 artifact not found: $artifact"
58+
exit 1
59+
}
60+
}
61+
62+
# The ARM64 MSVC toolchain is currently not installed in the Windows CI
63+
# environment. Enabling this build configuration results in build failures
64+
# due to the missing ARM64 platform definition.
65+
# `.\backends\qualcomm\scripts\build.ps1 -SkipX86Windows -Release`
66+
#
67+
# Temporarily disable this build option until ARM64 MSVC support is available
68+
# in CI. The configuration can be re-enabled in a future update.
69+
70+
Write-Host "PASSED: QNN backend Windows MSVC build completed"
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Test QNN Windows MSVC build
2+
3+
# Changes to backends/qualcomm/, top-level CMake files, extension/,
4+
# examples/, runtime/, and other shared infrastructure can affect
5+
# the QNN Windows MSVC build. Rather than maintaining a fragile list
6+
# of relevant path filters, this workflow runs on every PR to ensure
7+
# build coverage.
8+
#
9+
# Reasons for keeping qnn-windows-msvc.yml separate from test-backend-qnn.yml:
10+
#
11+
# - Two workflows are triggered by different tags.
12+
# - test-backend-qnn.yml runs under ciflow/nightly/*.
13+
# - qnn-windows-msvc.yml runs under ciflow/trunk/*.
14+
# Merging them would introduce the behavior change to the existing flow.
15+
#
16+
# - Workflow reruns are more efficient when they remain separate.
17+
# A Windows-only failure would still require rerunning jobs in test-backend-qnn.yml
18+
# if they are combined into a single workflow, resulting in unnecessary CI
19+
# resource consumption (and vice versa).
20+
#
21+
# - Failure signals are clearer when the workflows are isolated.
22+
# With a combined workflow, additional inspection of the job list would be required to
23+
# identify the root cause of a failing status. Keeping the workflows separate provides
24+
# distinct top-level CI statuses, making the failure domain immediately obvious.
25+
#
26+
# For now, qnn-windows-msvc.yml should remain separate from trunk.yml and pull.yml:
27+
#
28+
# - trunk.yml is only triggered for PRs that modify files matching:
29+
# - .ci/docker/ci_commit_pins/pytorch.txt
30+
# - .ci/scripts/**
31+
# - zephyr/**
32+
# As a result, trunk.yml would not run for PRs that touch backends/qualcomm/**.
33+
#
34+
# - pull.yml runs on every PR without path filters, but currently contains only
35+
# Linux jobs. Keeping qnn-windows-msvc.yml as a standalone workflow provides
36+
# independent status visibility and more efficient reruns for QNN Windows build.
37+
#
38+
# Once the QNN Windows CI path has demonstrated sufficient stability, we can revisit
39+
# whether it makes sense to consolidate qnn-windows-msvc.yml into pull.yml.
40+
41+
on:
42+
push:
43+
branches:
44+
- main
45+
- release/*
46+
tags:
47+
- ciflow/trunk/*
48+
pull_request:
49+
workflow_dispatch:
50+
51+
concurrency:
52+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.event_name == 'workflow_dispatch' }}
53+
cancel-in-progress: true
54+
55+
permissions:
56+
contents: read
57+
58+
jobs:
59+
build-qnn-windows-msvc:
60+
name: build-qnn-windows-msvc
61+
uses: pytorch/test-infra/.github/workflows/windows_job.yml@main
62+
with:
63+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
64+
timeout: 90
65+
script: |
66+
git config --global http.sslBackend openssl
67+
git submodule update --init --recursive
68+
conda init powershell
69+
powershell -Command "& {
70+
Set-PSDebug -Trace 1
71+
\$ErrorActionPreference = 'Stop'
72+
\$PSNativeCommandUseErrorActionPreference = \$true
73+
.ci/scripts/build-qnn-windows-msvc.ps1
74+
}"

backends/qualcomm/runtime/backends/QnnBackendUnifiedRegistry.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <executorch/backends/qualcomm/runtime/backends/lpai/LpaiBackend.h>
1717
#include <executorch/backends/qualcomm/runtime/backends/lpai/LpaiDevice.h>
1818

19+
#include <pal/Path.h>
20+
1921
#include <string>
2022

2123
namespace executorch {
@@ -154,7 +156,8 @@ Error QnnBackendUnifiedRegistry::GetOrCreateBackendBundle(
154156
}
155157
// 5. Create QnnSystemImplementation and load qnn library
156158
std::unique_ptr<QnnSystemImplementation> system_implementation =
157-
std::make_unique<QnnSystemImplementation>("libQnnSystem.so");
159+
std::make_unique<QnnSystemImplementation>(
160+
pal::path::GetLibraryName("QnnSystem"));
158161
ret = system_implementation->Load();
159162
ET_CHECK_OR_RETURN_ERROR(
160163
ret == Error::Ok, Internal, "Fail to load Qnn system library");

0 commit comments

Comments
 (0)