diff --git a/backends/qualcomm/CMakeLists.txt b/backends/qualcomm/CMakeLists.txt index c75b9abeeff..30589292850 100644 --- a/backends/qualcomm/CMakeLists.txt +++ b/backends/qualcomm/CMakeLists.txt @@ -77,7 +77,11 @@ if(${ANDROID}) find_library(android_log log) endif() -add_compile_options("-Wall" "-Werror" "-fvisibility=hidden") +if(MSVC) + add_compile_options("/wd4996") +else() + add_compile_options("-Wall" "-Werror" "-fvisibility=hidden") +endif() add_compile_definitions(C10_USING_CUSTOM_GENERATED_MACROS) # GNU emits warning for ignored attributes Unfortunately, we use @@ -89,21 +93,26 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - # strip symbols - add_link_options(LINKER:-s,--gc-sections) - if(${CMAKE_SYSTEM_PROCESSOR} MATCHES Hexagon) - add_compile_options( - "-Os" - "-ffunction-sections" - "-fdata-sections" - "-frtti" - "-fno-exceptions" - "-fomit-frame-pointer" - "-fno-asynchronous-unwind-tables" - ) + if(MSVC) + add_compile_options("/O2") else() - - add_compile_options("-O3" "-ffunction-sections" "-fdata-sections" "-frtti") + # strip symbols + add_link_options(LINKER:-s,--gc-sections) + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES Hexagon) + add_compile_options( + "-Os" + "-ffunction-sections" + "-fdata-sections" + "-frtti" + "-fno-exceptions" + "-fomit-frame-pointer" + "-fno-asynchronous-unwind-tables" + ) + else() + add_compile_options( + "-O3" "-ffunction-sections" "-fdata-sections" "-frtti" + ) + endif() endif() endif() @@ -275,16 +284,27 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES Hexagon) ) endif() -set_target_properties( - qnn_executorch_backend PROPERTIES LINK_FLAGS "-Wl,-rpath='$ORIGIN'" -) +if(MSVC) + target_compile_definitions( + qnn_executorch_backend PRIVATE QNN_EXECUTORCH_BUILDING_DLL + ) + set_target_properties( + qnn_executorch_backend PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON + ) +else() + set_target_properties( + qnn_executorch_backend PROPERTIES LINK_FLAGS "-Wl,-rpath='$ORIGIN'" + ) +endif() target_link_libraries( shared_buffer PRIVATE qnn_executorch_logging ${CMAKE_DL_LIBS} ) # # add linker option # -executorch_target_link_options_shared_lib(qnn_executorch_backend) +if(NOT MSVC) + executorch_target_link_options_shared_lib(qnn_executorch_backend) +endif() # # add sources @@ -316,7 +336,7 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES Hexagon) endif() # QNN pybind -if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64|AMD64") add_subdirectory( ${EXECUTORCH_SOURCE_DIR}/third-party/pybind11 ${CMAKE_CURRENT_BINARY_DIR}/pybind11 @@ -350,9 +370,13 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") # need to allow exceptions in pybind - set(_pybind_compile_options -Wno-deprecated-declarations -fPIC -frtti - -fexceptions - ) + if(MSVC) + set(_pybind_compile_options /wd4996 /EHsc) + else() + set(_pybind_compile_options -Wno-deprecated-declarations -fPIC -frtti + -fexceptions + ) + endif() target_compile_options( PyQnnManagerAdaptor PUBLIC ${_pybind_compile_options} ) diff --git a/backends/qualcomm/aot/wrappers/CMakeLists.txt b/backends/qualcomm/aot/wrappers/CMakeLists.txt index ffda17cb6eb..2e8a0efb8c6 100644 --- a/backends/qualcomm/aot/wrappers/CMakeLists.txt +++ b/backends/qualcomm/aot/wrappers/CMakeLists.txt @@ -7,9 +7,9 @@ # wrappers target_sources( wrappers - PUBLIC ${CMAKE_CURRENT_LIST_DIR}/TensorWrapper.cpp - ${CMAKE_CURRENT_LIST_DIR}/TensorWrapper.h - PRIVATE ${CMAKE_CURRENT_LIST_DIR}/QuantizeParamsWrapper.cpp + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/TensorWrapper.h + PRIVATE ${CMAKE_CURRENT_LIST_DIR}/TensorWrapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/QuantizeParamsWrapper.cpp ${CMAKE_CURRENT_LIST_DIR}/QuantizeParamsWrapper.h ${CMAKE_CURRENT_LIST_DIR}/OpWrapper.cpp ${CMAKE_CURRENT_LIST_DIR}/OpWrapper.h diff --git a/backends/qualcomm/runtime/backends/CMakeLists.txt b/backends/qualcomm/runtime/backends/CMakeLists.txt index 55714b71ed1..88ab07c3c16 100644 --- a/backends/qualcomm/runtime/backends/CMakeLists.txt +++ b/backends/qualcomm/runtime/backends/CMakeLists.txt @@ -44,7 +44,7 @@ target_sources( ) set(platform target) -if(${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64) +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64|AMD64") set(platform host) endif() diff --git a/backends/qualcomm/scripts/build.ps1 b/backends/qualcomm/scripts/build.ps1 new file mode 100644 index 00000000000..c64d49ce8d0 --- /dev/null +++ b/backends/qualcomm/scripts/build.ps1 @@ -0,0 +1,384 @@ +# Copyright (c) Qualcomm Innovation Center, Inc. +# All rights reserved +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. +# +# Windows PowerShell build script for the Qualcomm AI Engine Direct backend. +# Mirrors backends/qualcomm/scripts/build.sh but targets Windows x86-64 (host) +# and Windows-on-ARM64 (cross-compiled via LLVM/Clang for arm64-windows). +# +# Usage: +# .\backends\qualcomm\scripts\build.ps1 [options] +# +# Options: +# -SkipX86Windows Skip the x86-64 Windows host build (AOT + pybind) +# -SkipArm64Windows Skip the ARM64 Windows cross-compiled build +# -EnableHexagon Enable Hexagon DSP direct-mode skel library build +# -NoClean Incremental build (skip rm of build dir) +# -Release Use Release build type (default: RelWithDebInfo) +# -JobNumber Parallel jobs for cmake --build (default: 16) +# -DspType DSP domain for Hexagon direct-mode (default: 3 = CDSP) + +param( + [switch]$SkipX86Windows, + [switch]$SkipArm64Windows, + [switch]$EnableHexagon, + [switch]$NoClean, + [switch]$Release, + [int]$JobNumber = 16, + [int]$DspType = 3 +) + +# Stop on any error, mirroring bash's set -e. +$ErrorActionPreference = 'Stop' + +# --------------------------------------------------------------------------- +# Validate required environment variables +# --------------------------------------------------------------------------- + +if (-not $env:QNN_SDK_ROOT) { + Write-Error "Please set `$env:QNN_SDK_ROOT to the QNN SDK root directory." + exit 1 +} + +# ARM64 cross-compile requires the LLVM toolchain that ships with VS. +# The caller is expected to have run vcvarsall.bat or Setup-BuildEnv.ps1 so +# that clang-cl and lld-link are on PATH. We validate lazily inside the +# build-arm64-windows block rather than up front, because the user may only +# want the x86 host build. + +if ($EnableHexagon) { + foreach ($var in @('ANDROID_NDK_ROOT', 'HEXAGON_SDK_ROOT', 'HEXAGON_TOOLS_ROOT', 'DSP_VERSION')) { + if (-not (Get-Item "env:$var" -ErrorAction SilentlyContinue)) { + Write-Error "Hexagon build requires `$env:$var to be set." + exit 1 + } + } +} + +# --------------------------------------------------------------------------- +# Derived settings +# --------------------------------------------------------------------------- + +$BuildType = if ($Release) { 'Release' } else { 'RelWithDebInfo' } +$Clean = -not $NoClean + +# Resolve the repo root as the directory three levels above this script +# (backends/qualcomm/scripts/ -> backends/qualcomm/ -> backends/ -> repo root). +$PrjRoot = (Resolve-Path "$PSScriptRoot\..\..\..").Path + +$CmakeX86 = 'build-x86_64-windows' +$CmakeArm64 = 'build-arm64-windows' +$CmakeHexagon = 'build-hexagon' + +# Use the Python that is active in the current environment. +$PythonExe = if ($env:PYTHON_EXECUTABLE) { $env:PYTHON_EXECUTABLE } else { 'python' } + +# --------------------------------------------------------------------------- +# Helper: clean or prepare a build directory +# --------------------------------------------------------------------------- +function Prepare-BuildDir([string]$BuildRoot) { + if ($Clean) { + if (Test-Path $BuildRoot) { + Write-Host "Removing $BuildRoot ..." + Remove-Item -Recurse -Force $BuildRoot + } + New-Item -ItemType Directory -Path $BuildRoot | Out-Null + } else { + # Incremental: flatcc must be rebuilt for the host platform. + # On Windows flatcc is a CMake ExternalProject; there is no Makefile + # to run 'make clean' against, so we remove its stamp files so CMake + # re-runs it on the next configure. + $FlatccStamp = Join-Path $BuildRoot 'third-party\flatcc\src\flatcc_ep-stamp' + if (Test-Path $FlatccStamp) { + Write-Host "Removing flatcc stamp files for incremental rebuild ..." + Remove-Item -Recurse -Force $FlatccStamp + } + } +} + +# --------------------------------------------------------------------------- +# Helper: run cmake configure + build, aborting on failure +# --------------------------------------------------------------------------- +function Run-CMake([string[]]$ConfigArgs, [string]$BuildDir, [string]$Target = 'install') { + Write-Host "`n=== cmake configure ===" -ForegroundColor Cyan + & cmake @ConfigArgs + if ($LASTEXITCODE -ne 0) { throw "cmake configure failed (exit $LASTEXITCODE)" } + + Write-Host "`n=== cmake build (target: $Target) ===" -ForegroundColor Cyan + if ($Target -eq 'install') { + & cmake --build $BuildDir --config $BuildType -j $JobNumber --target install + } else { + & cmake --build $BuildDir --config $BuildType -j $JobNumber + } + if ($LASTEXITCODE -ne 0) { throw "cmake build failed (exit $LASTEXITCODE)" } +} + +# --------------------------------------------------------------------------- +# Block 1: ARM64 Windows cross-compiled build (build-arm64-windows/) +# +# Cross-compiles the ExecuTorch runtime + QNN backend for arm64-windows using +# the LLVM/Clang toolchain bundled with Visual Studio. This produces the +# on-device libraries and example runners for Windows-on-ARM devices. +# +# Differences from the Linux Android block: +# - No Android NDK toolchain file; instead we set CMAKE_SYSTEM_NAME=Windows +# and CMAKE_SYSTEM_PROCESSOR=ARM64 so CMake selects the MSVC/Clang-CL +# cross-compiler for arm64. +# - No ANDROID_ABI / ANDROID_PLATFORM flags. +# - Example runners are built for Windows (no adb push needed). +# --------------------------------------------------------------------------- +if (-not $SkipArm64Windows) { + $BuildRoot = Join-Path $PrjRoot $CmakeArm64 + Prepare-BuildDir $BuildRoot + + $ConfigArgs = @( + $PrjRoot, + "-DCMAKE_INSTALL_PREFIX=$BuildRoot", + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DCMAKE_SYSTEM_NAME=Windows", + "-DCMAKE_SYSTEM_PROCESSOR=ARM64", + "-A", "ARM64", + "-DEXECUTORCH_BUILD_QNN=ON", + "-DEXECUTORCH_BUILD_DEVTOOLS=ON", + "-DEXECUTORCH_BUILD_EXTENSION_LLM=ON", + "-DEXECUTORCH_BUILD_EXTENSION_LLM_RUNNER=ON", + "-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON", + "-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON", + "-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON", + "-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON", + "-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON", + "-DEXECUTORCH_ENABLE_EVENT_TRACER=ON", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-DQNN_SDK_ROOT=$env:QNN_SDK_ROOT", + "-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-B$BuildRoot" + ) + Run-CMake -ConfigArgs $ConfigArgs -BuildDir $BuildRoot + + # Build QNN example runners for arm64-windows + $ExampleRoot = Join-Path $PrjRoot 'examples\qualcomm' + $ExampleBuild = Join-Path $BuildRoot 'examples\qualcomm' + $CmakePrefixPath = "$BuildRoot;$BuildRoot\third-party\gflags" + + $DirectModeFlag = if ($EnableHexagon) { '-DBUILD_DIRECT_MODE=ON' } else { '-DBUILD_DIRECT_MODE=OFF' } + + $ExampleArgs = @( + $ExampleRoot, + "-DCMAKE_SYSTEM_NAME=Windows", + "-DCMAKE_SYSTEM_PROCESSOR=ARM64", + "-A", "ARM64", + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DCMAKE_PREFIX_PATH=$CmakePrefixPath", + "-DSUPPORT_REGEX_LOOKAHEAD=ON", + "-DBUILD_TESTING=OFF", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON", + "-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-DDSP_TYPE=$DspType", + $DirectModeFlag, + "-B$ExampleBuild" + ) + Write-Host "`n=== cmake configure (examples/qualcomm arm64-windows) ===" -ForegroundColor Cyan + & cmake @ExampleArgs + if ($LASTEXITCODE -ne 0) { throw "cmake configure (examples/qualcomm) failed" } + & cmake --build $ExampleBuild --config $BuildType -j $JobNumber + if ($LASTEXITCODE -ne 0) { throw "cmake build (examples/qualcomm) failed" } + + # Build Llama runner for arm64-windows + $LlamaRoot = Join-Path $PrjRoot 'examples\models\llama' + $LlamaBuild = Join-Path $BuildRoot 'examples\models\llama' + + $LlamaArgs = @( + $LlamaRoot, + "-DBUILD_TESTING=OFF", + "-DCMAKE_SYSTEM_NAME=Windows", + "-DCMAKE_SYSTEM_PROCESSOR=ARM64", + "-A", "ARM64", + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DCMAKE_PREFIX_PATH=$CmakePrefixPath", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-B$LlamaBuild" + ) + Write-Host "`n=== cmake configure (examples/models/llama arm64-windows) ===" -ForegroundColor Cyan + & cmake @LlamaArgs + if ($LASTEXITCODE -ne 0) { throw "cmake configure (llama) failed" } + & cmake --build $LlamaBuild --config $BuildType -j $JobNumber + if ($LASTEXITCODE -ne 0) { throw "cmake build (llama) failed" } +} + +# --------------------------------------------------------------------------- +# Block 2: Hexagon DSP direct-mode skel library (build-hexagon/) +# +# Identical in purpose to the Linux script's Hexagon block. Builds the +# DSP-side skel library that runs directly on the Hexagon processor. +# Requires HEXAGON_SDK_ROOT, HEXAGON_TOOLS_ROOT, DSP_VERSION in the +# environment (validated above). +# --------------------------------------------------------------------------- +if ($EnableHexagon) { + $BuildRoot = Join-Path $PrjRoot $CmakeHexagon + Prepare-BuildDir $BuildRoot + + $ConfigArgs = @( + $PrjRoot, + "-DCMAKE_INSTALL_PREFIX=$BuildRoot", + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DEXECUTORCH_BUILD_QNN=ON", + "-DEXECUTORCH_BUILD_XNNPACK=OFF", + "-DEXECUTORCH_BUILD_DEVTOOLS=ON", + "-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON", + "-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON", + "-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON", + "-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON", + "-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON", + "-DEXECUTORCH_ENABLE_EVENT_TRACER=ON", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-DEXECUTORCH_BUILD_PTHREADPOOL=OFF", + "-DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF", + "-DFLATCC_ALLOW_WERROR=OFF", + "-DQNN_SDK_ROOT=$env:QNN_SDK_ROOT", + "-DHEXAGON_SDK_ROOT=$env:HEXAGON_SDK_ROOT", + "-DHEXAGON_TOOLS_ROOT=$env:HEXAGON_TOOLS_ROOT", + "-DDSP_VERSION=$env:DSP_VERSION", + "-DCMAKE_TOOLCHAIN_FILE=$env:HEXAGON_SDK_ROOT\build\cmake\hexagon_toolchain.cmake", + "-DDSP_TYPE=$DspType", + "-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-B$BuildRoot" + ) + Run-CMake -ConfigArgs $ConfigArgs -BuildDir $BuildRoot +} + +# --------------------------------------------------------------------------- +# Block 3: x86-64 Windows host build (build-x86_64-windows/) +# +# Builds the AOT host libraries and the PyQnnManagerAdaptor pybind module. +# This block always runs last (same as the Linux script) because its +# post-build file copies make the Python AOT environment functional. +# +# Differences from the Linux x86_64 block: +# - No -DANDROID_ABI / -DANDROID_PLATFORM on the Llama example cmake +# (the Linux script has a copy-paste bug there; we omit those flags). +# - File copies use PowerShell Copy-Item instead of cp. +# - The pybind .pyd is named PyQnnManagerAdaptor*.pyd on Windows. +# --------------------------------------------------------------------------- +if (-not $SkipX86Windows) { + $BuildRoot = Join-Path $PrjRoot $CmakeX86 + + Prepare-BuildDir $BuildRoot + + $ConfigArgs = @( + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DCMAKE_INSTALL_PREFIX=$BuildRoot", + "-DQNN_SDK_ROOT=$env:QNN_SDK_ROOT", + "-DEXECUTORCH_BUILD_QNN=ON", + "-DEXECUTORCH_BUILD_DEVTOOLS=ON", + "-DEXECUTORCH_BUILD_EXTENSION_LLM=ON", + "-DEXECUTORCH_BUILD_EXTENSION_LLM_RUNNER=ON", + "-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON", + "-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON", + "-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON", + "-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON", + "-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON", + "-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON", + "-DEXECUTORCH_ENABLE_EVENT_TRACER=ON", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-S$PrjRoot", + "-B$BuildRoot" + ) + Run-CMake -ConfigArgs $ConfigArgs -BuildDir $BuildRoot + + # --- Post-build: copy pybind module into the Python-importable location --- + # On Windows the pybind module has a Python ABI tag in its name, e.g. + # PyQnnManagerAdaptor.cp310-win_amd64.pyd. We copy all matching files. + $PyDst = Join-Path $PrjRoot 'backends\qualcomm\python' + Write-Host "`nCopying pybind module to $PyDst ..." -ForegroundColor Cyan + # Remove stale pybind module files first; preserve other files such as .gitignore. + Get-ChildItem $PyDst -ErrorAction SilentlyContinue | + Where-Object { $_.Extension -in '.pyd', '.dll' } | + Remove-Item -Force + + # The multi-config generator (Visual Studio / Ninja Multi-Config) places + # outputs under //. Single-config generators place them + # directly under /. Try both locations. + $PySrcs = @( + Get-ChildItem (Join-Path $BuildRoot "backends\qualcomm\$BuildType\PyQnnManagerAdaptor*") -ErrorAction SilentlyContinue + Get-ChildItem (Join-Path $BuildRoot "backends\qualcomm\PyQnnManagerAdaptor*") -ErrorAction SilentlyContinue + ) | Where-Object { $_.Extension -in '.pyd', '.dll' } | Select-Object -Unique + + if (-not $PySrcs) { + throw "Could not find PyQnnManagerAdaptor.pyd under $BuildRoot\backends\qualcomm\" + } + foreach ($f in $PySrcs) { + Write-Host "`nCopying $($f.FullName) -> $PyDst" + Copy-Item $f.FullName $PyDst -Force + } + + # --- Post-build: copy FlatBuffers schemas for the AOT serialization pipeline --- + Write-Host "`nCopying FlatBuffers schemas ..." -ForegroundColor Cyan + Copy-Item (Join-Path $PrjRoot 'schema\program.fbs') (Join-Path $PrjRoot 'exir\_serialize\program.fbs') -Force + Copy-Item (Join-Path $PrjRoot 'schema\scalar_type.fbs') (Join-Path $PrjRoot 'exir\_serialize\scalar_type.fbs') -Force + + # --- Post-build: initialise tokenizers submodule (needed for LLM runner) --- + # Note: extension/llm/tokenizers is intentionally skipped on Windows in the + # install pipeline (see CLAUDE.md), but the submodule init is still useful + # if the user wants to build the runner manually later. + Write-Host "`nInitialising tokenizers submodule ..." -ForegroundColor Cyan + Push-Location (Join-Path $PrjRoot 'extension\llm\tokenizers') + & git submodule update --init + if ($LASTEXITCODE -ne 0) { Write-Warning "git submodule update --init failed (non-fatal)" } + Pop-Location + + # --- Build QNN example runners for x86-64 Windows --- + $ExampleRoot = Join-Path $PrjRoot 'examples\qualcomm' + $ExampleBuild = Join-Path $BuildRoot 'examples\qualcomm' + $CmakePrefixPath = "$BuildRoot;$BuildRoot\third-party\gflags" + + $ExampleArgs = @( + $ExampleRoot, + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DCMAKE_PREFIX_PATH=$CmakePrefixPath", + "-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-DSUPPORT_REGEX_LOOKAHEAD=ON", + "-DBUILD_TESTING=OFF", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-B$ExampleBuild" + ) + Write-Host "`n=== cmake configure (examples/qualcomm x86-64 Windows) ===" -ForegroundColor Cyan + & cmake @ExampleArgs + if ($LASTEXITCODE -ne 0) { throw "cmake configure (examples/qualcomm) failed" } + & cmake --build $ExampleBuild --config $BuildType -j $JobNumber + if ($LASTEXITCODE -ne 0) { throw "cmake build (examples/qualcomm) failed" } + + # --- Build Llama runner for x86-64 Windows --- + # Note: the Linux script incorrectly passes -DANDROID_ABI and + # -DANDROID_PLATFORM here (copy-paste from the Android block). Those + # flags are omitted here since no Android toolchain is active. + $LlamaRoot = Join-Path $PrjRoot 'examples\models\llama' + $LlamaBuild = Join-Path $BuildRoot 'examples\models\llama' + + $LlamaArgs = @( + $LlamaRoot, + "-DBUILD_TESTING=OFF", + "-DCMAKE_BUILD_TYPE=$BuildType", + "-DCMAKE_PREFIX_PATH=$CmakePrefixPath", + "-DEXECUTORCH_ENABLE_LOGGING=ON", + "-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH", + "-DPYTHON_EXECUTABLE=$PythonExe", + "-B$LlamaBuild" + ) + Write-Host "`n=== cmake configure (examples/models/llama x86-64 Windows) ===" -ForegroundColor Cyan + & cmake @LlamaArgs + if ($LASTEXITCODE -ne 0) { throw "cmake configure (llama) failed" } + & cmake --build $LlamaBuild --config $BuildType -j $JobNumber + if ($LASTEXITCODE -ne 0) { throw "cmake build (llama) failed" } +} + +Write-Host "`nBuild complete." -ForegroundColor Green diff --git a/examples/models/llama/CMakeLists.txt b/examples/models/llama/CMakeLists.txt index 6d5b5cc2566..52bbf27b9b3 100644 --- a/examples/models/llama/CMakeLists.txt +++ b/examples/models/llama/CMakeLists.txt @@ -63,7 +63,11 @@ else() set(CMAKE_TOOLCHAIN_IOS OFF) endif() -set(_common_compile_options -Wno-deprecated-declarations -fPIC) +if(MSVC) + set(_common_compile_options /wd4996) +else() + set(_common_compile_options -Wno-deprecated-declarations -fPIC) +endif() # Let files say "include ". set(_common_include_directories ${EXECUTORCH_ROOT}/..) @@ -186,7 +190,9 @@ endif() # Qnn backend if(TARGET qnn_executorch_backend) list(APPEND link_libraries qnn_executorch_backend) - executorch_target_link_options_shared_lib(qnn_executorch_backend) + if(NOT MSVC) + executorch_target_link_options_shared_lib(qnn_executorch_backend) + endif() endif() # MPS backend diff --git a/examples/models/llama/runner/CMakeLists.txt b/examples/models/llama/runner/CMakeLists.txt index 7c6c5413ab3..31bce16dd12 100644 --- a/examples/models/llama/runner/CMakeLists.txt +++ b/examples/models/llama/runner/CMakeLists.txt @@ -31,6 +31,7 @@ set(llama_runner_srcs runner.cpp ../tokenizer/llama_tiktoken.cpp) if(CMAKE_TOOLCHAIN_IOS OR ANDROID OR APPLE + OR MSVC ) # Building a share library on iOS requires code signing On Android we see # duplicated registration when using shared lib diff --git a/examples/models/llava/CMakeLists.txt b/examples/models/llava/CMakeLists.txt index 1e7cdea22d5..7f61ee019d8 100644 --- a/examples/models/llava/CMakeLists.txt +++ b/examples/models/llava/CMakeLists.txt @@ -60,7 +60,11 @@ else() set(CMAKE_TOOLCHAIN_IOS OFF) endif() -set(_common_compile_options -Wno-deprecated-declarations -fPIC) +if(MSVC) + set(_common_compile_options /wd4996) +else() + set(_common_compile_options -Wno-deprecated-declarations -fPIC) +endif() # Let files say "include ". set(_common_include_directories ${EXECUTORCH_ROOT}/..) diff --git a/examples/qualcomm/CMakeLists.txt b/examples/qualcomm/CMakeLists.txt index d7403030ca6..48dd0904272 100644 --- a/examples/qualcomm/CMakeLists.txt +++ b/examples/qualcomm/CMakeLists.txt @@ -35,7 +35,11 @@ find_package(absl REQUIRED NO_CMAKE_FIND_ROOT_PATH) find_package(executorch CONFIG REQUIRED) target_compile_options(executorch INTERFACE -DET_EVENT_TRACER_ENABLED) -set(_common_compile_options -Wno-deprecated-declarations -fPIC) +if(MSVC) + set(_common_compile_options /wd4996) +else() + set(_common_compile_options -Wno-deprecated-declarations -fPIC) +endif() # # The `__srcs` lists are defined by executorch_load_build_variables. diff --git a/examples/qualcomm/oss_scripts/llama/runner/multimodal_runner/multimodal_runner.h b/examples/qualcomm/oss_scripts/llama/runner/multimodal_runner/multimodal_runner.h index 363ded0f055..360bc44f02c 100644 --- a/examples/qualcomm/oss_scripts/llama/runner/multimodal_runner/multimodal_runner.h +++ b/examples/qualcomm/oss_scripts/llama/runner/multimodal_runner/multimodal_runner.h @@ -69,6 +69,13 @@ inline Modality modality_of(const ModelVersion& model_version) { class QNNMultimodalRunner : public executorch::extension::llm::MultimodalRunner { public: + enum EvalMode { + kKVCached = 0, + kHybrid, + kLookaheadDecoding, + kUnsupported, + }; + explicit QNNMultimodalRunner( std::unique_ptr encoder, std::unique_ptr tok_embedding, @@ -99,13 +106,6 @@ class QNNMultimodalRunner get_encoder_method_meta(); private: - enum EvalMode { - kKVCached = 0, - kHybrid, - kLookaheadDecoding, - kUnsupported, - }; - // Modules std::unique_ptr encoder_; std::unique_ptr tok_embedding_; diff --git a/examples/qualcomm/oss_scripts/llama/runner/runner.h b/examples/qualcomm/oss_scripts/llama/runner/runner.h index 5d03a12f61a..86934558656 100644 --- a/examples/qualcomm/oss_scripts/llama/runner/runner.h +++ b/examples/qualcomm/oss_scripts/llama/runner/runner.h @@ -48,6 +48,13 @@ enum DecoderModelVersion { class Runner : public executorch::extension::llm::IRunner { public: + enum EvalMode { + kKVCached = 0, + kHybrid, + kLookaheadDecoding, + kUnsupported, + }; + explicit Runner( std::unique_ptr module, const std::string& decoder_model, @@ -86,13 +93,6 @@ class Runner : public executorch::extension::llm::IRunner { executorch::runtime::Result get_decoder_model_version(); private: - enum EvalMode { - kKVCached = 0, - kHybrid, - kLookaheadDecoding, - kUnsupported, - }; - std::unique_ptr module_; std::unique_ptr attention_sink_rope_module_; int32_t context_len_{0}; diff --git a/kernels/quantized/CMakeLists.txt b/kernels/quantized/CMakeLists.txt index 0a6dd63f792..2dac38205b4 100644 --- a/kernels/quantized/CMakeLists.txt +++ b/kernels/quantized/CMakeLists.txt @@ -21,7 +21,10 @@ if(NOT EXECUTORCH_ROOT) set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..) endif() -set(_common_compile_options -Wno-deprecated-declarations) +set(_common_compile_options + $<$:/wd4996> + $<$>:-Wno-deprecated-declarations> +) include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake) include(${EXECUTORCH_ROOT}/tools/cmake/Codegen.cmake) diff --git a/setup.py b/setup.py index 85228bd37ae..adaadd96f34 100644 --- a/setup.py +++ b/setup.py @@ -1120,8 +1120,10 @@ def run(self): # noqa C901 dependent_cmake_flags=["EXECUTORCH_BUILD_QNN"], ), BuiltExtension( - src_dir="%CMAKE_CACHE_DIR%/backends/qualcomm/%BUILD_TYPE%/", - src="PyQnnManagerAdaptor.*", + src_dir="backends/qualcomm/%BUILD_TYPE%/", + src=( + "PyQnnManagerAdaptor*.pyd" if _is_windows() else "PyQnnManagerAdaptor.*" + ), modpath="executorch.backends.qualcomm.python.PyQnnManagerAdaptor", dependent_cmake_flags=["EXECUTORCH_BUILD_QNN"], ), diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 67da4833283..43b627f79f8 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -22,6 +22,20 @@ endif() # MARK: - flatbuffers if(WIN32) + # On Windows with the Visual Studio generator, unsetting CMAKE_TOOLCHAIN_FILE is + # not sufficient to force a host (AMD64) build when cross-compiling for ARM64. + # The VS generator propagates the parent's platform (-A ARM64) to child + # ExternalProjects automatically. CMAKE_GENERATOR_PLATFORM overrides it, but + # CMake requires CMAKE_GENERATOR to be set explicitly alongside it. We pass + # the parent's generator string verbatim so the child uses the same VS version + # but targets x64 (the host) and produces a runnable flatc.exe / flatcc.exe. + if(CMAKE_CROSSCOMPILING AND ${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64|arm64|aarch64") + set(_flatbuffers_ep_additional_args + CMAKE_GENERATOR "${CMAKE_GENERATOR}" + CMAKE_GENERATOR_PLATFORM x64) + else() + set(_flatbuffers_ep_additional_args) + endif() set(_executorch_external_project_additional_args) else() # Always use Make to avoid needing to codesign flatc if the project is using @@ -29,6 +43,7 @@ else() set(_executorch_external_project_additional_args CMAKE_GENERATOR "Unix Makefiles" ) + set(_flatbuffers_ep_additional_args) endif() # We use ExternalProject to build flatc from source to force it target the host. @@ -55,11 +70,12 @@ ExternalProject_Add( -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_BYPRODUCTS /bin/flatc ${_executorch_external_project_additional_args} + ${_flatbuffers_ep_additional_args} ) ExternalProject_Get_Property(flatbuffers_ep INSTALL_DIR) add_executable(flatc IMPORTED GLOBAL) add_dependencies(flatc flatbuffers_ep) -if(WIN32 AND NOT CMAKE_CROSSCOMPILING) +if(CMAKE_HOST_WIN32) # flatbuffers does not use CMAKE_BUILD_TYPE. Internally, the build forces # Release config, but from CMake's perspective the build type is always Debug. set_target_properties( @@ -111,12 +127,13 @@ ExternalProject_Add( ${_flatcc_extra_cmake_args} BUILD_BYPRODUCTS /bin/flatcc ${_executorch_external_project_additional_args} + ${_flatbuffers_ep_additional_args} ) file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/third-party/flatcc/lib) ExternalProject_Get_Property(flatcc_ep INSTALL_DIR) add_executable(flatcc_cli IMPORTED GLOBAL) add_dependencies(flatcc_cli flatcc_ep) -if(WIN32 AND NOT CMAKE_CROSSCOMPILING) +if(CMAKE_HOST_WIN32) set_target_properties( flatcc_cli PROPERTIES IMPORTED_LOCATION ${INSTALL_DIR}/bin/flatcc.exe )