-
Notifications
You must be signed in to change notification settings - Fork 311
Add WinML EP Catalog CMake sample with NuGet package integration #593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/experimental
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Build outputs | ||
| out/ | ||
| build/ | ||
|
|
||
| # CMake cache | ||
| CMakeCache.txt | ||
| CMakeFiles/ | ||
|
|
||
| # Local package overrides (for development/testing) | ||
| local_packages/ | ||
|
|
||
| # IDE files | ||
| .vs/ | ||
| .vscode/ | ||
| *.user | ||
|
|
||
| # Compiled files | ||
| *.exe | ||
| *.dll | ||
| *.pdb | ||
| *.obj | ||
| *.ilk |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| # 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 | ||
| ) | ||
|
|
||
| # 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}") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| set(_winml_extract_dir "${WINML_LOCAL_PACKAGES_DIR}/${_winml_nupkg_name}") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two could use |
||
| 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) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
|
||
| # Create the executable | ||
| add_executable(WinMLEpCatalogSample | ||
| main.cpp | ||
| ) | ||
|
|
||
| # 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 (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 | ||
| $<TARGET_RUNTIME_DLLS:WinMLEpCatalogSample> $<TARGET_FILE_DIR:WinMLEpCatalogSample> | ||
| 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}" $<TARGET_FILE_DIR: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$<$<CONFIG:Debug>:Debug>" | ||
| ) | ||
| endif() | ||
|
|
||
| # Set subsystem to console (not Windows GUI) | ||
| if(WIN32) | ||
| set_target_properties(WinMLEpCatalogSample PROPERTIES | ||
| WIN32_EXECUTABLE FALSE | ||
| ) | ||
| endif() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| { | ||
| "version": 6, | ||
| "cmakeMinimumRequired": { | ||
| "major": 3, | ||
| "minor": 21, | ||
| "patch": 0 | ||
| }, | ||
| "configurePresets": [ | ||
| { | ||
| "name": "nuget", | ||
| "displayName": "NuGet (Direct)", | ||
| "description": "Configure using local .nupkg extraction and direct CMake package files", | ||
| "generator": "Ninja", | ||
| "binaryDir": "${sourceDir}/out/build/${presetName}", | ||
| "condition": { | ||
| "type": "equals", | ||
| "lhs": "${hostSystemName}", | ||
| "rhs": "Windows" | ||
| } | ||
| } | ||
| ], | ||
| "buildPresets": [ | ||
| { | ||
| "name": "nuget", | ||
| "configurePreset": "nuget" | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # Windows ML EP Catalog Sample (CMake/WinML C API) | ||
|
|
||
| This sample demonstrates the **WinMLEpCatalog WinML C API** for discovering and managing hardware-accelerated execution providers (EPs) for machine learning inference on Windows. | ||
|
|
||
| The CMake project is configured to use the Windows ML NuGet package directly and auto-extract it during configure. | ||
|
|
||
| ## Overview | ||
|
|
||
| This sample showcases: | ||
|
|
||
| - Creating an ONNX Runtime environment (`Ort::Env`) | ||
| - Creating and releasing a catalog handle | ||
| - Enumerating registered execution providers | ||
| - Inspecting provider metadata (name, version, state, certification) | ||
| - Preparing providers with `EnsureReady` | ||
| - Registering prepared providers with ONNX Runtime | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - **Visual Studio 2022** with C++ workload | ||
| - **CMake** 3.21 or later | ||
| - **Ninja** (optional; only needed when using Ninja generator) | ||
| - `Microsoft.WindowsAppSDK.ML.2.0.246-experimental.nupkg` in this folder | ||
|
|
||
| Example install commands: | ||
|
|
||
| ```powershell | ||
| winget install --exact --id Kitware.CMake | ||
| winget install --exact --id Ninja-build.Ninja | ||
| ``` | ||
|
|
||
| ## Build (Recommended) | ||
|
|
||
| Use the helper script: | ||
|
|
||
| ```powershell | ||
| # RelWithDebInfo for host architecture | ||
| .\build.ps1 | ||
|
|
||
| # Debug with Visual Studio generator | ||
| .\build.ps1 -Generator VisualStudio -Configuration Debug | ||
|
|
||
| # Release for ARM64 | ||
| .\build.ps1 -Configuration Release -Platform arm64 | ||
|
|
||
| # Clean and rebuild | ||
| .\build.ps1 -Clean | ||
| ``` | ||
|
|
||
| During configure, CMake automatically: | ||
|
|
||
| 1. Finds the local `.nupkg` | ||
| 2. Extracts it to `local_packages/<nupkg-name>/` (if not already extracted) | ||
| 3. Sets `microsoft.windows.ai.machinelearning_DIR` to the extracted `build/cmake` folder | ||
|
|
||
| ## Manual Build | ||
|
|
||
| ```powershell | ||
| # Configure (auto-extracts nupkg if needed) | ||
| cmake --preset nuget | ||
|
|
||
| # Build | ||
| cmake --build out/build/nuget --config RelWithDebInfo | ||
|
|
||
| # Run | ||
| .\out\build\nuget\WinMLEpCatalogSample.exe | ||
| ``` | ||
|
|
||
| ## Package Version Override | ||
|
|
||
| To use a different package file: | ||
|
|
||
| ```powershell | ||
| cmake --preset nuget -DWINML_NUGET_PACKAGE=.\Microsoft.WindowsAppSDK.ML.<new-version>.nupkg | ||
| ``` | ||
|
|
||
| For a full refresh, delete `local_packages/` and `out/` and configure again. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### "Windows ML NuGet package not found" | ||
|
|
||
| Ensure the package exists in this directory, or pass `-DWINML_NUGET_PACKAGE=<path-to-nupkg>`. | ||
|
|
||
| ### "Failed to create EP catalog" | ||
|
|
||
| Check that runtime DLLs were copied to the executable output directory and the target OS is supported. | ||
|
|
||
| ## License | ||
|
|
||
| Copyright (C) Microsoft Corporation. All rights reserved. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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|RelWithDebInfo|MinSizeRel] [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% | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider extracting somewhere under the CMAKE_CURRENT_BINARY_DIR or CMAKE_BINARY_DIR so that the source tree isn't touched.