From 017b0ca472e64265a918f8c9bd2a7f61c726c376 Mon Sep 17 00:00:00 2001 From: Nick Eubanks Date: Fri, 6 Feb 2026 19:01:40 -0500 Subject: [PATCH 1/2] Add Windows ML EP Catalog Sample with CMake and vcpkg integration - Introduced a new sample demonstrating the WinMLEpCatalog Native C API for managing hardware-accelerated execution providers for machine learning inference on Windows. - Added CMake configuration with presets for various architectures and build types. - Created a PowerShell build script to automate the build process, including prerequisite checks and configuration. - Implemented a batch wrapper for the PowerShell script for easier command-line usage. - Included detailed README documentation covering sample usage, project structure, prerequisites, and build instructions. - Established vcpkg configuration and overlay ports for dependency management, including the Microsoft Windows AI Machine Learning SDK. - Implemented the main sample code to demonstrate provider registration and enumeration using the Windows ML API. --- Samples/WindowsML/README.md | 6 + .../cmake/WinMLEpCatalog/.clang-format | 49 +++ .../WindowsML/cmake/WinMLEpCatalog/.gitignore | 25 ++ .../cmake/WinMLEpCatalog/CMakeLists.txt | 55 +++ .../cmake/WinMLEpCatalog/CMakePresets.json | 167 ++++++++ .../WindowsML/cmake/WinMLEpCatalog/README.md | 328 ++++++++++++++++ .../WindowsML/cmake/WinMLEpCatalog/build.cmd | 20 + .../WindowsML/cmake/WinMLEpCatalog/build.ps1 | 360 ++++++++++++++++++ .../WindowsML/cmake/WinMLEpCatalog/main.cpp | 139 +++++++ .../WinMLEpCatalog/vcpkg-configuration.json | 11 + .../WindowsML/cmake/WinMLEpCatalog/vcpkg.json | 12 + .../portfile.cmake | 149 ++++++++ .../usage | 24 ++ .../vcpkg.json | 20 + 14 files changed, 1365 insertions(+) create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/.clang-format create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/README.md create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/main.cpp create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage create mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json diff --git a/Samples/WindowsML/README.md b/Samples/WindowsML/README.md index 011301bb2..f848a09a6 100644 --- a/Samples/WindowsML/README.md +++ b/Samples/WindowsML/README.md @@ -35,6 +35,12 @@ Windows ML enables high-performance, reliable inferencing of machine learning mo |--------|-------------|--------------| | [cpp-abi](cpp-abi/) | Direct ABI implementation using raw COM interfaces | Automatic ABI header generation, no projections | +### CMake Samples + +| Sample | Description | Key Features | +|--------|-------------|--------------| +| [cmake/WinMLEpCatalog](cmake/WinMLEpCatalog/) | WinMLEpCatalog Native C API with CMake/vcpkg | Native C API, no WinRT dependencies, interactive shell | + ### C# Samples #### Console Applications diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/.clang-format b/Samples/WindowsML/cmake/WinMLEpCatalog/.clang-format new file mode 100644 index 000000000..e371afbc6 --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/.clang-format @@ -0,0 +1,49 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +# Clang-format configuration for WinML EP Catalog Sample + +BasedOnStyle: Microsoft +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +ColumnLimit: 120 + +# Braces +BreakBeforeBraces: Allman +AllowShortBlocksOnASingleLine: Empty +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false + +# Indentation +NamespaceIndentation: None +IndentCaseLabels: false + +# Alignment +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignOperands: true +AlignTrailingComments: true + +# Line breaks +AllowAllParametersOfDeclarationOnNextLine: true +BinPackArguments: false +BinPackParameters: false + +# Includes +SortIncludes: true +IncludeBlocks: Preserve + +# Pointer alignment +PointerAlignment: Left + +# Spaces +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore b/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore new file mode 100644 index 000000000..c995aeff7 --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore @@ -0,0 +1,25 @@ +# Build outputs +out/ +build/ + +# CMake cache +CMakeCache.txt +CMakeFiles/ + +# vcpkg downloads +vcpkg_installed/ + +# Local package overrides (for development/testing) +local_packages/ + +# IDE files +.vs/ +.vscode/ +*.user + +# Compiled files +*.exe +*.dll +*.pdb +*.obj +*.ilk diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt new file mode 100644 index 000000000..1c7f5dbde --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +cmake_minimum_required(VERSION 3.21) + +project(WinMLEpCatalogSample + VERSION 1.0.0 + DESCRIPTION "Windows ML Execution Provider Catalog Sample with ONNX Runtime Integration" + LANGUAGES CXX +) + +# Find the Windows ML package installed via vcpkg +find_package(microsoft-windows-ai-machinelearning CONFIG REQUIRED) + +# C++20 standard for modern features (std::format, etc.) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Create the executable +add_executable(WinMLEpCatalogSample + main.cpp +) + +# Link against the Windows ML API and ONNX Runtime +# WindowsML::Api provides the WinMLEpCatalog* functions +# WindowsML::OnnxRuntime provides access to the ONNX Runtime C/C++ API for creating OrtEnv and registering providers +target_link_libraries(WinMLEpCatalogSample + PRIVATE + WindowsML::Api + WindowsML::OnnxRuntime +) + +# Copy runtime DLLs to the build output directory +# This is required because the Windows ML DLLs must be present alongside the executable +winml_copy_runtime_dlls(WinMLEpCatalogSample) + +# Set Windows-specific compiler options +if(MSVC) + target_compile_options(WinMLEpCatalogSample PRIVATE + /W4 # Warning level 4 + /permissive- # Strict C++ conformance + /Zc:__cplusplus # Report correct __cplusplus value + /EHsc # Enable C++ exception handling + ) + + # Use static runtime for easier deployment (no MSVC runtime dependency) + set_property(TARGET WinMLEpCatalogSample PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + ) +endif() + +# Set subsystem to console (not Windows GUI) +if(WIN32) + set_target_properties(WinMLEpCatalogSample PROPERTIES + WIN32_EXECUTABLE FALSE + ) +endif() diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json new file mode 100644 index 000000000..bfcb29cf7 --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json @@ -0,0 +1,167 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "base", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + }, + { + "name": "base-vs", + "hidden": true, + "generator": "Visual Studio 17 2022", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + }, + { + "name": "x64-debug", + "displayName": "x64 Debug", + "description": "Build for x64 architecture in Debug mode", + "inherits": "base", + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "VCPKG_TARGET_TRIPLET": "x64-windows" + } + }, + { + "name": "x64-release", + "displayName": "x64 Release", + "description": "Build for x64 architecture in Release mode", + "inherits": "base", + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "VCPKG_TARGET_TRIPLET": "x64-windows" + } + }, + { + "name": "arm64-debug", + "displayName": "ARM64 Debug", + "description": "Build for ARM64 architecture in Debug mode", + "inherits": "base", + "architecture": { + "value": "arm64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "VCPKG_TARGET_TRIPLET": "arm64-windows" + } + }, + { + "name": "arm64-release", + "displayName": "ARM64 Release", + "description": "Build for ARM64 architecture in Release mode", + "inherits": "base", + "architecture": { + "value": "arm64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "VCPKG_TARGET_TRIPLET": "arm64-windows" + } + }, + { + "name": "x64-debug-vs", + "displayName": "x64 Debug (VS)", + "description": "Build for x64 architecture in Debug mode (Visual Studio generator)", + "inherits": "base-vs", + "architecture": { + "value": "x64", + "strategy": "set" + }, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-windows" + } + }, + { + "name": "x64-release-vs", + "displayName": "x64 Release (VS)", + "description": "Build for x64 architecture in Release mode (Visual Studio generator)", + "inherits": "base-vs", + "architecture": { + "value": "x64", + "strategy": "set" + }, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-windows" + } + }, + { + "name": "arm64-debug-vs", + "displayName": "ARM64 Debug (VS)", + "description": "Build for ARM64 architecture in Debug mode (Visual Studio generator)", + "inherits": "base-vs", + "architecture": { + "value": "ARM64", + "strategy": "set" + }, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm64-windows" + } + }, + { + "name": "arm64-release-vs", + "displayName": "ARM64 Release (VS)", + "description": "Build for ARM64 architecture in Release mode (Visual Studio generator)", + "inherits": "base-vs", + "architecture": { + "value": "ARM64", + "strategy": "set" + }, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm64-windows" + } + } + ], + "buildPresets": [ + { + "name": "x64-debug", + "configurePreset": "x64-debug" + }, + { + "name": "x64-release", + "configurePreset": "x64-release" + }, + { + "name": "arm64-debug", + "configurePreset": "arm64-debug" + }, + { + "name": "arm64-release", + "configurePreset": "arm64-release" + }, + { + "name": "x64-debug-vs", + "configurePreset": "x64-debug-vs", + "configuration": "Debug" + }, + { + "name": "x64-release-vs", + "configurePreset": "x64-release-vs", + "configuration": "Release" + }, + { + "name": "arm64-debug-vs", + "configurePreset": "arm64-debug-vs", + "configuration": "Debug" + }, + { + "name": "arm64-release-vs", + "configurePreset": "arm64-release-vs", + "configuration": "Release" + } + ] +} diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/README.md b/Samples/WindowsML/cmake/WinMLEpCatalog/README.md new file mode 100644 index 000000000..fdc36aecb --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/README.md @@ -0,0 +1,328 @@ +# Windows ML EP Catalog Sample (CMake/Native C API) + +This sample demonstrates the **WinMLEpCatalog Native C API** for discovering and managing hardware-accelerated execution providers (EPs) for machine learning inference on Windows. The sample uses CMake and vcpkg for cross-platform-style builds without Visual Studio project files. + +## Overview + +The WinMLEpCatalog API is a native C API that provides low-level access to Windows ML's execution provider infrastructure. Unlike the WinRT/COM interfaces, this API: + +- **Has no WinRT dependencies** — pure C function calls with handle-based resource management +- **Is easy to integrate** — single header file (`WinMLEpCatalog.h`) with simple function signatures +- **Supports async operations** — progress callbacks and cancellation for long-running operations +- **Works with any build system** — CMake, Makefiles, or direct compiler invocation + +This sample showcases: + +- Creating an ONNX Runtime environment (OrtEnv) +- Creating and releasing a catalog handle +- Enumerating all registered execution providers +- Inspecting provider metadata (name, version, state, certification) +- Preparing providers with `EnsureReady` (sync) +- Registering prepared providers with ONNX Runtime +- Verifying registered EP devices + +## Key Features + +### ONNX Runtime Integration + +This sample demonstrates the complete workflow for registering certified execution providers with ONNX Runtime, matching the behavior of the `ExecutionProviderCatalog::RegisterCertifiedProviders` WinRT API: + +```cpp +// Initialize ORT API +const OrtApiBase* ortApiBase = OrtGetApiBase(); +const OrtApi* ortApi = ortApiBase->GetApi(ORT_API_VERSION); +Ort::InitApi(ortApi); + +// Create ORT environment +Ort::Env ortEnv(ORT_LOGGING_LEVEL_WARNING, "MyApp"); + +// Register provider library after EnsureReady +std::wstring libraryPath = Utf8ToWide(provider.libraryPath); +ortEnv.RegisterExecutionProviderLibrary(provider.name.c_str(), libraryPath); + +// Verify registered providers +auto epDevices = ortEnv.GetEpDevices(); +``` + +### Execution Provider Discovery + +Enumerate all available execution providers registered on the system: + +```cpp +WinMLEpCatalogEnumProviders(catalog, callback, context); +``` + +The callback receives information about each provider including: +- Provider name (e.g., `ContosoExecutionProvider`, `DmlExecutionProvider`) +- Version string +- Package family name +- Ready state (`Ready`, `NotReady`, `NotPresent`) +- Certification status + +### Provider Preparation + +Before using an execution provider, it must be prepared. This may involve downloading and installing the provider package: + +```cpp +// Synchronous (blocking) +WinMLEpEnsureReady(epHandle, &result); + +// Asynchronous (with progress) +WinMLEpEnsureReadyAsync(epHandle, &asyncBlock); +``` + +### Path Retrieval + +After preparation, retrieve the paths needed to load the provider: + +```cpp +WinMLEpGetLibraryPath(epHandle, bufferSize, buffer, &used); +WinMLEpGetPackageRootPath(epHandle, bufferSize, buffer, &used); +``` + +## When to Use This Approach + +**Choose the Native C API when:** + +- Integrating with C codebases or C-compatible FFI boundaries +- Building cross-platform applications that target Windows +- Requiring minimal dependencies (no WinRT/COM overhead) +- Working with build systems that don't easily support WinRT +- Need precise control over async operation lifetime and cancellation + +## Project Structure + +``` +WinMLEpCatalog/ +├── main.cpp # Sample implementation (all code in one file) +├── CMakeLists.txt # CMake build configuration +├── CMakePresets.json # Build presets (x64/arm64, Debug/Release) +├── vcpkg.json # Package manifest +├── vcpkg-configuration.json # vcpkg registry configuration +├── vcpkg_ports/ # Local vcpkg port overlay +│ └── microsoft-windows-ai-machinelearning/ +│ ├── portfile.cmake # Package download and install script +│ ├── vcpkg.json # Port metadata +│ └── usage # CMake integration instructions +├── build.ps1 # Build helper script +├── build.cmd # Batch wrapper for build.ps1 +└── README.md # This file +``` + +## Prerequisites + +- **Visual Studio 2022** with C++ development workload +- **CMake** 3.21 or later +- **vcpkg** (will be configured automatically if `VCPKG_ROOT` is set) +- **Ninja** (optional; required only when using the Ninja generator) + +### Installing Prerequisites + +```powershell +# Install CMake +winget install Kitware.CMake + +# Install Ninja (optional) +winget install Ninja-build.Ninja + +# Clone and bootstrap vcpkg +git clone https://github.com/microsoft/vcpkg.git C:\vcpkg +C:\vcpkg\bootstrap-vcpkg.bat +$env:VCPKG_ROOT = "C:\vcpkg" +``` + +## Building + +### Using the Build Script (Recommended) + +The included PowerShell script handles all build steps: + +```powershell +# Build Debug for current platform (auto-detected) +.\build.ps1 + +# Build with the Visual Studio generator (no Ninja required) +.\build.ps1 -Generator VisualStudio + +# Require Ninja (fails if Ninja is not installed) +.\build.ps1 -Generator Ninja + +# Build Release for x64 +.\build.ps1 -Configuration Release -Platform x64 + +# Build Debug for ARM64 +.\build.ps1 -Configuration Debug -Platform arm64 + +# Clean and rebuild +.\build.ps1 -Clean +``` + +### Manual Build Steps + +If you prefer manual control: + +```powershell +# 1. Set vcpkg root (if not already in environment) +$env:VCPKG_ROOT = "C:\path\to\vcpkg" + +# 2. Configure with CMake preset +cmake --preset x64-debug + +# Or configure with Visual Studio generator preset +cmake --preset x64-debug-vs + +# 3. Build +cmake --build out/build/x64-debug + +# Or for Visual Studio generator: +cmake --build out/build/x64-debug-vs --config Debug + +# 4. Run +.\out\build\x64-debug\WinMLEpCatalogSample.exe +``` + +### Visual Studio + +You can also open this folder directly in Visual Studio 2022: + +1. Open Visual Studio 2022 +2. Select **File > Open > Folder** +3. Navigate to the `WinMLEpCatalog` directory +4. Visual Studio will detect `CMakePresets.json` and configure automatically +5. Select the desired preset from the configuration dropdown +6. Build with **Build > Build All** (Ctrl+Shift+B) + +## Running the Sample + +After building, run the executable: + +``` +.\out\build\x64-debug\WinMLEpCatalogSample.exe +``` + +### Interactive Shell Commands + +The sample provides an interactive shell for exploring the API: + +| Command | Description | +|---------|-------------| +| `help` | Show available commands | +| `list` | List all registered execution providers | +| `select <#>` | Select a provider by index number | +| `info` | Show detailed info for selected provider | +| `ensure` | Prepare selected provider (async with progress) | +| `ensure-sync` | Prepare selected provider (synchronous) | +| `path` | Show library and package paths | +| `exit` | Exit the program | + +### Example Session + +``` +========================================== + Windows ML Execution Provider Catalog + Flat-C API Sample +========================================== +Catalog created successfully. + +======================================== + WinML EP Catalog - Interactive Shell +======================================== +Type 'help' for available commands. + + # Name State Version +------------------------------------------------------------ + 0 ContosoExecutionProvider NotReady 1.0.0 + +Total: 1 provider(s) + +winml> select 0 +Selected: ContosoExecutionProvider + +winml [ContosoExecutionProvider]> info + +Execution Provider Info: + Name: ContosoExecutionProvider + Version: 1.0.0 + Package Family Name: Microsoft.AI.MachineLearning.Contoso_8wekyb3d8bbwe + Ready State: NotReady + Certification: Certified + +winml [ContosoExecutionProvider]> ensure +Ensuring 'ContosoExecutionProvider' is ready (asynchronous)... + (Press ESC to cancel) + [==============================] 100% +Result: + Status: S_OK + Library Path: C:\Program Files\WindowsApps\...\onnxruntime_contoso.dll + Package Root Path: C:\Program Files\WindowsApps\... + +winml [ContosoExecutionProvider]> exit +Goodbye. +``` + +## API Reference + +### Catalog Management + +| Function | Description | +|----------|-------------| +| `WinMLEpCatalogCreate()` | Create a catalog instance | +| `WinMLEpCatalogRelease()` | Release catalog resources | +| `WinMLEpCatalogEnumProviders()` | Enumerate all providers via callback | +| `WinMLEpCatalogFindProvider()` | Find a specific provider by name | + +### Provider Operations + +| Function | Description | +|----------|-------------| +| `WinMLEpEnsureReady()` | Synchronously prepare a provider | +| `WinMLEpEnsureReadyAsync()` | Start async preparation | +| `WinMLEpEnsureReadyResult()` | Get async operation result | +| `WinMLEpGetLibraryPath()` | Get provider DLL path | +| `WinMLEpGetPackageRootPath()` | Get package root directory | + +### Async Operations + +| Function | Description | +|----------|-------------| +| `WinMLAsyncGetStatus()` | Poll async operation status | +| `WinMLAsyncCancel()` | Request cancellation | +| `WinMLAsyncClose()` | Release async operation resources | + +## Updating the Package Version + +The Windows ML package version is defined in the vcpkg overlay port. To update: + +1. Open `vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake` +2. Find the `WINML_EXPERIMENTAL_VERSION` variable near the top +3. Update to the new version: + ```cmake + set(WINML_EXPERIMENTAL_VERSION "2.0.228-experimental") + ``` +4. Delete the `out/` directory and rebuild + +## Troubleshooting + +### "Failed to create EP catalog" + +This typically means: +- Windows ML runtime DLLs are not in the application directory +- Windows version is not supported (requires Windows 11 24H2+) +- The `winml_copy_runtime_dlls()` CMake function did not run + +**Solution:** Ensure the build completed successfully and DLLs were copied to the output directory. + +### "vcpkg not found" + +**Solution:** Set the `VCPKG_ROOT` environment variable: +```powershell +$env:VCPKG_ROOT = "C:\path\to\vcpkg" +``` + +### Build fails with "package not found" + +The overlay port may not be found. Ensure you're building from the sample directory: +```powershell +cd samples\WindowsAppSDK-Samples\Samples\WindowsML\cmake\WinMLEpCatalog +.\build.ps1 +``` diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd b/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd new file mode 100644 index 000000000..109bb6c7a --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd @@ -0,0 +1,20 @@ +@echo off +REM Copyright (C) Microsoft Corporation. All rights reserved. +REM +REM Simple batch wrapper for build.ps1 +REM Usage: build.cmd [Debug|Release] [x64|arm64] [Ninja|VisualStudio] +REM + +setlocal + +set CONFIG=%1 +set PLATFORM=%2 +set GENERATOR=%3 + +if "%CONFIG%"=="" set CONFIG=Debug + +if "%GENERATOR%"=="" ( + powershell -ExecutionPolicy Bypass -File "%~dp0build.ps1" -Configuration %CONFIG% -Platform %PLATFORM% +) else ( + powershell -ExecutionPolicy Bypass -File "%~dp0build.ps1" -Configuration %CONFIG% -Platform %PLATFORM% -Generator %GENERATOR% +) diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 b/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 new file mode 100644 index 000000000..c6bdc95ad --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 @@ -0,0 +1,360 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +<# +.SYNOPSIS + Builds the WinML EP Catalog Sample using CMake and vcpkg. + +.DESCRIPTION + This script automates the build process for the WinMLEpCatalog sample. + It handles: + - Checking prerequisites (CMake, vcpkg, Visual Studio) + - Setting up VCPKG_ROOT if not already configured + - Configuring and building the project using CMake presets + +.PARAMETER Configuration + Build configuration: Debug or Release. Default: Debug + +.PARAMETER Platform + Target platform: x64 or arm64. Default: Auto-detect from host + +.PARAMETER Generator + Build generator: Auto, Ninja, or VisualStudio. Default: Auto (uses Ninja if installed) + +.PARAMETER VcpkgRoot + Path to vcpkg installation. Default: Uses VCPKG_ROOT environment variable + +.PARAMETER Clean + If specified, removes the build directory before building. + +.EXAMPLE + .\build.ps1 + # Builds Debug configuration for the current platform + +.EXAMPLE + .\build.ps1 -Configuration Release -Platform arm64 + # Builds Release configuration for ARM64 + +.EXAMPLE + .\build.ps1 -Generator VisualStudio + # Builds using the Visual Studio generator (no Ninja required) + +.EXAMPLE + .\build.ps1 -Clean -Configuration Debug + # Cleans and rebuilds Debug configuration +#> + +[CmdletBinding()] +param( + [ValidateSet('Debug', 'Release')] + [string]$Configuration = 'Debug', + + [ValidateSet('x64', 'arm64')] + [string]$Platform, + + [ValidateSet('Auto', 'Ninja', 'VisualStudio')] + [string]$Generator = 'Auto', + + [string]$VcpkgRoot, + + [switch]$Clean +) + +Set-StrictMode -Version 2.0 +$ErrorActionPreference = 'Stop' + +# ============================================================================ +# Helper Functions +# ============================================================================ + +function Test-CommandExists { + param([string]$Command) + $null -ne (Get-Command $Command -ErrorAction SilentlyContinue) +} + +function Get-HostArchitecture { + $arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture + switch ($arch) { + 'X64' { return 'x64' } + 'Arm64' { return 'arm64' } + default { return 'x64' } + } +} + +function Write-Header { + param([string]$Message) + Write-Host "" + Write-Host "========================================" -ForegroundColor Cyan + Write-Host " $Message" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan +} + +function Write-Step { + param([string]$Message) + Write-Host "" + Write-Host "[*] $Message" -ForegroundColor Yellow +} + +function Write-Success { + param([string]$Message) + Write-Host "[OK] $Message" -ForegroundColor Green +} + +function Write-ErrorMessage { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red +} + +function Enter-VsDevEnvironment { + param([string]$Arch) + + # Find Visual Studio installation + $vswherePath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + if (-not (Test-Path $vswherePath)) { + $vswherePath = "${env:ProgramFiles}\Microsoft Visual Studio\Installer\vswhere.exe" + } + + if (-not (Test-Path $vswherePath)) { + Write-ErrorMessage "vswhere not found. Please install Visual Studio 2022 or later." + return $false + } + + $vsPath = & $vswherePath -latest -property installationPath + if (-not $vsPath) { + Write-ErrorMessage "Visual Studio installation not found." + return $false + } + + $devShellModule = Join-Path $vsPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + if (-not (Test-Path $devShellModule)) { + Write-ErrorMessage "VS DevShell module not found at: $devShellModule" + return $false + } + + Write-Host " Visual Studio: $vsPath" + + # Import the DevShell module and enter the environment + Import-Module $devShellModule + Enter-VsDevShell -VsInstallPath $vsPath -DevCmdArguments "-arch=$Arch" -SkipAutomaticLocation + + return $true +} + +# ============================================================================ +# Main Script +# ============================================================================ + +Write-Header "WinML EP Catalog Sample Build" + +# Auto-detect platform if not specified +if (-not $Platform) { + $Platform = Get-HostArchitecture + Write-Host "Auto-detected platform: $Platform" +} + +# Select generator +if ($Generator -eq 'Auto') { + if (Test-CommandExists 'ninja') { + $Generator = 'Ninja' + } + else { + $Generator = 'VisualStudio' + } +} + +# Determine preset name +$presetSuffix = if ($Generator -eq 'VisualStudio') { '-vs' } else { '' } +$PresetName = "$Platform-$($Configuration.ToLower())$presetSuffix" +Write-Host "Build preset: $PresetName" +Write-Host "Generator: $Generator" + +# ============================================================================ +# Check Prerequisites +# ============================================================================ + +Write-Step "Checking prerequisites..." + +# Check CMake +if (-not (Test-CommandExists 'cmake')) { + Write-ErrorMessage "CMake not found. Please install CMake 3.21 or later." + Write-Host " Install with: winget install Kitware.CMake" -ForegroundColor Gray + exit 1 +} + +$cmakeVersion = (cmake --version | Select-Object -First 1) +Write-Host " CMake: $cmakeVersion" + +# Check Ninja +if ($Generator -eq 'Ninja') { + if (Test-CommandExists 'ninja') { + $ninjaVersion = (ninja --version) + Write-Host " Ninja: $ninjaVersion" + } + else { + Write-ErrorMessage "Ninja not found. Install Ninja or use -Generator VisualStudio." + exit 1 + } +} +else { + if (Test-CommandExists 'ninja') { + $ninjaVersion = (ninja --version) + Write-Host " Ninja: $ninjaVersion (not required for Visual Studio generator)" + } + else { + Write-Host " Ninja: Not required (using Visual Studio generator)" -ForegroundColor Yellow + } +} + +# Check vcpkg +if ($VcpkgRoot) { + $env:VCPKG_ROOT = $VcpkgRoot +} + +# Always try to find the windows-ml submodule vcpkg first (preferred) +$windowsMlVcpkg = Resolve-Path "$PSScriptRoot\..\..\..\..\..\..\external\vcpkg" -ErrorAction SilentlyContinue +if ($windowsMlVcpkg -and (Test-Path "$windowsMlVcpkg\vcpkg.exe")) { + $env:VCPKG_ROOT = $windowsMlVcpkg.Path + Write-Host " Using windows-ml vcpkg: $env:VCPKG_ROOT" +} +elseif (-not $env:VCPKG_ROOT -or -not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) { + # Try to find vcpkg in common locations + $possiblePaths = @( + "$env:USERPROFILE\vcpkg", + "C:\vcpkg", + "C:\src\vcpkg" + ) + + foreach ($path in $possiblePaths) { + $resolvedPath = Resolve-Path $path -ErrorAction SilentlyContinue + if ($resolvedPath -and (Test-Path "$resolvedPath\vcpkg.exe")) { + $env:VCPKG_ROOT = $resolvedPath.Path + Write-Host " Found vcpkg at: $env:VCPKG_ROOT" + break + } + } +} + +if (-not $env:VCPKG_ROOT -or -not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) { + Write-ErrorMessage "vcpkg not found. Please set VCPKG_ROOT or use -VcpkgRoot parameter." + Write-Host " To install vcpkg:" -ForegroundColor Gray + Write-Host " git clone https://github.com/microsoft/vcpkg.git" -ForegroundColor Gray + Write-Host " .\vcpkg\bootstrap-vcpkg.bat" -ForegroundColor Gray + Write-Host " set VCPKG_ROOT=" -ForegroundColor Gray + exit 1 +} + +Write-Host " VCPKG_ROOT: $env:VCPKG_ROOT" + +# Bootstrap vcpkg if needed +if (-not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) { + Write-Step "Bootstrapping vcpkg..." + Push-Location $env:VCPKG_ROOT + try { + & .\bootstrap-vcpkg.bat + if ($LASTEXITCODE -ne 0) { + Write-ErrorMessage "Failed to bootstrap vcpkg" + exit 1 + } + } + finally { + Pop-Location + } +} + +Write-Success "Prerequisites check passed" + +# Save VCPKG_ROOT before entering VS environment (VS may override it) +$savedVcpkgRoot = $env:VCPKG_ROOT + +# ============================================================================ +# Set up Visual Studio Developer Environment +# ============================================================================ + +Write-Step "Setting up Visual Studio Developer environment..." + +if (-not (Enter-VsDevEnvironment -Arch $Platform)) { + Write-ErrorMessage "Failed to set up Visual Studio environment" + exit 1 +} + +# Restore VCPKG_ROOT (VS environment may have changed it) +$env:VCPKG_ROOT = $savedVcpkgRoot +Write-Host " VCPKG_ROOT: $env:VCPKG_ROOT" + +Write-Success "VS Developer environment configured for $Platform" + +# ============================================================================ +# Clean (if requested) +# ============================================================================ + +if ($Clean) { + Write-Step "Cleaning build directory..." + $buildDir = Join-Path $PSScriptRoot "out" + if (Test-Path $buildDir) { + Remove-Item -Recurse -Force $buildDir + Write-Host " Removed: $buildDir" + } +} + +# ============================================================================ +# Configure +# ============================================================================ + +Write-Step "Configuring with CMake preset: $PresetName" + +Push-Location $PSScriptRoot +try { + & cmake --preset $PresetName + if ($LASTEXITCODE -ne 0) { + Write-ErrorMessage "CMake configuration failed" + exit 1 + } + Write-Success "Configuration complete" +} +finally { + Pop-Location +} + +# ============================================================================ +# Build +# ============================================================================ + +Write-Step "Building..." + +Push-Location $PSScriptRoot +try { + $buildArgs = @("out/build/$PresetName") + if ($Generator -eq 'VisualStudio') { + $buildArgs += @('--config', $Configuration) + } + + & cmake --build @buildArgs + if ($LASTEXITCODE -ne 0) { + Write-ErrorMessage "Build failed" + exit 1 + } + Write-Success "Build complete" +} +finally { + Pop-Location +} + +# ============================================================================ +# Output Information +# ============================================================================ + +Write-Header "Build Successful" + +$exePath = if ($Generator -eq 'VisualStudio') { + Join-Path $PSScriptRoot "out\build\$PresetName\$Configuration\WinMLEpCatalogSample.exe" +} else { + Join-Path $PSScriptRoot "out\build\$PresetName\WinMLEpCatalogSample.exe" +} +if (Test-Path $exePath) { + Write-Host "" + Write-Host "Output: $exePath" -ForegroundColor Green + Write-Host "" + Write-Host "To run the sample:" -ForegroundColor Cyan + Write-Host " $exePath" + Write-Host "" +} + +exit 0 diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/main.cpp b/Samples/WindowsML/cmake/WinMLEpCatalog/main.cpp new file mode 100644 index 000000000..e5108576e --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/main.cpp @@ -0,0 +1,139 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +// +// Windows ML Execution Provider Catalog Sample +// +// Demonstrates discovering certified ML execution providers, preparing them for use, +// and registering them with ONNX Runtime. This mirrors the behavior of the +// ExecutionProviderCatalog::RegisterCertifiedProviders WinRT API. +// + +#include +#include + +#include + +#include +#include +#include +#include +#include + +struct RegistrationContext +{ + Ort::Env* env; + std::vector registeredProviders; +}; + +static BOOL CALLBACK RegisterCertifiedProvider(WinMLEpHandle ep, const WinMLEpInfo* info, void* context) +{ + if (!info || !info->name) + { + return TRUE; + } + + auto* ctx = static_cast(context); + + std::cout << std::format("Provider: {}\n", info->name); + + if (info->certification != WinMLEpCertification_Certified) + { + std::cout << " Skipping (not certified)\n\n"; + return TRUE; + } + + HRESULT hr = WinMLEpEnsureReady(ep); + if (FAILED(hr)) + { + std::cout << std::format(" EnsureReady failed: 0x{:08X}\n\n", static_cast(hr)); + return TRUE; + } + + size_t pathSize = 0; + hr = WinMLEpGetLibraryPathSize(ep, &pathSize); + if (FAILED(hr) || pathSize == 0) + { + std::cout << " Failed to get library path\n\n"; + return TRUE; + } + + std::string libraryPathUtf8(pathSize, '\0'); + size_t used = 0; + hr = WinMLEpGetLibraryPath(ep, pathSize, libraryPathUtf8.data(), &used); + if (FAILED(hr)) + { + std::cout << " Failed to get library path\n\n"; + return TRUE; + } + libraryPathUtf8.resize(used > 0 ? used - 1 : 0); + + std::cout << std::format(" Library: {}\n", libraryPathUtf8); + + try + { + std::filesystem::path libraryPath(libraryPathUtf8); + ctx->env->RegisterExecutionProviderLibrary(info->name, libraryPath.wstring()); + ctx->registeredProviders.push_back(info->name); + std::cout << " Registered!\n\n"; + } + catch (const Ort::Exception& e) + { + std::cout << std::format(" Registration failed: {}\n\n", e.what()); + } + + return TRUE; +} + +int main() +{ + std::cout << "Windows ML Execution Provider Catalog Sample\n\n"; + + try + { + Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "WinMLEpCatalogSample"); + + WinMLEpCatalogHandle catalog = nullptr; + HRESULT hr = WinMLEpCatalogCreate(&catalog); + if (FAILED(hr)) + { + std::cerr << std::format("Failed to create catalog: 0x{:08X}\n", static_cast(hr)); + return 1; + } + + RegistrationContext ctx{&env, {}}; + hr = WinMLEpCatalogEnumProviders(catalog, RegisterCertifiedProvider, &ctx); + if (FAILED(hr)) + { + std::cerr << std::format("Enumeration failed: 0x{:08X}\n", static_cast(hr)); + } + + auto epDevices = env.GetEpDevices(); + std::cout << std::format("Available EP devices ({}):\n", epDevices.size()); + for (const auto& device : epDevices) + { + const char* epName = device.EpName(); + if (epName) + { + std::cout << std::format(" - {}\n", epName); + } + } + + WinMLEpCatalogRelease(catalog); + + std::cout << std::format("\nRegistered {} certified provider(s).\n", ctx.registeredProviders.size()); + + // Unregister providers before env goes out of scope + for (const auto& name : ctx.registeredProviders) + { + env.UnregisterExecutionProviderLibrary(name.c_str()); + } + } + catch (const Ort::Exception& e) + { + std::cerr << std::format("ORT error: {}\n", e.what()); + return 1; + } + + return 0; +} + diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json new file mode 100644 index 000000000..20ee12dfe --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json", + "default-registry": { + "kind": "git", + "baseline": "84bab45d415d22042bd0b9081aea57f362da3f35", + "repository": "https://github.com/microsoft/vcpkg" + }, + "overlay-ports": [ + "vcpkg_ports" + ] +} diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json new file mode 100644 index 000000000..9ecf53333 --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "name": "winml-ep-catalog-sample", + "version-string": "1.0.0", + "description": "Windows ML Execution Provider Catalog C API Sample", + "dependencies": [ + { + "name": "microsoft-windows-ai-machinelearning", + "features": ["experimental"] + } + ] +} diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake new file mode 100644 index 000000000..81f4bd9bb --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake @@ -0,0 +1,149 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. + +# Package name is the same for stable and experimental +# Experimental versions are prerelease versions (e.g., 2.0.169-experimental) +set(WINML_PACKAGE_NAME "Microsoft.WindowsAppSDK.ML") + +# +# VERSION CONFIGURATION +# ===================== +# Update this version when a new experimental build is available. +# This is the NuGet package version to download from nuget.org. +# +set(WINML_EXPERIMENTAL_VERSION "2.0.233-experimental-gfb98279532") + +# Stable version placeholder (not used when experimental feature is enabled) +set(WINML_STABLE_VERSION "2.0.0") + +# Select version based on feature +if("experimental" IN_LIST FEATURES) + set(WINML_SDK_VERSION "${WINML_EXPERIMENTAL_VERSION}") +else() + set(WINML_SDK_VERSION "${WINML_STABLE_VERSION}") +endif() + +# Support local package override for development +# Option 1: Set environment variable WINML_LOCAL_PACKAGE to the .nupkg path +# Option 2: Place the .nupkg file in the sample's local_packages/ directory +set(WINML_LOCAL_PACKAGE_PATH "$ENV{WINML_LOCAL_PACKAGE}") + +# Check for local packages directory relative to the overlay port +if(NOT WINML_LOCAL_PACKAGE_PATH OR NOT EXISTS "${WINML_LOCAL_PACKAGE_PATH}") + # Look in sample's local_packages folder (sibling to vcpkg_ports) + get_filename_component(SAMPLE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) + set(LOCAL_PKG_DIR "${SAMPLE_DIR}/local_packages") + set(LOCAL_PKG_FILE "${LOCAL_PKG_DIR}/${WINML_PACKAGE_NAME}.${WINML_SDK_VERSION}.nupkg") + if(EXISTS "${LOCAL_PKG_FILE}") + set(WINML_LOCAL_PACKAGE_PATH "${LOCAL_PKG_FILE}") + endif() +endif() + +if(WINML_LOCAL_PACKAGE_PATH AND EXISTS "${WINML_LOCAL_PACKAGE_PATH}") + file(TO_CMAKE_PATH "${WINML_LOCAL_PACKAGE_PATH}" WINML_LOCAL_PACKAGE_PATH) + set(WINML_SDK_NUGET_URL "file://${WINML_LOCAL_PACKAGE_PATH}") + message(STATUS "WINML: Using local package: ${WINML_LOCAL_PACKAGE_PATH}") + set(WINML_SKIP_HASH TRUE) +else() + set(WINML_SDK_NUGET_URL "https://www.nuget.org/api/v2/package/${WINML_PACKAGE_NAME}/${WINML_SDK_VERSION}") + # Skip hash for experimental versions (they change frequently during development) + if("experimental" IN_LIST FEATURES) + set(WINML_SKIP_HASH TRUE) + else() + set(WINML_SKIP_HASH FALSE) + endif() +endif() + +# Download the NuGet package +if(WINML_SKIP_HASH) + vcpkg_download_distfile( + WINML_ARCHIVE + URLS "${WINML_SDK_NUGET_URL}" + FILENAME "${WINML_PACKAGE_NAME}.${WINML_SDK_VERSION}.zip" + SKIP_SHA512 + ) +else() + # SHA512 hash for stable version (update when stable version changes) + set(WINML_SDK_SHA512 "0") + + vcpkg_download_distfile( + WINML_ARCHIVE + URLS "${WINML_SDK_NUGET_URL}" + FILENAME "${WINML_PACKAGE_NAME}.${WINML_SDK_VERSION}.zip" + SHA512 ${WINML_SDK_SHA512} + ) +endif() + +vcpkg_extract_source_archive( + WINML_EXTRACTED_FILES + ARCHIVE "${WINML_ARCHIVE}" + NO_REMOVE_ONE_LEVEL +) + +# Architecture mapping +if(VCPKG_TARGET_ARCHITECTURE STREQUAL "x64") + set(WINML_ARCH "x64") + set(WINML_NUGET_ARCH "win-x64") +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL "arm64") + set(WINML_ARCH "arm64") + set(WINML_NUGET_ARCH "win-arm64") +else() + message(FATAL_ERROR "Unsupported architecture: ${VCPKG_TARGET_ARCHITECTURE}") +endif() + +# Install headers +file(INSTALL "${WINML_EXTRACTED_FILES}/include/winml/" DESTINATION "${CURRENT_PACKAGES_DIR}/include/winml") +file(INSTALL "${WINML_EXTRACTED_FILES}/include/WinMLEpCatalog.h" DESTINATION "${CURRENT_PACKAGES_DIR}/include") + +# Install import libraries +file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/onnxruntime.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/lib") +if(EXISTS "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib") + file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/lib") +endif() + +# Install runtime DLLs +file(INSTALL + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime.dll" + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime_providers_shared.dll" + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/Microsoft.Windows.AI.MachineLearning.dll" + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/DirectML.dll" + DESTINATION "${CURRENT_PACKAGES_DIR}/bin" +) + +# Debug configuration +if(NOT VCPKG_BUILD_TYPE) + file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/onnxruntime.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") + if(EXISTS "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib") + file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") + endif() + file(INSTALL + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime.dll" + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime_providers_shared.dll" + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/Microsoft.Windows.AI.MachineLearning.dll" + "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/DirectML.dll" + DESTINATION "${CURRENT_PACKAGES_DIR}/debug/bin" + ) +endif() + +# Install CMake config files +file(INSTALL + "${WINML_EXTRACTED_FILES}/cmake/microsoft-windows-ai-machinelearning-config.cmake" + "${WINML_EXTRACTED_FILES}/cmake/microsoft-windows-ai-machinelearning-targets.cmake" + DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" +) + +file(READ "${CURRENT_PACKAGES_DIR}/share/${PORT}/microsoft-windows-ai-machinelearning-config.cmake" CONFIG_CONTENT) +string(REPLACE "@WINML_VERSION@" "${WINML_SDK_VERSION}" CONFIG_CONTENT "${CONFIG_CONTENT}") +file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/microsoft-windows-ai-machinelearning-config.cmake" "${CONFIG_CONTENT}") + +file(RENAME + "${CURRENT_PACKAGES_DIR}/share/${PORT}/microsoft-windows-ai-machinelearning-config.cmake" + "${CURRENT_PACKAGES_DIR}/share/${PORT}/${PORT}-config.cmake" +) + +# Install documentation and license +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +file(INSTALL "${WINML_EXTRACTED_FILES}/license.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) + +if(EXISTS "${WINML_EXTRACTED_FILES}/ThirdPartyNotices.txt") + file(INSTALL "${WINML_EXTRACTED_FILES}/ThirdPartyNotices.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +endif() diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage new file mode 100644 index 000000000..e1d4c98fa --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage @@ -0,0 +1,24 @@ +microsoft-windows-ai-machinelearning provides CMake integration: + + find_package(microsoft-windows-ai-machinelearning CONFIG REQUIRED) + + # For Windows ML API (requires both DLLs at runtime): + target_link_libraries(main PRIVATE WindowsML::Api) + + # For direct OnnxRuntime C API access: + target_link_libraries(main PRIVATE WindowsML::OnnxRuntime) + + # For both (if using both APIs): + target_link_libraries(main PRIVATE WindowsML::Api WindowsML::OnnxRuntime) + +Available CMake targets: + WindowsML::Api - Windows ML API (Microsoft.Windows.AI.MachineLearning.lib) + WindowsML::OnnxRuntime - OnnxRuntime C API (onnxruntime.lib) + +Helper function to copy runtime DLLs to build output: + + winml_copy_runtime_dlls(MyApp) + +Package variants: + Stable: vcpkg install microsoft-windows-ai-machinelearning + Experimental: vcpkg install microsoft-windows-ai-machinelearning[experimental] diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json new file mode 100644 index 000000000..aa47c317c --- /dev/null +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json @@ -0,0 +1,20 @@ +{ + "name": "microsoft-windows-ai-machinelearning", + "version": "2.0.233-experimental-gfb98279532", + "maintainers": "Microsoft Corporation", + "description": "Windows ML inference SDK with OnnxRuntime and DirectML.", + "homepage": "https://github.com/microsoft/windowsappsdk", + "license": "MIT", + "supports": "windows & (x64 | arm64)", + "dependencies": [ + { + "name": "vcpkg-cmake-config", + "host": true + } + ], + "features": { + "experimental": { + "description": "Use experimental (preview) builds instead of stable releases." + } + } +} From ab023f52ff341dad6ac0e1a754273c891d0fec0d Mon Sep 17 00:00:00 2001 From: Nick Eubanks Date: Wed, 18 Feb 2026 09:48:31 -0500 Subject: [PATCH 2/2] Add WinML EP Catalog CMake sample with NuGet package integration Adds a CMake-based C++ sample demonstrating the WinML Execution Provider Catalog C API (WinMLEpCatalog*) for discovering and registering hardware-accelerated ML execution providers with ONNX Runtime. What the sample shows: - Creating an EP catalog and enumerating registered execution providers - Inspecting provider metadata (name, version, certification status) - Preparing certified providers with WinMLEpEnsureReady and registering them with Ort::Env - Consuming the Microsoft.WindowsAppSDK.ML NuGet package from CMake with automatic .nupkg extraction at configure time - Deploying runtime DLLs via TARGET_RUNTIME_DLLS and an explicit WINML_DIRECTML_DLL copy for DirectML (which has no import library) Build setup: - CMake 3.21+ with a single nuget preset; supports both Ninja and Visual Studio generators - build.ps1 helper script handles VS developer environment setup, prerequisite checks, and NuGet package resolution - No vcpkg dependency -- the NuGet package is extracted directly by CMake's file(ARCHIVE_EXTRACT) --- .../WindowsML/cmake/WinMLEpCatalog/.gitignore | 3 - .../cmake/WinMLEpCatalog/CMakeLists.txt | 59 +++- .../cmake/WinMLEpCatalog/CMakePresets.json | 169 +-------- .../WindowsML/cmake/WinMLEpCatalog/README.md | 323 +++--------------- .../WindowsML/cmake/WinMLEpCatalog/build.cmd | 2 +- .../WindowsML/cmake/WinMLEpCatalog/build.ps1 | 192 ++++------- .../WinMLEpCatalog/vcpkg-configuration.json | 11 - .../WindowsML/cmake/WinMLEpCatalog/vcpkg.json | 12 - .../portfile.cmake | 149 -------- .../usage | 24 -- .../vcpkg.json | 20 -- 11 files changed, 169 insertions(+), 795 deletions(-) delete mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json delete mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json delete mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake delete mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage delete mode 100644 Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore b/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore index c995aeff7..a6544aed7 100644 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/.gitignore @@ -6,9 +6,6 @@ build/ CMakeCache.txt CMakeFiles/ -# vcpkg downloads -vcpkg_installed/ - # Local package overrides (for development/testing) local_packages/ diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt index 1c7f5dbde..3de80e79e 100644 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakeLists.txt @@ -7,8 +7,40 @@ project(WinMLEpCatalogSample LANGUAGES CXX ) -# Find the Windows ML package installed via vcpkg -find_package(microsoft-windows-ai-machinelearning CONFIG REQUIRED) +# Local NuGet package configuration +set(WINML_NUGET_PACKAGE "${CMAKE_CURRENT_SOURCE_DIR}/Microsoft.WindowsAppSDK.ML.2.0.246-experimental.nupkg" + CACHE FILEPATH "Path to Microsoft.WindowsAppSDK.ML nupkg") +set(WINML_LOCAL_PACKAGES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/local_packages" + CACHE PATH "Directory where the nupkg is extracted") + +# Auto-extract the local nupkg (if needed) and wire CMake package discovery. +# Users can still override microsoft.windows.ai.machinelearning_DIR directly. +if(NOT DEFINED microsoft.windows.ai.machinelearning_DIR) + if(EXISTS "${WINML_NUGET_PACKAGE}") + get_filename_component(_winml_nupkg_filename "${WINML_NUGET_PACKAGE}" NAME) + string(REGEX REPLACE "\\.nupkg$" "" _winml_nupkg_name "${_winml_nupkg_filename}") + set(_winml_extract_dir "${WINML_LOCAL_PACKAGES_DIR}/${_winml_nupkg_name}") + set(_winml_config_file "${_winml_extract_dir}/build/cmake/microsoft.windows.ai.machinelearning-config.cmake") + + if(NOT EXISTS "${_winml_config_file}") + file(MAKE_DIRECTORY "${WINML_LOCAL_PACKAGES_DIR}") + message(STATUS "Extracting ${WINML_NUGET_PACKAGE} -> ${_winml_extract_dir}") + file(ARCHIVE_EXTRACT + INPUT "${WINML_NUGET_PACKAGE}" + DESTINATION "${_winml_extract_dir}") + endif() + + set(microsoft.windows.ai.machinelearning_DIR "${_winml_extract_dir}/build/cmake" + CACHE PATH "Path to microsoft.windows.ai.machinelearning CMake config" FORCE) + else() + message(FATAL_ERROR + "Windows ML NuGet package not found: ${WINML_NUGET_PACKAGE}. " + "Place the nupkg at that location or set microsoft.windows.ai.machinelearning_DIR.") + endif() +endif() + +# Find the Windows ML package from the extracted NuGet package CMake config. +find_package(microsoft.windows.ai.machinelearning CONFIG REQUIRED) # C++20 standard for modern features (std::format, etc.) set(CMAKE_CXX_STANDARD 20) @@ -19,18 +51,29 @@ add_executable(WinMLEpCatalogSample main.cpp ) -# Link against the Windows ML API and ONNX Runtime -# WindowsML::Api provides the WinMLEpCatalog* functions -# WindowsML::OnnxRuntime provides access to the ONNX Runtime C/C++ API for creating OrtEnv and registering providers +# WindowsML::Api - WinMLEpCatalog* C API for discovering execution providers +# WindowsML::OnnxRuntime - ONNX Runtime C/C++ API (OrtEnv, session creation, etc.) target_link_libraries(WinMLEpCatalogSample PRIVATE WindowsML::Api WindowsML::OnnxRuntime ) -# Copy runtime DLLs to the build output directory -# This is required because the Windows ML DLLs must be present alongside the executable -winml_copy_runtime_dlls(WinMLEpCatalogSample) +# Copy runtime DLLs (onnxruntime.dll, Microsoft.Windows.AI.MachineLearning.dll) +# to the executable output directory so the sample can run in-place. +add_custom_command(TARGET WinMLEpCatalogSample POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ $ + COMMAND_EXPAND_LISTS + VERBATIM +) + +# DirectML.dll has no import library, so it is not included in TARGET_RUNTIME_DLLS. +# Copy it explicitly if your application uses the DirectML execution provider. +add_custom_command(TARGET WinMLEpCatalogSample POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${WINML_DIRECTML_DLL}" $ +) # Set Windows-specific compiler options if(MSVC) diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json index bfcb29cf7..e682b9764 100644 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/CMakePresets.json @@ -1,167 +1,28 @@ { - "version": 3, + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, "configurePresets": [ { - "name": "base", - "hidden": true, + "name": "nuget", + "displayName": "NuGet (Direct)", + "description": "Configure using local .nupkg extraction and direct CMake package files", "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", - "installDir": "${sourceDir}/out/install/${presetName}", - "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - }, - { - "name": "base-vs", - "hidden": true, - "generator": "Visual Studio 17 2022", - "binaryDir": "${sourceDir}/out/build/${presetName}", - "installDir": "${sourceDir}/out/install/${presetName}", - "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - }, - { - "name": "x64-debug", - "displayName": "x64 Debug", - "description": "Build for x64 architecture in Debug mode", - "inherits": "base", - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "VCPKG_TARGET_TRIPLET": "x64-windows" - } - }, - { - "name": "x64-release", - "displayName": "x64 Release", - "description": "Build for x64 architecture in Release mode", - "inherits": "base", - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "VCPKG_TARGET_TRIPLET": "x64-windows" - } - }, - { - "name": "arm64-debug", - "displayName": "ARM64 Debug", - "description": "Build for ARM64 architecture in Debug mode", - "inherits": "base", - "architecture": { - "value": "arm64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "VCPKG_TARGET_TRIPLET": "arm64-windows" - } - }, - { - "name": "arm64-release", - "displayName": "ARM64 Release", - "description": "Build for ARM64 architecture in Release mode", - "inherits": "base", - "architecture": { - "value": "arm64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "VCPKG_TARGET_TRIPLET": "arm64-windows" - } - }, - { - "name": "x64-debug-vs", - "displayName": "x64 Debug (VS)", - "description": "Build for x64 architecture in Debug mode (Visual Studio generator)", - "inherits": "base-vs", - "architecture": { - "value": "x64", - "strategy": "set" - }, - "cacheVariables": { - "VCPKG_TARGET_TRIPLET": "x64-windows" - } - }, - { - "name": "x64-release-vs", - "displayName": "x64 Release (VS)", - "description": "Build for x64 architecture in Release mode (Visual Studio generator)", - "inherits": "base-vs", - "architecture": { - "value": "x64", - "strategy": "set" - }, - "cacheVariables": { - "VCPKG_TARGET_TRIPLET": "x64-windows" - } - }, - { - "name": "arm64-debug-vs", - "displayName": "ARM64 Debug (VS)", - "description": "Build for ARM64 architecture in Debug mode (Visual Studio generator)", - "inherits": "base-vs", - "architecture": { - "value": "ARM64", - "strategy": "set" - }, - "cacheVariables": { - "VCPKG_TARGET_TRIPLET": "arm64-windows" - } - }, - { - "name": "arm64-release-vs", - "displayName": "ARM64 Release (VS)", - "description": "Build for ARM64 architecture in Release mode (Visual Studio generator)", - "inherits": "base-vs", - "architecture": { - "value": "ARM64", - "strategy": "set" - }, - "cacheVariables": { - "VCPKG_TARGET_TRIPLET": "arm64-windows" + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } } ], "buildPresets": [ { - "name": "x64-debug", - "configurePreset": "x64-debug" - }, - { - "name": "x64-release", - "configurePreset": "x64-release" - }, - { - "name": "arm64-debug", - "configurePreset": "arm64-debug" - }, - { - "name": "arm64-release", - "configurePreset": "arm64-release" - }, - { - "name": "x64-debug-vs", - "configurePreset": "x64-debug-vs", - "configuration": "Debug" - }, - { - "name": "x64-release-vs", - "configurePreset": "x64-release-vs", - "configuration": "Release" - }, - { - "name": "arm64-debug-vs", - "configurePreset": "arm64-debug-vs", - "configuration": "Debug" - }, - { - "name": "arm64-release-vs", - "configurePreset": "arm64-release-vs", - "configuration": "Release" + "name": "nuget", + "configurePreset": "nuget" } ] } diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/README.md b/Samples/WindowsML/cmake/WinMLEpCatalog/README.md index fdc36aecb..5814cdcc2 100644 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/README.md +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/README.md @@ -1,328 +1,91 @@ -# Windows ML EP Catalog Sample (CMake/Native C API) +# Windows ML EP Catalog Sample (CMake/WinML C API) -This sample demonstrates the **WinMLEpCatalog Native C API** for discovering and managing hardware-accelerated execution providers (EPs) for machine learning inference on Windows. The sample uses CMake and vcpkg for cross-platform-style builds without Visual Studio project files. +This sample demonstrates the **WinMLEpCatalog WinML C API** for discovering and managing hardware-accelerated execution providers (EPs) for machine learning inference on Windows. -## Overview - -The WinMLEpCatalog API is a native C API that provides low-level access to Windows ML's execution provider infrastructure. Unlike the WinRT/COM interfaces, this API: +The CMake project is configured to use the Windows ML NuGet package directly and auto-extract it during configure. -- **Has no WinRT dependencies** — pure C function calls with handle-based resource management -- **Is easy to integrate** — single header file (`WinMLEpCatalog.h`) with simple function signatures -- **Supports async operations** — progress callbacks and cancellation for long-running operations -- **Works with any build system** — CMake, Makefiles, or direct compiler invocation +## Overview This sample showcases: -- Creating an ONNX Runtime environment (OrtEnv) +- Creating an ONNX Runtime environment (`Ort::Env`) - Creating and releasing a catalog handle -- Enumerating all registered execution providers +- Enumerating registered execution providers - Inspecting provider metadata (name, version, state, certification) -- Preparing providers with `EnsureReady` (sync) +- Preparing providers with `EnsureReady` - Registering prepared providers with ONNX Runtime -- Verifying registered EP devices - -## Key Features - -### ONNX Runtime Integration - -This sample demonstrates the complete workflow for registering certified execution providers with ONNX Runtime, matching the behavior of the `ExecutionProviderCatalog::RegisterCertifiedProviders` WinRT API: - -```cpp -// Initialize ORT API -const OrtApiBase* ortApiBase = OrtGetApiBase(); -const OrtApi* ortApi = ortApiBase->GetApi(ORT_API_VERSION); -Ort::InitApi(ortApi); - -// Create ORT environment -Ort::Env ortEnv(ORT_LOGGING_LEVEL_WARNING, "MyApp"); - -// Register provider library after EnsureReady -std::wstring libraryPath = Utf8ToWide(provider.libraryPath); -ortEnv.RegisterExecutionProviderLibrary(provider.name.c_str(), libraryPath); - -// Verify registered providers -auto epDevices = ortEnv.GetEpDevices(); -``` - -### Execution Provider Discovery - -Enumerate all available execution providers registered on the system: - -```cpp -WinMLEpCatalogEnumProviders(catalog, callback, context); -``` - -The callback receives information about each provider including: -- Provider name (e.g., `ContosoExecutionProvider`, `DmlExecutionProvider`) -- Version string -- Package family name -- Ready state (`Ready`, `NotReady`, `NotPresent`) -- Certification status - -### Provider Preparation - -Before using an execution provider, it must be prepared. This may involve downloading and installing the provider package: - -```cpp -// Synchronous (blocking) -WinMLEpEnsureReady(epHandle, &result); - -// Asynchronous (with progress) -WinMLEpEnsureReadyAsync(epHandle, &asyncBlock); -``` - -### Path Retrieval - -After preparation, retrieve the paths needed to load the provider: - -```cpp -WinMLEpGetLibraryPath(epHandle, bufferSize, buffer, &used); -WinMLEpGetPackageRootPath(epHandle, bufferSize, buffer, &used); -``` - -## When to Use This Approach - -**Choose the Native C API when:** - -- Integrating with C codebases or C-compatible FFI boundaries -- Building cross-platform applications that target Windows -- Requiring minimal dependencies (no WinRT/COM overhead) -- Working with build systems that don't easily support WinRT -- Need precise control over async operation lifetime and cancellation - -## Project Structure - -``` -WinMLEpCatalog/ -├── main.cpp # Sample implementation (all code in one file) -├── CMakeLists.txt # CMake build configuration -├── CMakePresets.json # Build presets (x64/arm64, Debug/Release) -├── vcpkg.json # Package manifest -├── vcpkg-configuration.json # vcpkg registry configuration -├── vcpkg_ports/ # Local vcpkg port overlay -│ └── microsoft-windows-ai-machinelearning/ -│ ├── portfile.cmake # Package download and install script -│ ├── vcpkg.json # Port metadata -│ └── usage # CMake integration instructions -├── build.ps1 # Build helper script -├── build.cmd # Batch wrapper for build.ps1 -└── README.md # This file -``` ## Prerequisites -- **Visual Studio 2022** with C++ development workload +- **Visual Studio 2022** with C++ workload - **CMake** 3.21 or later -- **vcpkg** (will be configured automatically if `VCPKG_ROOT` is set) -- **Ninja** (optional; required only when using the Ninja generator) +- **Ninja** (optional; only needed when using Ninja generator) +- `Microsoft.WindowsAppSDK.ML.2.0.246-experimental.nupkg` in this folder -### Installing Prerequisites +Example install commands: ```powershell -# Install CMake -winget install Kitware.CMake - -# Install Ninja (optional) -winget install Ninja-build.Ninja - -# Clone and bootstrap vcpkg -git clone https://github.com/microsoft/vcpkg.git C:\vcpkg -C:\vcpkg\bootstrap-vcpkg.bat -$env:VCPKG_ROOT = "C:\vcpkg" +winget install --exact --id Kitware.CMake +winget install --exact --id Ninja-build.Ninja ``` -## Building - -### Using the Build Script (Recommended) +## Build (Recommended) -The included PowerShell script handles all build steps: +Use the helper script: ```powershell -# Build Debug for current platform (auto-detected) +# RelWithDebInfo for host architecture .\build.ps1 -# Build with the Visual Studio generator (no Ninja required) -.\build.ps1 -Generator VisualStudio +# Debug with Visual Studio generator +.\build.ps1 -Generator VisualStudio -Configuration Debug -# Require Ninja (fails if Ninja is not installed) -.\build.ps1 -Generator Ninja - -# Build Release for x64 -.\build.ps1 -Configuration Release -Platform x64 - -# Build Debug for ARM64 -.\build.ps1 -Configuration Debug -Platform arm64 +# Release for ARM64 +.\build.ps1 -Configuration Release -Platform arm64 # Clean and rebuild .\build.ps1 -Clean ``` -### Manual Build Steps - -If you prefer manual control: - -```powershell -# 1. Set vcpkg root (if not already in environment) -$env:VCPKG_ROOT = "C:\path\to\vcpkg" - -# 2. Configure with CMake preset -cmake --preset x64-debug - -# Or configure with Visual Studio generator preset -cmake --preset x64-debug-vs - -# 3. Build -cmake --build out/build/x64-debug - -# Or for Visual Studio generator: -cmake --build out/build/x64-debug-vs --config Debug - -# 4. Run -.\out\build\x64-debug\WinMLEpCatalogSample.exe -``` - -### Visual Studio +During configure, CMake automatically: -You can also open this folder directly in Visual Studio 2022: +1. Finds the local `.nupkg` +2. Extracts it to `local_packages//` (if not already extracted) +3. Sets `microsoft.windows.ai.machinelearning_DIR` to the extracted `build/cmake` folder -1. Open Visual Studio 2022 -2. Select **File > Open > Folder** -3. Navigate to the `WinMLEpCatalog` directory -4. Visual Studio will detect `CMakePresets.json` and configure automatically -5. Select the desired preset from the configuration dropdown -6. Build with **Build > Build All** (Ctrl+Shift+B) +## Manual Build -## Running the Sample +```powershell +# Configure (auto-extracts nupkg if needed) +cmake --preset nuget -After building, run the executable: +# Build +cmake --build out/build/nuget --config RelWithDebInfo -``` -.\out\build\x64-debug\WinMLEpCatalogSample.exe +# Run +.\out\build\nuget\WinMLEpCatalogSample.exe ``` -### Interactive Shell Commands +## Package Version Override -The sample provides an interactive shell for exploring the API: +To use a different package file: -| Command | Description | -|---------|-------------| -| `help` | Show available commands | -| `list` | List all registered execution providers | -| `select <#>` | Select a provider by index number | -| `info` | Show detailed info for selected provider | -| `ensure` | Prepare selected provider (async with progress) | -| `ensure-sync` | Prepare selected provider (synchronous) | -| `path` | Show library and package paths | -| `exit` | Exit the program | - -### Example Session - -``` -========================================== - Windows ML Execution Provider Catalog - Flat-C API Sample -========================================== -Catalog created successfully. - -======================================== - WinML EP Catalog - Interactive Shell -======================================== -Type 'help' for available commands. - - # Name State Version ------------------------------------------------------------- - 0 ContosoExecutionProvider NotReady 1.0.0 - -Total: 1 provider(s) - -winml> select 0 -Selected: ContosoExecutionProvider - -winml [ContosoExecutionProvider]> info - -Execution Provider Info: - Name: ContosoExecutionProvider - Version: 1.0.0 - Package Family Name: Microsoft.AI.MachineLearning.Contoso_8wekyb3d8bbwe - Ready State: NotReady - Certification: Certified - -winml [ContosoExecutionProvider]> ensure -Ensuring 'ContosoExecutionProvider' is ready (asynchronous)... - (Press ESC to cancel) - [==============================] 100% -Result: - Status: S_OK - Library Path: C:\Program Files\WindowsApps\...\onnxruntime_contoso.dll - Package Root Path: C:\Program Files\WindowsApps\... - -winml [ContosoExecutionProvider]> exit -Goodbye. +```powershell +cmake --preset nuget -DWINML_NUGET_PACKAGE=.\Microsoft.WindowsAppSDK.ML..nupkg ``` -## API Reference - -### Catalog Management - -| Function | Description | -|----------|-------------| -| `WinMLEpCatalogCreate()` | Create a catalog instance | -| `WinMLEpCatalogRelease()` | Release catalog resources | -| `WinMLEpCatalogEnumProviders()` | Enumerate all providers via callback | -| `WinMLEpCatalogFindProvider()` | Find a specific provider by name | - -### Provider Operations - -| Function | Description | -|----------|-------------| -| `WinMLEpEnsureReady()` | Synchronously prepare a provider | -| `WinMLEpEnsureReadyAsync()` | Start async preparation | -| `WinMLEpEnsureReadyResult()` | Get async operation result | -| `WinMLEpGetLibraryPath()` | Get provider DLL path | -| `WinMLEpGetPackageRootPath()` | Get package root directory | - -### Async Operations - -| Function | Description | -|----------|-------------| -| `WinMLAsyncGetStatus()` | Poll async operation status | -| `WinMLAsyncCancel()` | Request cancellation | -| `WinMLAsyncClose()` | Release async operation resources | - -## Updating the Package Version - -The Windows ML package version is defined in the vcpkg overlay port. To update: - -1. Open `vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake` -2. Find the `WINML_EXPERIMENTAL_VERSION` variable near the top -3. Update to the new version: - ```cmake - set(WINML_EXPERIMENTAL_VERSION "2.0.228-experimental") - ``` -4. Delete the `out/` directory and rebuild +For a full refresh, delete `local_packages/` and `out/` and configure again. ## Troubleshooting -### "Failed to create EP catalog" - -This typically means: -- Windows ML runtime DLLs are not in the application directory -- Windows version is not supported (requires Windows 11 24H2+) -- The `winml_copy_runtime_dlls()` CMake function did not run +### "Windows ML NuGet package not found" -**Solution:** Ensure the build completed successfully and DLLs were copied to the output directory. +Ensure the package exists in this directory, or pass `-DWINML_NUGET_PACKAGE=`. -### "vcpkg not found" +### "Failed to create EP catalog" -**Solution:** Set the `VCPKG_ROOT` environment variable: -```powershell -$env:VCPKG_ROOT = "C:\path\to\vcpkg" -``` +Check that runtime DLLs were copied to the executable output directory and the target OS is supported. -### Build fails with "package not found" +## License -The overlay port may not be found. Ensure you're building from the sample directory: -```powershell -cd samples\WindowsAppSDK-Samples\Samples\WindowsML\cmake\WinMLEpCatalog -.\build.ps1 -``` +Copyright (C) Microsoft Corporation. All rights reserved. diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd b/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd index 109bb6c7a..e2e2a4a12 100644 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/build.cmd @@ -2,7 +2,7 @@ REM Copyright (C) Microsoft Corporation. All rights reserved. REM REM Simple batch wrapper for build.ps1 -REM Usage: build.cmd [Debug|Release] [x64|arm64] [Ninja|VisualStudio] +REM Usage: build.cmd [Debug|Release|RelWithDebInfo|MinSizeRel] [x64|arm64] [Ninja|VisualStudio] REM setlocal diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 b/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 index c6bdc95ad..cdfda3c07 100644 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 +++ b/Samples/WindowsML/cmake/WinMLEpCatalog/build.ps1 @@ -1,41 +1,39 @@ # Copyright (C) Microsoft Corporation. All rights reserved. <# .SYNOPSIS - Builds the WinML EP Catalog Sample using CMake and vcpkg. + Builds the WinML EP Catalog Sample using CMake and a local NuGet package. .DESCRIPTION This script automates the build process for the WinMLEpCatalog sample. It handles: - - Checking prerequisites (CMake, vcpkg, Visual Studio) - - Setting up VCPKG_ROOT if not already configured - - Configuring and building the project using CMake presets + - Checking prerequisites (CMake, Visual Studio) + - Setting up Visual Studio developer environment + - Configuring and building the project using the NuGet CMake preset .PARAMETER Configuration - Build configuration: Debug or Release. Default: Debug - -.PARAMETER Platform - Target platform: x64 or arm64. Default: Auto-detect from host + Build configuration: Debug, Release, RelWithDebInfo, MinSizeRel. Default: RelWithDebInfo .PARAMETER Generator - Build generator: Auto, Ninja, or VisualStudio. Default: Auto (uses Ninja if installed) + Build generator: Ninja or VisualStudio. Default: Ninja -.PARAMETER VcpkgRoot - Path to vcpkg installation. Default: Uses VCPKG_ROOT environment variable +.PARAMETER NuGetPackage + Path to Microsoft.WindowsAppSDK.ML nupkg. + Default: .\Microsoft.WindowsAppSDK.ML.2.0.246-experimental.nupkg .PARAMETER Clean - If specified, removes the build directory before building. + If specified, reconfigures with `cmake --fresh` before building. .EXAMPLE .\build.ps1 - # Builds Debug configuration for the current platform + # Builds RelWithDebInfo for the current platform .EXAMPLE .\build.ps1 -Configuration Release -Platform arm64 - # Builds Release configuration for ARM64 + # Builds Release for ARM64 .EXAMPLE - .\build.ps1 -Generator VisualStudio - # Builds using the Visual Studio generator (no Ninja required) + .\build.ps1 -Generator VisualStudio -Configuration Debug + # Builds Debug using the Visual Studio generator .EXAMPLE .\build.ps1 -Clean -Configuration Debug @@ -44,16 +42,16 @@ [CmdletBinding()] param( - [ValidateSet('Debug', 'Release')] - [string]$Configuration = 'Debug', + [ValidateSet('Debug', 'Release', 'RelWithDebInfo', 'MinSizeRel')] + [string]$Configuration = 'RelWithDebInfo', [ValidateSet('x64', 'arm64')] [string]$Platform, - [ValidateSet('Auto', 'Ninja', 'VisualStudio')] - [string]$Generator = 'Auto', - - [string]$VcpkgRoot, + [ValidateSet('Ninja', 'VisualStudio')] + [string]$Generator = 'Ninja', + + [string]$NuGetPackage = 'Microsoft.WindowsAppSDK.ML.2.0.246-experimental.nupkg', [switch]$Clean ) @@ -150,19 +148,8 @@ if (-not $Platform) { Write-Host "Auto-detected platform: $Platform" } -# Select generator -if ($Generator -eq 'Auto') { - if (Test-CommandExists 'ninja') { - $Generator = 'Ninja' - } - else { - $Generator = 'VisualStudio' - } -} - # Determine preset name -$presetSuffix = if ($Generator -eq 'VisualStudio') { '-vs' } else { '' } -$PresetName = "$Platform-$($Configuration.ToLower())$presetSuffix" +$PresetName = "nuget" Write-Host "Build preset: $PresetName" Write-Host "Generator: $Generator" @@ -182,7 +169,7 @@ if (-not (Test-CommandExists 'cmake')) { $cmakeVersion = (cmake --version | Select-Object -First 1) Write-Host " CMake: $cmakeVersion" -# Check Ninja +# Check Ninja (only required for Ninja generator) if ($Generator -eq 'Ninja') { if (Test-CommandExists 'ninja') { $ninjaVersion = (ninja --version) @@ -193,77 +180,23 @@ if ($Generator -eq 'Ninja') { exit 1 } } -else { - if (Test-CommandExists 'ninja') { - $ninjaVersion = (ninja --version) - Write-Host " Ninja: $ninjaVersion (not required for Visual Studio generator)" - } - else { - Write-Host " Ninja: Not required (using Visual Studio generator)" -ForegroundColor Yellow - } -} -# Check vcpkg -if ($VcpkgRoot) { - $env:VCPKG_ROOT = $VcpkgRoot +# Check NuGet package +$resolvedNuGetPackage = Resolve-Path (Join-Path $PSScriptRoot $NuGetPackage) -ErrorAction SilentlyContinue +if (-not $resolvedNuGetPackage) { + $resolvedNuGetPackage = Resolve-Path $NuGetPackage -ErrorAction SilentlyContinue } -# Always try to find the windows-ml submodule vcpkg first (preferred) -$windowsMlVcpkg = Resolve-Path "$PSScriptRoot\..\..\..\..\..\..\external\vcpkg" -ErrorAction SilentlyContinue -if ($windowsMlVcpkg -and (Test-Path "$windowsMlVcpkg\vcpkg.exe")) { - $env:VCPKG_ROOT = $windowsMlVcpkg.Path - Write-Host " Using windows-ml vcpkg: $env:VCPKG_ROOT" -} -elseif (-not $env:VCPKG_ROOT -or -not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) { - # Try to find vcpkg in common locations - $possiblePaths = @( - "$env:USERPROFILE\vcpkg", - "C:\vcpkg", - "C:\src\vcpkg" - ) - - foreach ($path in $possiblePaths) { - $resolvedPath = Resolve-Path $path -ErrorAction SilentlyContinue - if ($resolvedPath -and (Test-Path "$resolvedPath\vcpkg.exe")) { - $env:VCPKG_ROOT = $resolvedPath.Path - Write-Host " Found vcpkg at: $env:VCPKG_ROOT" - break - } - } -} - -if (-not $env:VCPKG_ROOT -or -not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) { - Write-ErrorMessage "vcpkg not found. Please set VCPKG_ROOT or use -VcpkgRoot parameter." - Write-Host " To install vcpkg:" -ForegroundColor Gray - Write-Host " git clone https://github.com/microsoft/vcpkg.git" -ForegroundColor Gray - Write-Host " .\vcpkg\bootstrap-vcpkg.bat" -ForegroundColor Gray - Write-Host " set VCPKG_ROOT=" -ForegroundColor Gray +if (-not $resolvedNuGetPackage) { + Write-ErrorMessage "NuGet package not found: $NuGetPackage" + Write-Host " Place Microsoft.WindowsAppSDK.ML.2.0.246-experimental.nupkg in this folder or pass -NuGetPackage." -ForegroundColor Gray exit 1 } -Write-Host " VCPKG_ROOT: $env:VCPKG_ROOT" - -# Bootstrap vcpkg if needed -if (-not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) { - Write-Step "Bootstrapping vcpkg..." - Push-Location $env:VCPKG_ROOT - try { - & .\bootstrap-vcpkg.bat - if ($LASTEXITCODE -ne 0) { - Write-ErrorMessage "Failed to bootstrap vcpkg" - exit 1 - } - } - finally { - Pop-Location - } -} +Write-Host " NuGet package: $resolvedNuGetPackage" Write-Success "Prerequisites check passed" -# Save VCPKG_ROOT before entering VS environment (VS may override it) -$savedVcpkgRoot = $env:VCPKG_ROOT - # ============================================================================ # Set up Visual Studio Developer Environment # ============================================================================ @@ -275,10 +208,6 @@ if (-not (Enter-VsDevEnvironment -Arch $Platform)) { exit 1 } -# Restore VCPKG_ROOT (VS environment may have changed it) -$env:VCPKG_ROOT = $savedVcpkgRoot -Write-Host " VCPKG_ROOT: $env:VCPKG_ROOT" - Write-Success "VS Developer environment configured for $Platform" # ============================================================================ @@ -286,12 +215,7 @@ Write-Success "VS Developer environment configured for $Platform" # ============================================================================ if ($Clean) { - Write-Step "Cleaning build directory..." - $buildDir = Join-Path $PSScriptRoot "out" - if (Test-Path $buildDir) { - Remove-Item -Recurse -Force $buildDir - Write-Host " Removed: $buildDir" - } + Write-Step "Clean requested: configure will run with --fresh" } # ============================================================================ @@ -300,18 +224,31 @@ if ($Clean) { Write-Step "Configuring with CMake preset: $PresetName" -Push-Location $PSScriptRoot -try { - & cmake --preset $PresetName - if ($LASTEXITCODE -ne 0) { - Write-ErrorMessage "CMake configuration failed" - exit 1 - } - Write-Success "Configuration complete" +$buildDir = Join-Path $PSScriptRoot "out/build/$PresetName" +$configureArgs = @( + '--preset', $PresetName, + '-S', $PSScriptRoot, + '-B', $buildDir, + "-DWINML_NUGET_PACKAGE=$($resolvedNuGetPackage.Path)" +) + +if ($Clean) { + $configureArgs += '--fresh' +} + +if ($Generator -eq 'VisualStudio') { + $configureArgs += @('-G', 'Visual Studio 17 2022', '-A', $Platform) +} +else { + $configureArgs += @('-G', 'Ninja', "-DCMAKE_BUILD_TYPE=$Configuration") } -finally { - Pop-Location + +& cmake @configureArgs +if ($LASTEXITCODE -ne 0) { + Write-ErrorMessage "CMake configuration failed" + exit 1 } +Write-Success "Configuration complete" # ============================================================================ # Build @@ -319,23 +256,12 @@ finally { Write-Step "Building..." -Push-Location $PSScriptRoot -try { - $buildArgs = @("out/build/$PresetName") - if ($Generator -eq 'VisualStudio') { - $buildArgs += @('--config', $Configuration) - } - - & cmake --build @buildArgs - if ($LASTEXITCODE -ne 0) { - Write-ErrorMessage "Build failed" - exit 1 - } - Write-Success "Build complete" -} -finally { - Pop-Location +& cmake --build $buildDir --config $Configuration +if ($LASTEXITCODE -ne 0) { + Write-ErrorMessage "Build failed" + exit 1 } +Write-Success "Build complete" # ============================================================================ # Output Information diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json deleted file mode 100644 index 20ee12dfe..000000000 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg-configuration.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json", - "default-registry": { - "kind": "git", - "baseline": "84bab45d415d22042bd0b9081aea57f362da3f35", - "repository": "https://github.com/microsoft/vcpkg" - }, - "overlay-ports": [ - "vcpkg_ports" - ] -} diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json deleted file mode 100644 index 9ecf53333..000000000 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", - "name": "winml-ep-catalog-sample", - "version-string": "1.0.0", - "description": "Windows ML Execution Provider Catalog C API Sample", - "dependencies": [ - { - "name": "microsoft-windows-ai-machinelearning", - "features": ["experimental"] - } - ] -} diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake deleted file mode 100644 index 81f4bd9bb..000000000 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/portfile.cmake +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (C) Microsoft Corporation. All rights reserved. - -# Package name is the same for stable and experimental -# Experimental versions are prerelease versions (e.g., 2.0.169-experimental) -set(WINML_PACKAGE_NAME "Microsoft.WindowsAppSDK.ML") - -# -# VERSION CONFIGURATION -# ===================== -# Update this version when a new experimental build is available. -# This is the NuGet package version to download from nuget.org. -# -set(WINML_EXPERIMENTAL_VERSION "2.0.233-experimental-gfb98279532") - -# Stable version placeholder (not used when experimental feature is enabled) -set(WINML_STABLE_VERSION "2.0.0") - -# Select version based on feature -if("experimental" IN_LIST FEATURES) - set(WINML_SDK_VERSION "${WINML_EXPERIMENTAL_VERSION}") -else() - set(WINML_SDK_VERSION "${WINML_STABLE_VERSION}") -endif() - -# Support local package override for development -# Option 1: Set environment variable WINML_LOCAL_PACKAGE to the .nupkg path -# Option 2: Place the .nupkg file in the sample's local_packages/ directory -set(WINML_LOCAL_PACKAGE_PATH "$ENV{WINML_LOCAL_PACKAGE}") - -# Check for local packages directory relative to the overlay port -if(NOT WINML_LOCAL_PACKAGE_PATH OR NOT EXISTS "${WINML_LOCAL_PACKAGE_PATH}") - # Look in sample's local_packages folder (sibling to vcpkg_ports) - get_filename_component(SAMPLE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) - set(LOCAL_PKG_DIR "${SAMPLE_DIR}/local_packages") - set(LOCAL_PKG_FILE "${LOCAL_PKG_DIR}/${WINML_PACKAGE_NAME}.${WINML_SDK_VERSION}.nupkg") - if(EXISTS "${LOCAL_PKG_FILE}") - set(WINML_LOCAL_PACKAGE_PATH "${LOCAL_PKG_FILE}") - endif() -endif() - -if(WINML_LOCAL_PACKAGE_PATH AND EXISTS "${WINML_LOCAL_PACKAGE_PATH}") - file(TO_CMAKE_PATH "${WINML_LOCAL_PACKAGE_PATH}" WINML_LOCAL_PACKAGE_PATH) - set(WINML_SDK_NUGET_URL "file://${WINML_LOCAL_PACKAGE_PATH}") - message(STATUS "WINML: Using local package: ${WINML_LOCAL_PACKAGE_PATH}") - set(WINML_SKIP_HASH TRUE) -else() - set(WINML_SDK_NUGET_URL "https://www.nuget.org/api/v2/package/${WINML_PACKAGE_NAME}/${WINML_SDK_VERSION}") - # Skip hash for experimental versions (they change frequently during development) - if("experimental" IN_LIST FEATURES) - set(WINML_SKIP_HASH TRUE) - else() - set(WINML_SKIP_HASH FALSE) - endif() -endif() - -# Download the NuGet package -if(WINML_SKIP_HASH) - vcpkg_download_distfile( - WINML_ARCHIVE - URLS "${WINML_SDK_NUGET_URL}" - FILENAME "${WINML_PACKAGE_NAME}.${WINML_SDK_VERSION}.zip" - SKIP_SHA512 - ) -else() - # SHA512 hash for stable version (update when stable version changes) - set(WINML_SDK_SHA512 "0") - - vcpkg_download_distfile( - WINML_ARCHIVE - URLS "${WINML_SDK_NUGET_URL}" - FILENAME "${WINML_PACKAGE_NAME}.${WINML_SDK_VERSION}.zip" - SHA512 ${WINML_SDK_SHA512} - ) -endif() - -vcpkg_extract_source_archive( - WINML_EXTRACTED_FILES - ARCHIVE "${WINML_ARCHIVE}" - NO_REMOVE_ONE_LEVEL -) - -# Architecture mapping -if(VCPKG_TARGET_ARCHITECTURE STREQUAL "x64") - set(WINML_ARCH "x64") - set(WINML_NUGET_ARCH "win-x64") -elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL "arm64") - set(WINML_ARCH "arm64") - set(WINML_NUGET_ARCH "win-arm64") -else() - message(FATAL_ERROR "Unsupported architecture: ${VCPKG_TARGET_ARCHITECTURE}") -endif() - -# Install headers -file(INSTALL "${WINML_EXTRACTED_FILES}/include/winml/" DESTINATION "${CURRENT_PACKAGES_DIR}/include/winml") -file(INSTALL "${WINML_EXTRACTED_FILES}/include/WinMLEpCatalog.h" DESTINATION "${CURRENT_PACKAGES_DIR}/include") - -# Install import libraries -file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/onnxruntime.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/lib") -if(EXISTS "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib") - file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/lib") -endif() - -# Install runtime DLLs -file(INSTALL - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime.dll" - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime_providers_shared.dll" - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/Microsoft.Windows.AI.MachineLearning.dll" - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/DirectML.dll" - DESTINATION "${CURRENT_PACKAGES_DIR}/bin" -) - -# Debug configuration -if(NOT VCPKG_BUILD_TYPE) - file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/onnxruntime.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") - if(EXISTS "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib") - file(INSTALL "${WINML_EXTRACTED_FILES}/lib/native/${WINML_ARCH}/Microsoft.Windows.AI.MachineLearning.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") - endif() - file(INSTALL - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime.dll" - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/onnxruntime_providers_shared.dll" - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/Microsoft.Windows.AI.MachineLearning.dll" - "${WINML_EXTRACTED_FILES}/runtimes-framework/${WINML_NUGET_ARCH}/native/DirectML.dll" - DESTINATION "${CURRENT_PACKAGES_DIR}/debug/bin" - ) -endif() - -# Install CMake config files -file(INSTALL - "${WINML_EXTRACTED_FILES}/cmake/microsoft-windows-ai-machinelearning-config.cmake" - "${WINML_EXTRACTED_FILES}/cmake/microsoft-windows-ai-machinelearning-targets.cmake" - DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" -) - -file(READ "${CURRENT_PACKAGES_DIR}/share/${PORT}/microsoft-windows-ai-machinelearning-config.cmake" CONFIG_CONTENT) -string(REPLACE "@WINML_VERSION@" "${WINML_SDK_VERSION}" CONFIG_CONTENT "${CONFIG_CONTENT}") -file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/microsoft-windows-ai-machinelearning-config.cmake" "${CONFIG_CONTENT}") - -file(RENAME - "${CURRENT_PACKAGES_DIR}/share/${PORT}/microsoft-windows-ai-machinelearning-config.cmake" - "${CURRENT_PACKAGES_DIR}/share/${PORT}/${PORT}-config.cmake" -) - -# Install documentation and license -file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") -file(INSTALL "${WINML_EXTRACTED_FILES}/license.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) - -if(EXISTS "${WINML_EXTRACTED_FILES}/ThirdPartyNotices.txt") - file(INSTALL "${WINML_EXTRACTED_FILES}/ThirdPartyNotices.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") -endif() diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage deleted file mode 100644 index e1d4c98fa..000000000 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/usage +++ /dev/null @@ -1,24 +0,0 @@ -microsoft-windows-ai-machinelearning provides CMake integration: - - find_package(microsoft-windows-ai-machinelearning CONFIG REQUIRED) - - # For Windows ML API (requires both DLLs at runtime): - target_link_libraries(main PRIVATE WindowsML::Api) - - # For direct OnnxRuntime C API access: - target_link_libraries(main PRIVATE WindowsML::OnnxRuntime) - - # For both (if using both APIs): - target_link_libraries(main PRIVATE WindowsML::Api WindowsML::OnnxRuntime) - -Available CMake targets: - WindowsML::Api - Windows ML API (Microsoft.Windows.AI.MachineLearning.lib) - WindowsML::OnnxRuntime - OnnxRuntime C API (onnxruntime.lib) - -Helper function to copy runtime DLLs to build output: - - winml_copy_runtime_dlls(MyApp) - -Package variants: - Stable: vcpkg install microsoft-windows-ai-machinelearning - Experimental: vcpkg install microsoft-windows-ai-machinelearning[experimental] diff --git a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json b/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json deleted file mode 100644 index aa47c317c..000000000 --- a/Samples/WindowsML/cmake/WinMLEpCatalog/vcpkg_ports/microsoft-windows-ai-machinelearning/vcpkg.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "microsoft-windows-ai-machinelearning", - "version": "2.0.233-experimental-gfb98279532", - "maintainers": "Microsoft Corporation", - "description": "Windows ML inference SDK with OnnxRuntime and DirectML.", - "homepage": "https://github.com/microsoft/windowsappsdk", - "license": "MIT", - "supports": "windows & (x64 | arm64)", - "dependencies": [ - { - "name": "vcpkg-cmake-config", - "host": true - } - ], - "features": { - "experimental": { - "description": "Use experimental (preview) builds instead of stable releases." - } - } -}