diff --git a/.pipelines/foundry-local-packaging.yml b/.pipelines/foundry-local-packaging.yml index e67dc61c6..20e40c62c 100644 --- a/.pipelines/foundry-local-packaging.yml +++ b/.pipelines/foundry-local-packaging.yml @@ -3,9 +3,7 @@ # Builds Foundry Local Core from neutron-server (windows.ai.toolkit project), # then packages the C# and JS SDKs from this repo using the built Core. # -# Produces artifacts: flc-nuget, flc-nuget-winml, flc-wheels, flc-wheels-winml, -# cs-sdk, cs-sdk-winml, js-sdk, js-sdk-winml, python-sdk, python-sdk-winml, -# rust-sdk, rust-sdk-winml +# Produces artifacts: flc-nuget, flc-wheels, cs-sdk, js-sdk, python-sdk, rust-sdk # CI: only auto-run on pushes to main / release branches. Without an explicit # trigger block, ADO defaults to "every commit on every branch", which fires @@ -54,17 +52,11 @@ parameters: variables: - group: FoundryLocal-ESRP-Signing # C++ SDK (sdk_v2/cpp) native dependency versions. Must match cmake defaults -# in sdk_v2/deps_versions.json and sdk_v2/deps_versions_winml.json. +# in sdk_v2/deps_versions.json. - name: cppOrtVersion value: '1.25.1' -- name: cppOrtVersionWinml - # Pinned to the WinML-aligned ORT line so foundry_local.dll's ORT ABI matches - # the WinML EP catalog plugins it loads. See FindOnnxRuntime.cmake. - value: '1.23.2.3' - name: cppGenaiVersion value: '0.13.2' -- name: cppWinmlVersion - value: '1.8.2192' - name: cppBuildConfig value: 'RelWithDebInfo' @@ -167,7 +159,6 @@ extends: # ── Compute Version ── # A single version string is computed once and shared across all stages. - # This prevents timestamp drift between standard and WinML builds. # Outputs (written to the `version-info` pipeline artifact): # sdk_v2 (no suffix; FLC is legacy-only and not emitted here): # sdkVersion.txt – semver for C# (e.g. X.Y.Z-dev.202604061234) @@ -269,6 +260,4 @@ extends: parameters: buildConfig: $(cppBuildConfig) ortVersion: $(cppOrtVersion) - ortVersionWinml: $(cppOrtVersionWinml) genaiVersion: $(cppGenaiVersion) - winmlVersion: $(cppWinmlVersion) diff --git a/.pipelines/v2/templates/stages-build-native.yml b/.pipelines/v2/templates/stages-build-native.yml index 295b9a934..2331915b4 100644 --- a/.pipelines/v2/templates/stages-build-native.yml +++ b/.pipelines/v2/templates/stages-build-native.yml @@ -1,25 +1,18 @@ # Native build + pack stages for the Foundry Local C++ SDK. # -# Per-platform stages each produce a `cpp-native-[-winml]` pipeline -# artifact. Two pack stages assemble the artifacts into separate NuGet -# packages on every build (PR and main): +# Per-platform stages each produce a `cpp-native-` pipeline artifact. +# A single pack stage assembles the artifacts into a NuGet package: # -# pack_nuget – Microsoft.AI.Foundry.Local.Runtime -# (win-x64, win-arm64, linux-x64, osx-arm64) -# pack_nuget_winml – Microsoft.AI.Foundry.Local.Runtime.WinML -# (win-x64, win-arm64; both built with --use_winml) +# pack_nuget – Microsoft.AI.Foundry.Local.Runtime +# (win-x64, win-arm64, linux-x64, osx-arm64) parameters: - name: buildConfig type: string - name: ortVersion type: string -- name: ortVersionWinml - type: string - name: genaiVersion type: string -- name: winmlVersion - type: string stages: @@ -54,7 +47,6 @@ stages: buildConfig: ${{ parameters.buildConfig }} ortVersion: ${{ parameters.ortVersion }} genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: ${{ parameters.winmlVersion }} runTests: true stageHeaders: true @@ -86,7 +78,6 @@ stages: buildConfig: ${{ parameters.buildConfig }} ortVersion: ${{ parameters.ortVersion }} genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: ${{ parameters.winmlVersion }} runTests: false stageHeaders: false @@ -150,77 +141,6 @@ stages: genaiVersion: ${{ parameters.genaiVersion }} runTests: true - # ==================================================================== - # Windows x64 (WinML) — build + test - # The WinML variant links against the WinML-aligned ORT (1.23.x), which - # is older than the base ORT and lacks some ops used by cataloged vision - # models (e.g. com.microsoft:CausalConvWithState). The C++ VisionFixture - # and the C# VisionTests both skip themselves on WinML so the rest of - # the suite still runs against this configuration. - # ==================================================================== - - stage: cpp_build_win_x64_winml - displayName: 'C++ Native: Windows x64 (WinML)' - dependsOn: - - compute_version - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - outputs: - - output: pipelineArtifact - artifactName: 'cpp-native-win-x64-winml' - targetPath: '$(Build.ArtifactStagingDirectory)/native' - steps: - - template: steps-build-windows.yml - parameters: - arch: x64 - buildConfig: ${{ parameters.buildConfig }} - ortVersion: ${{ parameters.ortVersionWinml }} - genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: ${{ parameters.winmlVersion }} - useWinml: true - runTests: true - stageHeaders: false - - # ==================================================================== - # Windows ARM64 (WinML) — cross-compile only - # ==================================================================== - - stage: cpp_build_win_arm64_winml - displayName: 'C++ Native: Windows ARM64 (WinML)' - dependsOn: - - compute_version - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - outputs: - - output: pipelineArtifact - artifactName: 'cpp-native-win-arm64-winml' - targetPath: '$(Build.ArtifactStagingDirectory)/native' - steps: - - template: steps-build-windows.yml - parameters: - arch: arm64 - buildConfig: ${{ parameters.buildConfig }} - ortVersion: ${{ parameters.ortVersionWinml }} - genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: ${{ parameters.winmlVersion }} - useWinml: true - runTests: false - stageHeaders: false - # ==================================================================== # Pack — base NuGet package (all 4 platforms) # ==================================================================== @@ -263,40 +183,3 @@ stages: parameters: ortVersion: ${{ parameters.ortVersion }} genaiVersion: ${{ parameters.genaiVersion }} - variant: base - - # ==================================================================== - # Pack — WinML NuGet package (Windows x64 + arm64 only) - # ==================================================================== - - stage: cpp_pack_nuget_winml - displayName: 'C++ Native: Pack NuGet (WinML)' - dependsOn: - - compute_version - - cpp_build_win_x64_winml - - cpp_build_win_arm64_winml - jobs: - - job: pack - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-win-x64-winml' - targetPath: '$(Pipeline.Workspace)/cpp-native-win-x64-winml' - - input: pipelineArtifact - artifactName: 'cpp-native-win-arm64-winml' - targetPath: '$(Pipeline.Workspace)/cpp-native-win-arm64-winml' - outputs: - - output: pipelineArtifact - artifactName: 'cpp-nuget-winml' - targetPath: '$(Build.ArtifactStagingDirectory)/nuget' - steps: - - template: steps-pack-nuget.yml - parameters: - ortVersion: ${{ parameters.ortVersionWinml }} - genaiVersion: ${{ parameters.genaiVersion }} - variant: winml diff --git a/.pipelines/v2/templates/stages-cs.yml b/.pipelines/v2/templates/stages-cs.yml index 8ebc67ff1..a611cf0ea 100644 --- a/.pipelines/v2/templates/stages-cs.yml +++ b/.pipelines/v2/templates/stages-cs.yml @@ -1,41 +1,28 @@ -# Build + test stages for the sdk_v2 C# SDK, parameterized by variant. +# Build + test stages for the sdk_v2 C# SDK. # -# variant: base -> Microsoft.AI.Foundry.Local (build + test win/linux/osx) -# variant: winml -> Microsoft.AI.Foundry.Local.WinML (build + test win only) +# variant: base -> Microsoft.AI.Foundry.Local (build + test win/linux/osx) # -# Depends on the matching native pack stage from stages-build-native.yml: -# base -> cpp_pack_nuget (artifact: cpp-nuget) -# winml -> cpp_pack_nuget_winml (artifact: cpp-nuget-winml) +# Depends on the native pack stage from stages-build-native.yml: +# base -> cpp_pack_nuget (artifact: cpp-nuget) # -# Produces a `cs-sdk-v2-` pipeline artifact containing the signed +# Produces a `cs-sdk-v2-base` pipeline artifact containing the signed # .nupkg (+ .snupkg). parameters: - name: variant type: string default: 'base' - values: ['base', 'winml'] + values: ['base'] -# Per-variant config block selected at template-expansion time. Keeps the -# stage bodies free of nested ${{ if }} branching for static naming. +# Per-variant config block selected at template-expansion time. - name: _config_base type: object default: suffix: 'base' - isWinML: false packStage: 'cpp_pack_nuget' nativeArtifact: 'cpp-nuget' csArtifact: 'cs-sdk-v2-base' -- name: _config_winml - type: object - default: - suffix: 'winml' - isWinML: true - packStage: 'cpp_pack_nuget_winml' - nativeArtifact: 'cpp-nuget-winml' - csArtifact: 'cs-sdk-v2-winml' - stages: # ==================================================================== @@ -70,39 +57,6 @@ stages: - template: steps-build-cs.yml parameters: flNugetDir: '$(Pipeline.Workspace)/${{ parameters._config_base.nativeArtifact }}' - isWinML: false - outputDir: '$(Build.ArtifactStagingDirectory)/cs-sdk' - -- ${{ if eq(parameters.variant, 'winml') }}: - - stage: cs_build_winml - displayName: 'C# SDK: Build (WinML)' - dependsOn: - - compute_version - - ${{ parameters._config_winml.packStage }} - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: ${{ parameters._config_winml.nativeArtifact }} - targetPath: '$(Pipeline.Workspace)/${{ parameters._config_winml.nativeArtifact }}' - outputs: - - output: pipelineArtifact - artifactName: ${{ parameters._config_winml.csArtifact }} - targetPath: '$(Build.ArtifactStagingDirectory)/cs-sdk' - steps: - - checkout: self - clean: true - - template: steps-build-cs.yml - parameters: - flNugetDir: '$(Pipeline.Workspace)/${{ parameters._config_winml.nativeArtifact }}' - isWinML: true outputDir: '$(Build.ArtifactStagingDirectory)/cs-sdk' # ==================================================================== @@ -135,41 +89,11 @@ stages: - template: steps-test-cs.yml parameters: flNugetDir: '$(Pipeline.Workspace)/${{ parameters._config_base.nativeArtifact }}' - isWinML: false testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' -- ${{ if eq(parameters.variant, 'winml') }}: - - stage: cs_test_win_x64_winml - displayName: 'C# SDK: Test Windows x64 (WinML)' - dependsOn: - - cs_build_winml - jobs: - - job: test - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: ${{ parameters._config_winml.nativeArtifact }} - targetPath: '$(Pipeline.Workspace)/${{ parameters._config_winml.nativeArtifact }}' - steps: - - checkout: self - clean: true - - template: ../../templates/checkout-steps.yml@self - parameters: - repoName: test-data-shared - - template: steps-test-cs.yml - parameters: - flNugetDir: '$(Pipeline.Workspace)/${{ parameters._config_winml.nativeArtifact }}' - isWinML: true - testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' # ==================================================================== -# Test — Linux x64 / macOS ARM64 (base variant only; WinML is Windows-only) +# Test — Linux x64 / macOS ARM64 # ==================================================================== - ${{ if eq(parameters.variant, 'base') }}: - stage: cs_test_linux_x64 @@ -198,7 +122,6 @@ stages: - template: steps-test-cs.yml parameters: flNugetDir: '$(Pipeline.Workspace)/${{ parameters._config_base.nativeArtifact }}' - isWinML: false testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' - stage: cs_test_osx_arm64 @@ -236,5 +159,4 @@ stages: - template: steps-test-cs.yml parameters: flNugetDir: '$(Pipeline.Workspace)/${{ parameters._config_base.nativeArtifact }}' - isWinML: false testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' diff --git a/.pipelines/v2/templates/stages-python.yml b/.pipelines/v2/templates/stages-python.yml index 7a07c7dae..3b5dae5fb 100644 --- a/.pipelines/v2/templates/stages-python.yml +++ b/.pipelines/v2/templates/stages-python.yml @@ -1,22 +1,20 @@ -# Build + test stages for the sdk_v2 Python SDK, parameterized by variant. +# Build + test stages for the sdk_v2 Python SDK. # -# variant: base -> foundry-local-sdk (build win-x64 + win-arm64 + linux-x64 + osx-arm64; -# test win-x64 + linux-x64 + osx-arm64) -# variant: winml -> foundry-local-sdk-winml (build + test win-x64; build-only win-arm64) +# variant: base -> foundry-local-sdk (build win-x64 + win-arm64 + linux-x64 + osx-arm64; +# test win-x64 + linux-x64 + osx-arm64) # # Each build stage depends on the matching native build stage from -# stages-build-native.yml and consumes the `cpp-native-[-winml]` -# pipeline artifact directly (no NuGet — the wheel bundles the native lib +# stages-build-native.yml and consumes the `cpp-native-` pipeline +# artifact directly (no NuGet — the wheel bundles the native lib # at src/foundry_local_sdk/_native//). # -# Each build stage emits one wheel under the -# `python-sdk--` pipeline artifact. +# Each build stage emits one wheel under the `python-sdk-base-` pipeline artifact. parameters: - name: variant type: string default: 'base' - values: ['base', 'winml'] + values: ['base'] stages: @@ -54,7 +52,6 @@ stages: parameters: nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-x64' rid: 'win-x64' - isWinML: false outputDir: '$(Build.ArtifactStagingDirectory)/python-sdk' - stage: python_build_base_win_arm64 @@ -86,7 +83,6 @@ stages: parameters: nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-arm64' rid: 'win-arm64' - isWinML: false targetArch: 'arm64' outputDir: '$(Build.ArtifactStagingDirectory)/python-sdk' @@ -119,7 +115,6 @@ stages: parameters: nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-linux-x64' rid: 'linux-x64' - isWinML: false outputDir: '$(Build.ArtifactStagingDirectory)/python-sdk' - stage: python_build_base_osx_arm64 @@ -153,7 +148,6 @@ stages: parameters: nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-osx-arm64' rid: 'osx-arm64' - isWinML: false pythonArchitecture: 'arm64' outputDir: '$(Build.ArtifactStagingDirectory)/python-sdk' @@ -185,7 +179,6 @@ stages: parameters: wheelDir: '$(Pipeline.Workspace)/python-sdk-base-win-x64' testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' - isWinML: false - stage: python_test_base_linux_x64 displayName: 'Python SDK: Test Linux x64 (base)' @@ -211,7 +204,6 @@ stages: parameters: wheelDir: '$(Pipeline.Workspace)/python-sdk-base-linux-x64' testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' - isWinML: false - stage: python_test_base_osx_arm64 displayName: 'Python SDK: Test macOS ARM64 (base)' @@ -246,101 +238,4 @@ stages: parameters: wheelDir: '$(Pipeline.Workspace)/python-sdk-base-osx-arm64' testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' - isWinML: false pythonArchitecture: 'arm64' - -# ===================================================================== -# WinML variant: Windows only (x64 + arm64); only x64 is tested. -# ===================================================================== -- ${{ if eq(parameters.variant, 'winml') }}: - - - stage: python_build_winml_win_x64 - displayName: 'Python SDK: Build Windows x64 (WinML)' - dependsOn: - - compute_version - - cpp_build_win_x64_winml - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-win-x64-winml' - targetPath: '$(Pipeline.Workspace)/cpp-native-win-x64-winml' - outputs: - - output: pipelineArtifact - artifactName: 'python-sdk-winml-win-x64' - targetPath: '$(Build.ArtifactStagingDirectory)/python-sdk' - steps: - - checkout: self - clean: true - - template: steps-build-python.yml - parameters: - nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-x64-winml' - rid: 'win-x64' - isWinML: true - outputDir: '$(Build.ArtifactStagingDirectory)/python-sdk' - - - stage: python_build_winml_win_arm64 - displayName: 'Python SDK: Build Windows ARM64 (WinML)' - dependsOn: - - compute_version - - cpp_build_win_arm64_winml - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-win-arm64-winml' - targetPath: '$(Pipeline.Workspace)/cpp-native-win-arm64-winml' - outputs: - - output: pipelineArtifact - artifactName: 'python-sdk-winml-win-arm64' - targetPath: '$(Build.ArtifactStagingDirectory)/python-sdk' - steps: - - checkout: self - clean: true - - template: steps-build-python.yml - parameters: - nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-arm64-winml' - rid: 'win-arm64' - isWinML: true - targetArch: 'arm64' - outputDir: '$(Build.ArtifactStagingDirectory)/python-sdk' - - - stage: python_test_winml_win_x64 - displayName: 'Python SDK: Test Windows x64 (WinML)' - dependsOn: - - python_build_winml_win_x64 - jobs: - - job: test - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'python-sdk-winml-win-x64' - targetPath: '$(Pipeline.Workspace)/python-sdk-winml-win-x64' - steps: - - checkout: self - clean: true - - template: ../../templates/checkout-steps.yml@self - parameters: - repoName: test-data-shared - - template: steps-test-python.yml - parameters: - wheelDir: '$(Pipeline.Workspace)/python-sdk-winml-win-x64' - testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' - isWinML: true diff --git a/.pipelines/v2/templates/stages-sdk-v2.yml b/.pipelines/v2/templates/stages-sdk-v2.yml index c2cae47d1..7d094a3c2 100644 --- a/.pipelines/v2/templates/stages-sdk-v2.yml +++ b/.pipelines/v2/templates/stages-sdk-v2.yml @@ -2,8 +2,8 @@ # # Composes: # 1. Native C++ build + pack (templates/stages-build-native.yml) -# 2. C# SDK base + WinML (templates/stages-cs.yml × 2) -# 3. Python SDK base + WinML (templates/stages-python.yml × 2) +# 2. C# SDK (templates/stages-cs.yml) +# 3. Python SDK (templates/stages-python.yml) # # Assumes the caller has already emitted a `compute_version` stage that # publishes the `version-info` pipeline artifact (containing sdkVersion.txt @@ -16,12 +16,8 @@ parameters: default: 'RelWithDebInfo' - name: ortVersion type: string -- name: ortVersionWinml - type: string - name: genaiVersion type: string -- name: winmlVersion - type: string stages: @@ -30,29 +26,17 @@ stages: parameters: buildConfig: ${{ parameters.buildConfig }} ortVersion: ${{ parameters.ortVersion }} - ortVersionWinml: ${{ parameters.ortVersionWinml }} genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: ${{ parameters.winmlVersion }} -# ── C# SDK (base) ── +# ── C# SDK ── - template: stages-cs.yml parameters: variant: base -# ── C# SDK (WinML) ── -- template: stages-cs.yml - parameters: - variant: winml - -# ── Python SDK (base) ── +# ── Python SDK ── - template: stages-python.yml parameters: variant: base -# ── Python SDK (WinML) ── -- template: stages-python.yml - parameters: - variant: winml - # ── JS SDK (single multi-platform tarball) ── - template: stages-js.yml diff --git a/.pipelines/v2/templates/steps-build-cs.yml b/.pipelines/v2/templates/steps-build-cs.yml index 1c77af191..2ebf7e085 100644 --- a/.pipelines/v2/templates/steps-build-cs.yml +++ b/.pipelines/v2/templates/steps-build-cs.yml @@ -1,8 +1,8 @@ # Inner steps to restore, build, sign, and pack the sdk_v2 C# SDK -# (Microsoft.AI.Foundry.Local / Microsoft.AI.Foundry.Local.WinML). +# (Microsoft.AI.Foundry.Local). # # The caller is responsible for placing the Foundry Local Runtime nupkg -# (Microsoft.AI.Foundry.Local.Runtime[.WinML]) in `flNugetDir`, and for +# (Microsoft.AI.Foundry.Local.Runtime) in `flNugetDir`, and for # downloading the `version-info` pipeline artifact so this template can # read $(Pipeline.Workspace)/version-info/sdkVersion.txt. @@ -10,9 +10,6 @@ parameters: - name: flNugetDir type: string displayName: 'Path to directory containing the Foundry Local Runtime .nupkg' -- name: isWinML - type: boolean - default: false - name: outputDir type: string default: '$(Build.ArtifactStagingDirectory)/cs-sdk' @@ -92,7 +89,6 @@ steps: if (-not (Test-Path $proj)) { throw "Project not found: $proj" } dotnet restore $proj ` --configfile "$(customNugetConfig)" ` - /p:UseWinML=${{ parameters.isWinML }} ` /p:FoundryLocalRuntimeVersion=$(packageVersion) ` /p:FoundryLocalNativeBinDir= if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } @@ -105,7 +101,6 @@ steps: script: | dotnet build "$(Build.SourcesDirectory)/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj" ` --no-restore --configuration Release ` - /p:UseWinML=${{ parameters.isWinML }} ` /p:FoundryLocalRuntimeVersion=$(packageVersion) ` /p:FoundryLocalNativeBinDir= if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } @@ -145,7 +140,6 @@ steps: --no-build --no-restore --configuration Release ` --output "${{ parameters.outputDir }}" ` /p:PackageVersion=$(packageVersion) ` - /p:UseWinML=${{ parameters.isWinML }} ` /p:FoundryLocalRuntimeVersion=$(packageVersion) ` /p:FoundryLocalNativeBinDir= ` /p:IncludeSymbols=true ` diff --git a/.pipelines/v2/templates/steps-build-linux.yml b/.pipelines/v2/templates/steps-build-linux.yml index b16b13fdd..b759c3a66 100644 --- a/.pipelines/v2/templates/steps-build-linux.yml +++ b/.pipelines/v2/templates/steps-build-linux.yml @@ -27,8 +27,6 @@ steps: parameters: ortVersion: ${{ parameters.ortVersion }} genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: '' - includeWinml: false includeOrtGpuLinux: true shell: bash diff --git a/.pipelines/v2/templates/steps-build-macos.yml b/.pipelines/v2/templates/steps-build-macos.yml index 278bdbff8..6d151ad9c 100644 --- a/.pipelines/v2/templates/steps-build-macos.yml +++ b/.pipelines/v2/templates/steps-build-macos.yml @@ -36,8 +36,6 @@ steps: parameters: ortVersion: ${{ parameters.ortVersion }} genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: '' - includeWinml: false shell: bash # Bake the pipeline-computed version into the binary so FoundryLocalGetVersionString() diff --git a/.pipelines/v2/templates/steps-build-python.yml b/.pipelines/v2/templates/steps-build-python.yml index fe81d69cd..432cfebc9 100644 --- a/.pipelines/v2/templates/steps-build-python.yml +++ b/.pipelines/v2/templates/steps-build-python.yml @@ -13,13 +13,10 @@ parameters: - name: nativeArtifactDir type: string - displayName: 'Path to the downloaded cpp-native-[-winml] artifact directory' + displayName: 'Path to the downloaded cpp-native- artifact directory' - name: rid type: string displayName: 'Runtime identifier (win-x64, win-arm64, linux-x64, osx-arm64)' -- name: isWinML - type: boolean - default: false - name: outputDir type: string default: '$(Build.ArtifactStagingDirectory)/python-sdk' @@ -270,13 +267,7 @@ steps: script: | $outDir = "${{ parameters.outputDir }}" New-Item -ItemType Directory -Force -Path $outDir | Out-Null - $isWinML = [bool]::Parse('${{ parameters.isWinML }}') - if ($isWinML) { - $env:FL_PYTHON_PACKAGE_NAME = 'foundry-local-sdk-winml' - Write-Host "WinML variant: FL_PYTHON_PACKAGE_NAME=$env:FL_PYTHON_PACKAGE_NAME" - } else { - Remove-Item Env:FL_PYTHON_PACKAGE_NAME -ErrorAction SilentlyContinue - } + Remove-Item Env:FL_PYTHON_PACKAGE_NAME -ErrorAction SilentlyContinue $targetArch = '${{ parameters.targetArch }}' $extraArgs = @() if ($targetArch -eq 'arm64') { diff --git a/.pipelines/v2/templates/steps-build-windows.yml b/.pipelines/v2/templates/steps-build-windows.yml index ba2d82d79..a4a498066 100644 --- a/.pipelines/v2/templates/steps-build-windows.yml +++ b/.pipelines/v2/templates/steps-build-windows.yml @@ -1,6 +1,6 @@ # Reusable Windows build steps for the Foundry Local C++ SDK. # -# Bootstraps vcpkg, pre-downloads ORT/GenAI/WinML packages, then configures, +# Bootstraps vcpkg, pre-downloads ORT/GenAI packages, then configures, # builds, optionally tests, and stages artifacts for the parent stage's # templateContext.outputs. # @@ -9,9 +9,6 @@ # buildConfig – CMake config (Debug, Release, RelWithDebInfo, MinSizeRel) # ortVersion – Microsoft.ML.OnnxRuntime.Foundry version # genaiVersion – Microsoft.ML.OnnxRuntimeGenAI.Foundry version -# winmlVersion – Microsoft.WindowsAppSDK.ML version -# useWinml – Build the WinML variant (--use_winml). Caller is responsible -# for passing the WinML-aligned ortVersion (e.g. 1.23.2.3). # runTests – Whether to run tests # stageHeaders – Whether to stage public headers as a separate artifact @@ -25,11 +22,6 @@ parameters: type: string - name: genaiVersion type: string -- name: winmlVersion - type: string -- name: useWinml - type: boolean - default: false - name: runTests type: boolean default: false @@ -60,8 +52,6 @@ steps: parameters: ortVersion: ${{ parameters.ortVersion }} genaiVersion: ${{ parameters.genaiVersion }} - winmlVersion: ${{ parameters.winmlVersion }} - includeWinml: ${{ parameters.useWinml }} shell: pwsh # Bake the pipeline-computed version into the binary so FoundryLocalGetVersionString() @@ -84,7 +74,7 @@ steps: repoName: test-data-shared basePath: '$(Agent.BuildDirectory)' -- ${{ if and(eq(parameters.arch, 'x64'), eq(parameters.useWinml, false)) }}: +- ${{ if eq(parameters.arch, 'x64') }}: - script: >- python build.py --configure --build @@ -97,21 +87,7 @@ steps: VCPKG_ROOT: $(Build.BinariesDirectory)\vcpkg PKG_CONFIG: $(Build.BinariesDirectory)\tools\pkg-config.bat -- ${{ if and(eq(parameters.arch, 'x64'), eq(parameters.useWinml, true)) }}: - - script: >- - python build.py - --configure --build - --config ${{ parameters.buildConfig }} - --cmake_generator "Visual Studio 17 2022" - --use_winml --winml_sdk_version ${{ parameters.winmlVersion }} - --cmake_extra_defines $(cmakeFetchDefines) - displayName: 'Configure and build (x64, WinML)' - workingDirectory: $(Build.SourcesDirectory)/sdk_v2/cpp - env: - VCPKG_ROOT: $(Build.BinariesDirectory)\vcpkg - PKG_CONFIG: $(Build.BinariesDirectory)\tools\pkg-config.bat - -- ${{ if and(eq(parameters.arch, 'arm64'), eq(parameters.useWinml, false)) }}: +- ${{ if eq(parameters.arch, 'arm64') }}: - script: >- python build.py --configure --build --arm64 @@ -124,20 +100,6 @@ steps: VCPKG_ROOT: $(Build.BinariesDirectory)\vcpkg PKG_CONFIG: $(Build.BinariesDirectory)\tools\pkg-config.bat -- ${{ if and(eq(parameters.arch, 'arm64'), eq(parameters.useWinml, true)) }}: - - script: >- - python build.py - --configure --build --arm64 - --config ${{ parameters.buildConfig }} - --cmake_generator "Visual Studio 17 2022" - --use_winml --winml_sdk_version ${{ parameters.winmlVersion }} - --cmake_extra_defines $(cmakeFetchDefines) - displayName: 'Configure and build (arm64 cross-compile, WinML)' - workingDirectory: $(Build.SourcesDirectory)/sdk_v2/cpp - env: - VCPKG_ROOT: $(Build.BinariesDirectory)\vcpkg - PKG_CONFIG: $(Build.BinariesDirectory)\tools\pkg-config.bat - - ${{ if and(eq(parameters.runTests, true), eq(parameters.arch, 'x64')) }}: - script: python build.py --test --config ${{ parameters.buildConfig }} displayName: 'Run tests' @@ -147,21 +109,9 @@ steps: FOUNDRY_TEST_DATA_DIR: $(Agent.BuildDirectory)\test-data-shared # Stage the redistributable native artifacts. -# - Standard build: vcpkg statically links ORT/GenAI/azure-*/spdlog/fmt/ -# libcurl/libssl/zlib/brotli* into foundry_local.dll (see -# sdk_v2/cpp/triplets/x64-windows.cmake), so the only runtime payload is -# foundry_local.dll itself. -# - WinML build: foundry_local.dll picks up one extra static import — -# Microsoft.WindowsAppRuntime.Bootstrap.dll — which is the entry point -# that calls MddBootstrapInitialize2 to register the system-installed -# Windows App Runtime. Bootstrap.dll must travel with the wheel because -# end-user / CI machines don't have it on PATH otherwise. Everything -# downstream of Bootstrap (Microsoft.Windows.AI.MachineLearning.dll, -# DirectML, the WinML-flavored ORT, etc.) is supplied by the system -# App Runtime that Bootstrap registers — Microsoft.Windows.AI.MachineLearning -# is delay-loaded (see /DELAYLOAD in CMakeLists.txt) so it is NOT needed at -# foundry_local.dll load time. ORT/GenAI come from the onnxruntime-core / -# onnxruntime-genai-core pip deps. +# vcpkg statically links ORT/GenAI/azure-*/spdlog/fmt/libcurl/libssl/zlib/brotli* +# into foundry_local.dll (see sdk_v2/cpp/triplets/x64-windows.cmake), so the only +# runtime payload is foundry_local.dll itself. - task: PowerShell@2 displayName: 'Stage native artifacts' inputs: @@ -178,9 +128,6 @@ steps: (Join-Path $binDir 'foundry_local.pdb'), (Join-Path $linkDir 'foundry_local.lib') ) - if ($${{ parameters.useWinml }}) { - $sources += (Join-Path $binDir 'Microsoft.WindowsAppRuntime.Bootstrap.dll') - } foreach ($s in $sources) { if (-not (Test-Path $s)) { diff --git a/.pipelines/v2/templates/steps-pack-nuget.yml b/.pipelines/v2/templates/steps-pack-nuget.yml index bde97d772..2af831a9d 100644 --- a/.pipelines/v2/templates/steps-pack-nuget.yml +++ b/.pipelines/v2/templates/steps-pack-nuget.yml @@ -3,22 +3,12 @@ # # Inputs are downloaded by the parent job's templateContext.inputs into # $(Pipeline.Workspace)//. -# -# Variants: -# base -> Microsoft.AI.Foundry.Local.Runtime -# (win-x64, win-arm64, linux-x64, osx-arm64) -# winml -> Microsoft.AI.Foundry.Local.Runtime.WinML -# (win-x64, win-arm64 only — both built with --use_winml) parameters: - name: ortVersion type: string - name: genaiVersion type: string -- name: variant - type: string - default: 'base' - values: ['base', 'winml'] steps: @@ -45,58 +35,30 @@ steps: } } -- ${{ if eq(parameters.variant, 'base') }}: - - task: PowerShell@2 - displayName: 'Pack NuGet package (base)' - inputs: - targetType: inline - pwsh: true - script: | - $ErrorActionPreference = 'Stop' - - $version = (Get-Content "$(Pipeline.Workspace)/version-info/sdkVersion.txt" -Raw).Trim() - Write-Host "Packing version: $version" - - $outDir = "$(Build.ArtifactStagingDirectory)/nuget" - New-Item -ItemType Directory -Force -Path $outDir | Out-Null - - python "$(Build.SourcesDirectory)/sdk_v2/cpp/nuget/pack.py" ` - --version "$version" ` - --package_id "Microsoft.AI.Foundry.Local.Runtime" ` - --ort_version "${{ parameters.ortVersion }}" ` - --genai_version "${{ parameters.genaiVersion }}" ` - --win_x64 "$(Pipeline.Workspace)/cpp-native-win-x64" ` - --win_arm64 "$(Pipeline.Workspace)/cpp-native-win-arm64" ` - --linux_x64 "$(Pipeline.Workspace)/cpp-native-linux-x64" ` - --osx_arm64 "$(Pipeline.Workspace)/cpp-native-osx-arm64" ` - --output_dir "$outDir" - - Write-Host "Generated packages:" - Get-ChildItem $outDir -Filter '*.nupkg' | ForEach-Object { Write-Host " $($_.Name)" } - -- ${{ if eq(parameters.variant, 'winml') }}: - - task: PowerShell@2 - displayName: 'Pack NuGet package (WinML)' - inputs: - targetType: inline - pwsh: true - script: | - $ErrorActionPreference = 'Stop' +- task: PowerShell@2 + displayName: 'Pack NuGet package' + inputs: + targetType: inline + pwsh: true + script: | + $ErrorActionPreference = 'Stop' - $version = (Get-Content "$(Pipeline.Workspace)/version-info/sdkVersion.txt" -Raw).Trim() - Write-Host "Packing version: $version" + $version = (Get-Content "$(Pipeline.Workspace)/version-info/sdkVersion.txt" -Raw).Trim() + Write-Host "Packing version: $version" - $outDir = "$(Build.ArtifactStagingDirectory)/nuget" - New-Item -ItemType Directory -Force -Path $outDir | Out-Null + $outDir = "$(Build.ArtifactStagingDirectory)/nuget" + New-Item -ItemType Directory -Force -Path $outDir | Out-Null - python "$(Build.SourcesDirectory)/sdk_v2/cpp/nuget/pack.py" ` - --version "$version" ` - --package_id "Microsoft.AI.Foundry.Local.Runtime.WinML" ` - --ort_version "${{ parameters.ortVersion }}" ` - --genai_version "${{ parameters.genaiVersion }}" ` - --win_x64 "$(Pipeline.Workspace)/cpp-native-win-x64-winml" ` - --win_arm64 "$(Pipeline.Workspace)/cpp-native-win-arm64-winml" ` - --output_dir "$outDir" + python "$(Build.SourcesDirectory)/sdk_v2/cpp/nuget/pack.py" ` + --version "$version" ` + --package_id "Microsoft.AI.Foundry.Local.Runtime" ` + --ort_version "${{ parameters.ortVersion }}" ` + --genai_version "${{ parameters.genaiVersion }}" ` + --win_x64 "$(Pipeline.Workspace)/cpp-native-win-x64" ` + --win_arm64 "$(Pipeline.Workspace)/cpp-native-win-arm64" ` + --linux_x64 "$(Pipeline.Workspace)/cpp-native-linux-x64" ` + --osx_arm64 "$(Pipeline.Workspace)/cpp-native-osx-arm64" ` + --output_dir "$outDir" - Write-Host "Generated packages:" - Get-ChildItem $outDir -Filter '*.nupkg' | ForEach-Object { Write-Host " $($_.Name)" } + Write-Host "Generated packages:" + Get-ChildItem $outDir -Filter '*.nupkg' | ForEach-Object { Write-Host " $($_.Name)" } diff --git a/.pipelines/v2/templates/steps-prefetch-nuget.yml b/.pipelines/v2/templates/steps-prefetch-nuget.yml index 70a83f7c2..40658e095 100644 --- a/.pipelines/v2/templates/steps-prefetch-nuget.yml +++ b/.pipelines/v2/templates/steps-prefetch-nuget.yml @@ -1,5 +1,5 @@ -# Pre-download ORT / GenAI / (optionally) WinML NuGet packages from the -# aiinfra ADO feed and emit cmake_extra_defines pointing at them. +# Pre-download ORT / GenAI NuGet packages from nuget.org and emit cmake_extra_defines +# pointing at them. # # Sets the pipeline variable `cmakeFetchDefines` containing the space-separated # `KEY=PATH` pairs to pass to build.py --cmake_extra_defines. @@ -7,8 +7,6 @@ # Parameters: # ortVersion – Microsoft.ML.OnnxRuntime.Foundry version # genaiVersion – Microsoft.ML.OnnxRuntimeGenAI.Foundry version -# winmlVersion – Microsoft.WindowsAppSDK.ML version (Windows only) -# includeWinml – Download WinML and emit WINML_EP_CATALOG_FETCH_URL # includeOrtGpuLinux – Also download Microsoft.ML.OnnxRuntime.Gpu.Linux (Linux only) # shell – 'pwsh' (Windows/macOS) or 'bash' (Linux) @@ -17,12 +15,6 @@ parameters: type: string - name: genaiVersion type: string -- name: winmlVersion - type: string - default: '' -- name: includeWinml - type: boolean - default: false - name: includeOrtGpuLinux type: boolean default: false @@ -73,37 +65,6 @@ steps: } } - if ($${{ parameters.includeWinml }}) { - # WinML's bootstrap dep (Microsoft.WindowsAppSDK.Foundation) is a transitive dep of - # Microsoft.WindowsAppSDK.ML, and nuget min-version semantics mean the exact min - # version often isn't published — only later patches are. Defer to `nuget install` - # so the real resolver picks a satisfying version. - $winmlDir = "$cacheDir/winml-resolved" - if (Test-Path $winmlDir) { Remove-Item -Recurse -Force $winmlDir } - New-Item -ItemType Directory -Force -Path $winmlDir | Out-Null - Write-Host "Resolving Microsoft.WindowsAppSDK.ML ${{ parameters.winmlVersion }} via nuget install" - nuget install Microsoft.WindowsAppSDK.ML ` - -Version '${{ parameters.winmlVersion }}' ` - -OutputDirectory $winmlDir ` - -Source 'https://api.nuget.org/v3/index.json' ` - -DependencyVersion Lowest ` - -PackageSaveMode nupkg ` - -DirectDownload ` - -Verbosity quiet - if ($LASTEXITCODE -ne 0) { throw "nuget install Microsoft.WindowsAppSDK.ML failed (exit $LASTEXITCODE)" } - - $mlNupkg = Get-ChildItem $winmlDir -Recurse -Filter 'Microsoft.WindowsAppSDK.ML.*.nupkg' | - Select-Object -First 1 - $foundationNupkg = Get-ChildItem $winmlDir -Recurse -Filter 'Microsoft.WindowsAppSDK.Foundation.*.nupkg' | - Select-Object -First 1 - if (-not $mlNupkg) { throw "Microsoft.WindowsAppSDK.ML .nupkg not found under $winmlDir after nuget install" } - if (-not $foundationNupkg) { throw "Microsoft.WindowsAppSDK.Foundation .nupkg not found under $winmlDir after nuget install" } - Write-Host " -> $($mlNupkg.FullName) ($($mlNupkg.Length) bytes)" - Write-Host " -> $($foundationNupkg.FullName) ($($foundationNupkg.Length) bytes)" - $defines += "WINML_EP_CATALOG_FETCH_URL=$($mlNupkg.FullName)" - $defines += "WINAPPSDK_FOUNDATION_FETCH_URL=$($foundationNupkg.FullName)" - } - $joined = ($defines | ForEach-Object { "`"$_`"" }) -join ' ' Write-Host "##vso[task.setvariable variable=cmakeFetchDefines]$joined" Write-Host "cmakeFetchDefines = $joined" @@ -124,13 +85,6 @@ steps: "genai:Microsoft.ML.OnnxRuntimeGenAI.Foundry:${{ parameters.genaiVersion }}" "ort:Microsoft.ML.OnnxRuntime.Foundry:${{ parameters.ortVersion }}" ) - if [ "${{ parameters.includeWinml }}" = "True" ]; then - # WinML is Windows-only; the bash branch should never receive includeWinml=true. - # If this fires, the prefetch needs to mirror the pwsh logic that resolves the - # Microsoft.WindowsAppSDK.Foundation version from the .ML nuspec dependency list. - echo "ERROR: includeWinml=true is not supported on the bash prefetch branch (WinML is Windows-only)." >&2 - exit 1 - fi if [ "${{ parameters.includeOrtGpuLinux }}" = "True" ]; then entries+=("ort_gpu_linux:Microsoft.ML.OnnxRuntime.Gpu.Linux:${{ parameters.ortVersion }}") fi diff --git a/.pipelines/v2/templates/steps-test-cs.yml b/.pipelines/v2/templates/steps-test-cs.yml index 00b1902cd..76b42a0fd 100644 --- a/.pipelines/v2/templates/steps-test-cs.yml +++ b/.pipelines/v2/templates/steps-test-cs.yml @@ -8,9 +8,6 @@ parameters: - name: flNugetDir type: string displayName: 'Path to directory containing the Foundry Local Runtime .nupkg' -- name: isWinML - type: boolean - default: false - name: testDataSharedDir type: string displayName: 'Absolute path to a checked-out test-data-shared working tree' @@ -76,23 +73,15 @@ steps: - task: NuGetAuthenticate@1 displayName: 'Authenticate NuGet feeds' -- ${{ if eq(parameters.isWinML, true) }}: +- ${{ if false }}: + # Placeholder: WinML Runtime install block removed — WinML is now detected + # at runtime from the system Windows App SDK installation. - task: PowerShell@2 - displayName: 'Install Windows App SDK Runtime' - inputs: - targetType: 'inline' - pwsh: true - script: | - $installerUrl = "https://aka.ms/windowsappsdk/1.8/latest/windowsappruntimeinstall-x64.exe" - $installerPath = "$env:TEMP\windowsappruntimeinstall.exe" - Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath - & $installerPath --quiet --force - if ($LASTEXITCODE -ne 0) { throw "Windows App SDK Runtime install failed" } - errorActionPreference: 'stop' + displayName: '(disabled) Install Windows App SDK Runtime' # Per-job NuGet isolation to prevent "Central Directory corrupt" / file-locking -# errors when multiple C# test jobs (regular + WinML) run concurrently on the -# same reused agent. Keyed by $(System.JobId); cleaned on each run. +# errors when multiple C# test jobs run concurrently on the same reused agent. +# Keyed by $(System.JobId); cleaned on each run. - task: PowerShell@2 displayName: 'Set isolated NuGet packages path' inputs: @@ -127,7 +116,6 @@ steps: dotnet restore $proj ` --configfile "$(customNugetConfig)" ` - /p:UseWinML=${{ parameters.isWinML }} ` /p:FoundryLocalRuntimeVersion=$(packageVersion) ` /p:FoundryLocalNativeBinDir= ` /p:RuntimeIdentifiers=$rid @@ -135,7 +123,6 @@ steps: dotnet build $proj ` --no-restore --configuration Release ` - /p:UseWinML=${{ parameters.isWinML }} ` /p:FoundryLocalRuntimeVersion=$(packageVersion) ` /p:FoundryLocalNativeBinDir= ` /p:RuntimeIdentifiers=$rid @@ -169,8 +156,7 @@ steps: script: | $proj = "$(Build.SourcesDirectory)/sdk_v2/cs/test/FoundryLocal.Tests/Microsoft.AI.Foundry.Local.Tests.csproj" dotnet test $proj ` - --no-build --configuration Release ` - /p:UseWinML=${{ parameters.isWinML }} + --no-build --configuration Release if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } env: TF_BUILD: 'true' diff --git a/.pipelines/v2/templates/steps-test-python.yml b/.pipelines/v2/templates/steps-test-python.yml index 3b95b71fd..2bf2b303a 100644 --- a/.pipelines/v2/templates/steps-test-python.yml +++ b/.pipelines/v2/templates/steps-test-python.yml @@ -12,9 +12,6 @@ parameters: - name: testDataSharedDir type: string displayName: 'Absolute path to a checked-out test-data-shared working tree' -- name: isWinML - type: boolean - default: false - name: pythonArchitecture type: string default: 'x64' @@ -30,20 +27,6 @@ steps: addToPath: true architecture: '${{ parameters.pythonArchitecture }}' -- ${{ if eq(parameters.isWinML, true) }}: - - task: PowerShell@2 - displayName: 'Install Windows App SDK Runtime' - inputs: - targetType: 'inline' - pwsh: true - script: | - $installerUrl = "https://aka.ms/windowsappsdk/1.8/latest/windowsappruntimeinstall-x64.exe" - $installerPath = "$env:TEMP\windowsappruntimeinstall.exe" - Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath - & $installerPath --quiet --force - if ($LASTEXITCODE -ne 0) { throw "Windows App SDK Runtime install failed" } - errorActionPreference: 'stop' - # Job-local venv so installs never pollute the agent's site-packages. - task: PowerShell@2 displayName: 'Create test venv' diff --git a/sdk_v2/build_and_test_all.ps1 b/sdk_v2/build_and_test_all.ps1 index fff54329a..fcacb223f 100644 --- a/sdk_v2/build_and_test_all.ps1 +++ b/sdk_v2/build_and_test_all.ps1 @@ -15,14 +15,6 @@ unless -ContinueOnError is supplied, and prints a per-SDK pass/fail summary at the end. -.PARAMETER UseWinml - Build the WinML variant across all SDKs: - * C++: passes --use_winml to build.py - * C#: passes -p:UseWinML=true to dotnet test - * Python: sets FL_PYTHON_PACKAGE_NAME=foundry-local-sdk-winml before pip install - * JS: rebuilds the native addon against the WinML C++ build - Windows only. - .PARAMETER Skip SDKs to skip. Any of: cpp, cs, python, js. @@ -39,11 +31,7 @@ .EXAMPLE pwsh ./build_and_test_all.ps1 - # Full build + test, no WinML. - -.EXAMPLE - pwsh ./build_and_test_all.ps1 -UseWinml - # Full build + test against the WinML variant. + # Full build + test. .EXAMPLE pwsh ./build_and_test_all.ps1 -Only cpp,js -SkipCppTests @@ -51,7 +39,6 @@ #> [CmdletBinding()] param( - [switch] $UseWinml, [ValidateSet('cpp', 'cs', 'python', 'js')] [string[]] $Skip = @(), [ValidateSet('cpp', 'cs', 'python', 'js')] @@ -71,10 +58,6 @@ $csDir = Join-Path $sdkRoot 'cs' $pythonDir = Join-Path $sdkRoot 'python' $jsDir = Join-Path $sdkRoot 'js' -if ($UseWinml -and -not $IsWindows) { - throw "-UseWinml is Windows-only." -} - # Resolve which SDKs to run. $all = @('cpp', 'cs', 'python', 'js') if ($Only) { @@ -100,7 +83,7 @@ function Invoke-Step { ) Write-Host "" Write-Host "============================================================" -ForegroundColor Cyan - Write-Host "==> [$Name] start (UseWinml=$UseWinml)" -ForegroundColor Cyan + Write-Host "==> [$Name] start" -ForegroundColor Cyan Write-Host "============================================================" -ForegroundColor Cyan $start = Get-Date $ok = $false @@ -133,7 +116,6 @@ try { if ('cpp' -in $targets) { Invoke-Step 'cpp' { $args = @('build.py', '--config', $Config) - if ($UseWinml) { $args += '--use_winml' } if ($SkipCppTests) { $args += '--skip_tests' } Push-Location $cppDir try { @@ -156,7 +138,6 @@ try { '-c', $dotnetConfig, '--nologo' ) - if ($UseWinml) { $dotnetArgs += '-p:UseWinML=true' } dotnet @dotnetArgs if ($LASTEXITCODE -ne 0) { throw "dotnet test exit $LASTEXITCODE" } } finally { @@ -197,8 +178,7 @@ print(sys.executable) $env:Platform = 'x64' } - $env:FL_PYTHON_PACKAGE_NAME = - if ($UseWinml) { 'foundry-local-sdk-winml' } else { 'foundry-local-sdk' } + $env:FL_PYTHON_PACKAGE_NAME = 'foundry-local-sdk' try { python -m pip install -e '.[dev]' if ($LASTEXITCODE -ne 0) { throw "pip install exit $LASTEXITCODE" } diff --git a/sdk_v2/cpp/CMakeLists.txt b/sdk_v2/cpp/CMakeLists.txt index c203deec6..3b2c7ef86 100644 --- a/sdk_v2/cpp/CMakeLists.txt +++ b/sdk_v2/cpp/CMakeLists.txt @@ -44,7 +44,6 @@ option(FOUNDRY_LOCAL_BUILD_TESTS "Build unit tests" ON) option(FOUNDRY_LOCAL_BUILD_EXAMPLES "Build example programs" ON) option(FOUNDRY_LOCAL_BUILD_TOOLS "Build internal build-time tools (catalog_snapshot, ...)" ON) option(FOUNDRY_LOCAL_BUILD_SERVICE "Build web service support (requires oat++)" ON) -option(FOUNDRY_LOCAL_USE_WINML "Use WinML/WindowsAppSDK.ML for OnnxRuntime instead of standalone ORT" OFF) option(FOUNDRY_LOCAL_ENABLE_ASAN "Enable AddressSanitizer + UndefinedBehaviorSanitizer (Linux only)" OFF) # Android: interactive examples and host tools don't run on device @@ -78,7 +77,7 @@ if(FOUNDRY_LOCAL_BUILD_TESTS) enable_testing() endif() -# ORT and ORT GenAI — acquired via FetchContent from nuget.org (or WinML SDK when FOUNDRY_LOCAL_USE_WINML=ON) +# ORT and ORT GenAI — acquired via FetchContent from nuget.org list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") find_package(OnnxRuntimeGenAI REQUIRED) find_package(OnnxRuntime REQUIRED) @@ -262,12 +261,6 @@ function(foundry_local_configure_target TARGET LINK_SCOPE) target_compile_definitions(${TARGET} ${LINK_SCOPE} FOUNDRY_LOCAL_HAS_WEB_SERVICE=1) endif() - if(FOUNDRY_LOCAL_USE_WINML) - target_compile_definitions(${TARGET} PUBLIC FOUNDRY_LOCAL_USE_WINML=1) - else() - target_compile_definitions(${TARGET} PUBLIC FOUNDRY_LOCAL_USE_WINML=0) - endif() - if(WinMLEpCatalog_FOUND) target_link_libraries(${TARGET} ${LINK_SCOPE} WinMLEpCatalog::WinMLEpCatalog) target_compile_definitions(${TARGET} ${LINK_SCOPE} FOUNDRY_LOCAL_HAS_EP_CATALOG=1) @@ -275,16 +268,6 @@ function(foundry_local_configure_target TARGET LINK_SCOPE) target_compile_definitions(${TARGET} ${LINK_SCOPE} FOUNDRY_LOCAL_HAS_EP_CATALOG=0) endif() - # WinAppSDK Bootstrap (MddBootstrapInitialize2). Only linked in WinML builds, since - # WinML by definition depends on the WindowsAppSDK runtime; non-WinML builds skip it - # and the bootstrap call site in Manager::Create is compiled out via the same macro. - if(FOUNDRY_LOCAL_USE_WINML) - if(NOT TARGET WinAppSdkBootstrap::WinAppSdkBootstrap) - message(FATAL_ERROR "FOUNDRY_LOCAL_USE_WINML=ON but the WinAppSDK Bootstrap import " - "library was not found. See FindWinMLEpCatalog.cmake.") - endif() - target_link_libraries(${TARGET} ${LINK_SCOPE} WinAppSdkBootstrap::WinAppSdkBootstrap) - endif() endfunction() # -------------------------------------------------------------------------- @@ -419,16 +402,6 @@ if(TARGET OnnxRuntime::OnnxRuntime) $ ) endif() - - # Co-locate the WinAppSDK bootstrap DLL with foundry_local.dll. Required at runtime - # because it's an import-library dependency of the WinML build, not a delay-loaded one. - if(FOUNDRY_LOCAL_USE_WINML AND WINAPPSDK_BOOTSTRAP_DLL AND EXISTS "${WINAPPSDK_BOOTSTRAP_DLL}") - add_custom_command(TARGET foundry_local POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${WINAPPSDK_BOOTSTRAP_DLL}" - $ - ) - endif() elseif(APPLE) # macOS: copy dylibs so consumers that only link libfoundry_local.dylib (e.g. cache_only_tests) find the correct # ORT version instead of any system-installed ORT, which would cause an Ort::InitApi() version mismatch. diff --git a/sdk_v2/cpp/build.py b/sdk_v2/cpp/build.py index f4e2a6a39..7a23ba840 100644 --- a/sdk_v2/cpp/build.py +++ b/sdk_v2/cpp/build.py @@ -160,18 +160,6 @@ class HelpFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescript parser.add_argument( "--skip_service", action="store_true", help="Skip building web service support (oat++)." ) - parser.add_argument( - "--use_winml", action="store_true", - help="Enable the WinML EP catalog (Microsoft.WindowsAppSDK.ML) for hardware EP " - "discovery. ORT itself still comes from Microsoft.ML.OnnxRuntime.Foundry; " - "this flag only adds the WinML EP catalog client.", - ) - parser.add_argument( - "--winml_sdk_version", default=None, type=str, - help="Version of Microsoft.WindowsAppSDK.ML NuGet package (used for the WinML EP " - "catalog when --use_winml is set; defaults to the version pinned in " - "FindWinMLEpCatalog.cmake).", - ) # Cross-compilation (mutually exclusive targets) cross_group = parser.add_mutually_exclusive_group() @@ -462,14 +450,6 @@ def configure(args: argparse.Namespace) -> None: if build_tests == "ON": command += ["-DVCPKG_MANIFEST_FEATURES=tests"] - if args.use_winml: - command += ["-DFOUNDRY_LOCAL_USE_WINML=ON"] - if args.winml_sdk_version: - command += [f"-DWINML_SDK_VERSION={args.winml_sdk_version}"] - else: - # Pass explicitly so a re-configure without the flag clears any cached ON value. - command += ["-DFOUNDRY_LOCAL_USE_WINML=OFF"] - if args.ort_home: command += [f"-DORT_HOME={args.ort_home}"] diff --git a/sdk_v2/cpp/cmake/FindOnnxRuntime.cmake b/sdk_v2/cpp/cmake/FindOnnxRuntime.cmake index 2ec92011f..ee9fedd1e 100644 --- a/sdk_v2/cpp/cmake/FindOnnxRuntime.cmake +++ b/sdk_v2/cpp/cmake/FindOnnxRuntime.cmake @@ -1,12 +1,9 @@ # Copyright (c) Microsoft. All rights reserved. # Find/acquire ONNX Runtime. # -# ORT is always sourced from Microsoft.ML.OnnxRuntime.Foundry (or +# ORT is sourced from Microsoft.ML.OnnxRuntime.Foundry (or # Microsoft.ML.OnnxRuntime on Android) via FetchContent — nuget.org for releases, -# the ORT-Nightly ADO feed for -dev- versions. The FOUNDRY_LOCAL_USE_WINML flag -# does NOT change the ORT package source; it only: -# - selects a WinML-compatible ORT version (see version branch below), and -# - opts in to the WinML EP catalog (handled by FindWinMLEpCatalog.cmake). +# the ORT-Nightly ADO feed for -dev- versions. # # Creates an IMPORTED target: OnnxRuntime::OnnxRuntime @@ -42,25 +39,6 @@ else() message(FATAL_ERROR "Unsupported platform for OnnxRuntime: ${CMAKE_GENERATOR_PLATFORM} on ${CMAKE_SYSTEM_NAME}") endif() -if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - # WinML is only available on Windows - set(FOUNDRY_LOCAL_USE_WINML OFF) -endif() - -if(FOUNDRY_LOCAL_USE_WINML) - # FOUNDRY_LOCAL_USE_WINML opts in to the WinML EP catalog (see FindWinMLEpCatalog.cmake) but - # does NOT change where ORT comes from. We always link against our own ORT - # (Microsoft.ML.OnnxRuntime.Foundry) because it enables CUDA and WebGPU EPs. - # - # Which onnxruntime.dll the process actually binds to at runtime is determined by the - # binding-side preload contract (see sdk_v2/cpp/docs/OrtRuntimeLoading.md), not by build - # layout. Co-location of our onnxruntime.dll next to foundry_local.dll keeps in-tree - # tests and examples zero-config, but is not a correctness guarantee for arbitrary - # deployments — bindings preload the intended onnxruntime.dll by absolute path before - # loading foundry_local. - message(STATUS "FOUNDRY_LOCAL_USE_WINML=ON: WinML EP catalog enabled; ORT still sourced from Microsoft.ML.OnnxRuntime.Foundry") -endif() - if(ORT_HOME) # Use a pre-extracted ORT directory (e.g. from build.py --ort_home). # Android: expects headers/ and jni// from an extracted AAR. @@ -80,14 +58,10 @@ else() # Standard path: FetchContent from nuget.org (releases) or ORT-Nightly ADO feed (dev builds) # ----------------------------------------------------------------------- if(NOT ORT_VERSION) - # Single source of truth: sdk_v2/deps_versions[_winml].json. The Python - # SDK build backend reads the same files so wheel deps and native ABI + # Single source of truth: sdk_v2/deps_versions.json. The Python + # SDK build backend reads the same file so wheel deps and native ABI # always agree. Override at the cmake command line with -DORT_VERSION=... - if(FOUNDRY_LOCAL_USE_WINML) - set(_DEPS_FILE "${CMAKE_CURRENT_LIST_DIR}/../../deps_versions_winml.json") - else() - set(_DEPS_FILE "${CMAKE_CURRENT_LIST_DIR}/../../deps_versions.json") - endif() + set(_DEPS_FILE "${CMAKE_CURRENT_LIST_DIR}/../../deps_versions.json") if(NOT EXISTS "${_DEPS_FILE}") message(FATAL_ERROR "Required versions file not found: ${_DEPS_FILE}") endif() diff --git a/sdk_v2/cpp/cmake/FindOnnxRuntimeGenAI.cmake b/sdk_v2/cpp/cmake/FindOnnxRuntimeGenAI.cmake index 4906c254b..de2196a1b 100644 --- a/sdk_v2/cpp/cmake/FindOnnxRuntimeGenAI.cmake +++ b/sdk_v2/cpp/cmake/FindOnnxRuntimeGenAI.cmake @@ -1,10 +1,7 @@ # Copyright (c) Microsoft. All rights reserved. # Find/acquire ONNX Runtime GenAI. # -# Windows + FOUNDRY_LOCAL_USE_WINML=ON: Microsoft.ML.OnnxRuntimeGenAI.WinML -# Windows + FOUNDRY_LOCAL_USE_WINML=OFF: Microsoft.ML.OnnxRuntimeGenAI.Foundry -# Linux: Microsoft.ML.OnnxRuntimeGenAI.Foundry -# macOS: Microsoft.ML.OnnxRuntimeGenAI.Foundry +# All platforms: Microsoft.ML.OnnxRuntimeGenAI.Foundry # # When ORT_GENAI_HOME is set, uses the local ORT GenAI build instead of NuGet. # Otherwise uses FetchContent from nuget.org. @@ -104,21 +101,13 @@ else() message(FATAL_ERROR "Unsupported platform for OnnxRuntimeGenAI: ${CMAKE_GENERATOR_PLATFORM} on ${CMAKE_SYSTEM_NAME}") endif() -if(FOUNDRY_LOCAL_USE_WINML) - set(_GENAI_PACKAGE_NAME "Microsoft.ML.OnnxRuntimeGenAI.WinML") -else() - set(_GENAI_PACKAGE_NAME "Microsoft.ML.OnnxRuntimeGenAI.Foundry") -endif() +set(_GENAI_PACKAGE_NAME "Microsoft.ML.OnnxRuntimeGenAI.Foundry") if(NOT ORT_GENAI_VERSION) - # Single source of truth: sdk_v2/deps_versions[_winml].json. The Python - # SDK build backend reads the same files. Override at the cmake command + # Single source of truth: sdk_v2/deps_versions.json. The Python + # SDK build backend reads the same file. Override at the cmake command # line with -DORT_GENAI_VERSION=... - if(FOUNDRY_LOCAL_USE_WINML) - set(_GENAI_DEPS_FILE "${CMAKE_CURRENT_LIST_DIR}/../../deps_versions_winml.json") - else() - set(_GENAI_DEPS_FILE "${CMAKE_CURRENT_LIST_DIR}/../../deps_versions.json") - endif() + set(_GENAI_DEPS_FILE "${CMAKE_CURRENT_LIST_DIR}/../../deps_versions.json") if(NOT EXISTS "${_GENAI_DEPS_FILE}") message(FATAL_ERROR "Required versions file not found: ${_GENAI_DEPS_FILE}") endif() diff --git a/sdk_v2/cpp/src/ep_detection/cuda_ep_bootstrapper.cc b/sdk_v2/cpp/src/ep_detection/cuda_ep_bootstrapper.cc index 55ac8cd2a..a89145d34 100644 --- a/sdk_v2/cpp/src/ep_detection/cuda_ep_bootstrapper.cc +++ b/sdk_v2/cpp/src/ep_detection/cuda_ep_bootstrapper.cc @@ -28,35 +28,20 @@ constexpr const char* kLockFileName = "cuda-ep.lock"; constexpr const char* kUserAgent = "FoundryLocal"; constexpr int kMaxInstallAttempts = 5; -// CUDA EP package is built against the ONNX Runtime version we link against, so -// WinML and non-WinML builds need separate downloads. Hashes mirror the C# core -// (see neutron.main/src/Service/Providers/Detector/CudaEpBootstrapper.cs). -// WinML build -> ORT 1.23.2 (cuda-ep-20260501-182408.zip) -// Non-WinML -> ORT 1.25.1 (cuda-ep-20260501-062935.zip) -#if defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML -constexpr const char* kDownloadUrl = - "https://foundrypackages-ffhrdhbxb7gpdreh.b02.azurefd.net/cuda-ep-20260501-182408.zip"; -#else +// CUDA EP package is built against the ONNX Runtime version we link against. +// Hashes mirror the C# core (see neutron.main/src/Service/Providers/Detector/CudaEpBootstrapper.cs). constexpr const char* kDownloadUrl = "https://foundrypackages-ffhrdhbxb7gpdreh.b02.azurefd.net/cuda-ep-20260501-062935.zip"; -#endif struct ExpectedBinary { const char* filename; const char* sha256; }; -#if defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML -constexpr ExpectedBinary kExpectedBinaries[] = { - {"onnxruntime_providers_cuda.dll", "4CEF18654878CEFCFCF8488E9C3A705EB5327AA9B5556155C319C9CBB2D98FCF"}, - {"onnxruntime-genai-cuda.dll", "BC953F8E2AAFC6219B2D723B65AB8F1A9426A6B7724D6A01ED756FAE8C3DE6AE"}, -}; -#else constexpr ExpectedBinary kExpectedBinaries[] = { {"onnxruntime_providers_cuda.dll", "DD540FCFECFBC68B4675C9ADF09C2858CF6B054563859D79598AA2524406A76F"}, {"onnxruntime-genai-cuda.dll", "BC953F8E2AAFC6219B2D723B65AB8F1A9426A6B7724D6A01ED756FAE8C3DE6AE"}, }; -#endif constexpr const char* kRegistrationName = "Foundry.CUDA"; constexpr const char* kCudaProviderDll = "onnxruntime_providers_cuda.dll"; diff --git a/sdk_v2/cpp/src/manager.cc b/sdk_v2/cpp/src/manager.cc index f7c1e4bb1..c75c26f31 100644 --- a/sdk_v2/cpp/src/manager.cc +++ b/sdk_v2/cpp/src/manager.cc @@ -254,12 +254,8 @@ Manager::Manager(const Configuration& config) } // WebGPU EP — always available (no hardware detection needed). - // Skipped in WinML builds because the WinML-aligned ORT (1.23.2) is older - // than the ORT API version required by the WebGPU EP plugin (>= 24). -#if !(defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML) auto webgpu_ep_dir = *config_.model_cache_dir + "/webgpu-ep"; bootstrappers.push_back(std::make_unique(std::move(webgpu_ep_dir), register_ep)); -#endif } ep_detector_ = std::make_unique(*ort_api_, *ort_env_, std::move(bootstrappers), *logger_); @@ -355,15 +351,11 @@ Manager& Manager::Create(const Configuration& config) { "Manager already created. Call Destroy() first."); } +#ifdef _WIN32 // Optional Windows App SDK bootstrap. When the caller passes Bootstrap=true in - // additional_options we initialize the WinAppSDK framework package for this process. This - // must run before the Manager constructor so that WinML EP discovery (inside - // Manager::Manager) can resolve Microsoft.Windows.AI.MachineLearning.dll. We use a - // temporary stderr logger here because the Manager-owned logger doesn't exist yet; - // bootstrap output is low-volume (one line on success, one warning on failure). Mirrors - // the C# FoundryLocalCore IS_WINML path. Only meaningful in WinML builds; outside that - // configuration TryInitializeWindowsAppSdk is a no-op stub. -#if defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML + // additional_options, initialize the WinAppSDK framework package so that + // WinML EP discovery can resolve Microsoft.Windows.AI.MachineLearning.dll. + // The bootstrap DLL is loaded dynamically — graceful no-op when WinAppSDK is absent. { auto it = config.additional_options.find("Bootstrap"); constexpr std::string_view kTrue = "true"; @@ -418,7 +410,7 @@ void Manager::Destroy() { // Pair WinAppSDK bootstrap shutdown with Manager teardown. No-op if the bootstrap was // never initialized for this process. Use a temporary logger for the same reason as in // Create — the Manager-owned logger has been destroyed by this point. -#if defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML +#ifdef _WIN32 StderrLogger bootstrap_logger; ShutdownWindowsAppSdk(bootstrap_logger); #endif diff --git a/sdk_v2/cpp/src/winml_bootstrap.cc b/sdk_v2/cpp/src/winml_bootstrap.cc index 5999a6d54..27aae1933 100644 --- a/sdk_v2/cpp/src/winml_bootstrap.cc +++ b/sdk_v2/cpp/src/winml_bootstrap.cc @@ -2,16 +2,13 @@ // Licensed under the MIT License. #include "winml_bootstrap.h" -// Entire translation unit is empty outside WinML builds — see winml_bootstrap.h. Callers -// guard their use sites with the same FOUNDRY_LOCAL_USE_WINML macro, so there are no -// undefined references to no-op stubs. -#if defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML +// Entire translation unit is empty outside Windows builds. +#ifdef _WIN32 #include "logger.h" #define WIN32_LEAN_AND_MEAN #include -#include #include #include @@ -19,13 +16,32 @@ namespace { -// Windows App SDK 1.8 — matches the C# FoundryLocalCore reference (majorMinorVersion= -// 0x00010008, minVersion={1,8,1,0}). Update in lockstep with the WinML EP catalog NuGet. +// MddBootstrap types replicated from MddBootstrap.h to avoid a hard link dep on +// Microsoft.WindowsAppRuntime.Bootstrap.lib. Loaded dynamically at runtime so +// foundry_local.dll is usable on systems without the Windows App SDK installed. +struct MddPackageVersion { + union { + UINT64 Version; + struct { + UINT16 Revision; + UINT16 Build; + UINT16 Minor; + UINT16 Major; + }; + }; +}; + +// MddBootstrapInitializeOptions flags (subset from MddBootstrap.h) +enum MddBootstrapInitializeOptions : UINT32 { + MddBootstrapInitializeOptions_None = 0, +}; + +using MddBootstrapInitialize2Fn = HRESULT(WINAPI*)(UINT32, PCWSTR, MddPackageVersion, + MddBootstrapInitializeOptions); +using MddBootstrapShutdownFn = void(WINAPI*)(); + +// Windows App SDK 1.8 — matches the C# FoundryLocalCore reference. constexpr UINT32 kMajorMinorVersion = 0x00010008; -constexpr UINT16 kMinMajor = 1; -constexpr UINT16 kMinMinor = 8; -constexpr UINT16 kMinBuild = 1; -constexpr UINT16 kMinRevision = 0; std::atomic g_initialized{false}; @@ -38,27 +54,44 @@ bool TryInitializeWindowsAppSdk(ILogger& logger) { return true; } - PACKAGE_VERSION min_version{}; - min_version.Major = kMinMajor; - min_version.Minor = kMinMinor; - min_version.Build = kMinBuild; - min_version.Revision = kMinRevision; + HMODULE bootstrap_dll = LoadLibraryW(L"Microsoft.WindowsAppRuntime.Bootstrap.dll"); + if (!bootstrap_dll) { + logger.Log(LogLevel::Information, + "WindowsAppSdk bootstrap: Microsoft.WindowsAppRuntime.Bootstrap.dll not found — " + "WinML EP bootstrap skipped."); + return false; + } + + auto* init_fn = reinterpret_cast( + GetProcAddress(bootstrap_dll, "MddBootstrapInitialize2")); + if (!init_fn) { + logger.Log(LogLevel::Warning, + "WindowsAppSdk bootstrap: MddBootstrapInitialize2 not found in Bootstrap DLL."); + FreeLibrary(bootstrap_dll); + return false; + } + + MddPackageVersion min_version{}; + min_version.Major = 1; + min_version.Minor = 8; + min_version.Build = 1; + min_version.Revision = 0; - HRESULT hr = ::MddBootstrapInitialize2( - kMajorMinorVersion, nullptr, min_version, - MddBootstrapInitializeOptions_OnNoMatch_ShowUI); + HRESULT hr = init_fn(kMajorMinorVersion, nullptr, min_version, MddBootstrapInitializeOptions_None); if (FAILED(hr)) { char buf[16]; std::snprintf(buf, sizeof(buf), "%08lX", static_cast(hr)); - logger.Log(LogLevel::Warning, + logger.Log(LogLevel::Information, std::string("WindowsAppSdk bootstrap: MddBootstrapInitialize2 failed (HRESULT=0x") + - buf + "). WinML EP discovery may find no providers."); + buf + "). WinML EPs will not be available."); + // Don't FreeLibrary — leak is intentional to keep the module handle stable + // if a subsequent call succeeds after a transient failure. return false; } + // Keep the DLL loaded — MddBootstrapShutdown needs it. g_initialized.store(true, std::memory_order_release); - logger.Log(LogLevel::Information, - "WindowsAppSdk bootstrap: initialized successfully (WinAppSDK >= 1.8.1.0)."); + logger.Log(LogLevel::Information, "WindowsAppSdk bootstrap: initialized successfully (WinAppSDK >= 1.8.1.0)."); return true; } @@ -67,10 +100,18 @@ void ShutdownWindowsAppSdk(ILogger& logger) { return; } - ::MddBootstrapShutdown(); + HMODULE bootstrap_dll = GetModuleHandleW(L"Microsoft.WindowsAppRuntime.Bootstrap.dll"); + if (bootstrap_dll) { + auto* shutdown_fn = reinterpret_cast( + GetProcAddress(bootstrap_dll, "MddBootstrapShutdown")); + if (shutdown_fn) { + shutdown_fn(); + } + } + logger.Log(LogLevel::Information, "WindowsAppSdk bootstrap: shutdown complete."); } } // namespace fl -#endif // FOUNDRY_LOCAL_USE_WINML +#endif // _WIN32 diff --git a/sdk_v2/cpp/src/winml_bootstrap.h b/sdk_v2/cpp/src/winml_bootstrap.h index 4a068c83a..4247aed83 100644 --- a/sdk_v2/cpp/src/winml_bootstrap.h +++ b/sdk_v2/cpp/src/winml_bootstrap.h @@ -1,19 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // -// Optional Windows App SDK bootstrap helper for non-packaged consumer processes (e.g. the +// Windows App SDK bootstrap helper for non-packaged consumer processes (e.g. the // JavaScript binding loaded into Node, where the host process has no built-in WinAppSDK // activation). When opted in via additional_options["Bootstrap"]="true", initializes the // Windows App Runtime framework package so that APIs depending on it — notably the WinML EP // catalog DLL `Microsoft.Windows.AI.MachineLearning.dll` consumed by `WinMLEpBootstrapper` — -// can resolve at runtime. Defaults to off; matches the C# FoundryLocalCore behavior. +// can resolve at runtime. Defaults to off; the C# and JS bindings set it automatically. // -// Compiled only in WinML builds (FOUNDRY_LOCAL_USE_WINML=ON), which already take a hard -// dependency on the WindowsAppSDK NuGet. Outside that configuration the header is empty and -// callers must guard their use sites with the same FOUNDRY_LOCAL_USE_WINML macro. +// The bootstrap DLL (Microsoft.WindowsAppRuntime.Bootstrap.dll) is loaded dynamically, so +// foundry_local.dll is usable on machines without the Windows App SDK installed — failure is +// silent and WinML EP discovery simply finds no providers. #pragma once -#if defined(FOUNDRY_LOCAL_USE_WINML) && FOUNDRY_LOCAL_USE_WINML +#ifdef _WIN32 namespace fl { @@ -24,8 +24,7 @@ class ILogger; /// no-ops once initialized. /// /// Returns true if bootstrap succeeded (or was already initialized). Returns false on -/// failure; the reason is logged but the process continues — WinML EP discovery will simply -/// find no providers. +/// failure (e.g. WinAppSDK not installed); the reason is logged at Information level. bool TryInitializeWindowsAppSdk(ILogger& logger); /// Reverse the effects of TryInitializeWindowsAppSdk(). Safe to call even if init never @@ -34,4 +33,4 @@ void ShutdownWindowsAppSdk(ILogger& logger); } // namespace fl -#endif // FOUNDRY_LOCAL_USE_WINML +#endif // _WIN32 diff --git a/sdk_v2/cs/src/FoundryLocalManager.cs b/sdk_v2/cs/src/FoundryLocalManager.cs index 4453c44f1..1d3123771 100644 --- a/sdk_v2/cs/src/FoundryLocalManager.cs +++ b/sdk_v2/cs/src/FoundryLocalManager.cs @@ -255,9 +255,11 @@ await Task.Run(() => } } -#if IS_WINML - // WinML build needs the native side to bootstrap the Windows App Runtime. + // On Windows, attempt to bootstrap the Windows App Runtime so WinML EPs can be + // discovered if the Windows App SDK is installed. The native side handles failure + // gracefully — if the SDK is absent, EP discovery falls back to CPU/CUDA/WebGPU. // Caller can override by setting "Bootstrap" explicitly in AdditionalSettings. +#if IS_WINDOWS if (!additionalSettings.ContainsKey("Bootstrap")) { additionalSettings["Bootstrap"] = "true"; diff --git a/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj b/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj index 8114eadaf..7e2a6f995 100644 --- a/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj +++ b/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj @@ -15,8 +15,6 @@ net8.0;net9.0;netstandard2.0 win-x64;win-arm64;linux-x64;linux-arm64;osx-arm64 - - true False enable latest @@ -29,13 +27,6 @@ true snupkg true - - - false - win-x64;win-arm64 @@ -82,24 +72,6 @@ - - - Microsoft AI Foundry Local for WinML - Microsoft Foundry Local SDK for WinML - Microsoft.AI.Foundry.Local.WinML - Microsoft.AI.Foundry.Local.WinML - $(DefineConstants);IS_WINML - net9.0-windows10.0.26100.0 - win-x64;win-arm64 - - 10.0.17763.0 - - - $(NoWarn);CsWinRT1028 - - - - True @@ -130,12 +102,9 @@ Option 2 (local build): set FoundryLocalNativeBinDir to point at a C++ build output, e.g.: dotnet build /p:FoundryLocalNativeBinDir=..\..\cpp\build\Windows\RelWithDebInfo\bin\RelWithDebInfo Option 3 (default): auto-detect the C++ build output from the repo-relative location. --> - + - - - diff --git a/sdk_v2/cs/test/FoundryLocal.Tests/Microsoft.AI.Foundry.Local.Tests.csproj b/sdk_v2/cs/test/FoundryLocal.Tests/Microsoft.AI.Foundry.Local.Tests.csproj index 1196a1b6c..9a855661b 100644 --- a/sdk_v2/cs/test/FoundryLocal.Tests/Microsoft.AI.Foundry.Local.Tests.csproj +++ b/sdk_v2/cs/test/FoundryLocal.Tests/Microsoft.AI.Foundry.Local.Tests.csproj @@ -13,7 +13,6 @@ latest false true - false false @@ -47,17 +46,6 @@ - - net9.0-windows10.0.26100.0 - 10.0.17763.0 - None - - $(DefineConstants);USE_WINML - - diff --git a/sdk_v2/cs/test/FoundryLocal.Tests/VisionTests.cs b/sdk_v2/cs/test/FoundryLocal.Tests/VisionTests.cs index 03399b88f..07be22307 100644 --- a/sdk_v2/cs/test/FoundryLocal.Tests/VisionTests.cs +++ b/sdk_v2/cs/test/FoundryLocal.Tests/VisionTests.cs @@ -17,23 +17,13 @@ namespace Microsoft.AI.Foundry.Local.Tests; [SkipUnlessIntegration] internal sealed class VisionTests { -#pragma warning disable CS0649 // assigned in non-WinML Setup; under USE_WINML the field is never written private static IModel? model; -#pragma warning restore CS0649 private static string TestImagePath => Utils.TestDataPath("Taittinger.jpg"); [Before(Class)] public static async Task Setup() { -#if USE_WINML - // The WinML variant pins an older ORT than the base SDK. Cataloged vision - // models use ops (e.g. com.microsoft:CausalConvWithState) that aren't - // registered in that ORT, so no vision model can load. Skip the whole suite. - Console.WriteLine("VisionTests: skipped on WinML build (ORT version lacks required ops)"); - await Task.CompletedTask; - return; -#else try { var manager = FoundryLocalManager.Instance; @@ -86,7 +76,6 @@ public static async Task Setup() Console.WriteLine($"VisionTests setup failed: {ex}"); throw; } -#endif } [Test] diff --git a/sdk_v2/deps_versions_winml.json b/sdk_v2/deps_versions_winml.json deleted file mode 100644 index c2f43bfb5..000000000 --- a/sdk_v2/deps_versions_winml.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "_comment": "WinML variant of sdk_v2/deps_versions.json. Selected by FOUNDRY_LOCAL_USE_WINML=ON (cmake) and FL_PYTHON_PACKAGE_NAME=foundry-local-sdk-winml (python build backend).", - "onnxruntime": { "version": "1.23.2.3" }, - "onnxruntime-genai": { "version": "0.13.2" } -} diff --git a/sdk_v2/python/_build_backend/__init__.py b/sdk_v2/python/_build_backend/__init__.py index d3bb42dd3..e8e4a123b 100644 --- a/sdk_v2/python/_build_backend/__init__.py +++ b/sdk_v2/python/_build_backend/__init__.py @@ -50,11 +50,9 @@ _ENV_VAR = "FL_PYTHON_PACKAGE_NAME" -_WINML_PKG_NAME = "foundry-local-sdk-winml" _PYPROJECT = Path(__file__).resolve().parent.parent / "pyproject.toml" _SDK_V2_ROOT = _PYPROJECT.resolve().parent.parent _DEPS_JSON_STD = _SDK_V2_ROOT / "deps_versions.json" -_DEPS_JSON_WINML = _SDK_V2_ROOT / "deps_versions_winml.json" # Match ``name = "..."`` only inside the [project] table. The regex is # anchored to the first ``name = "foundry-local-sdk"`` occurrence which @@ -108,13 +106,12 @@ def _patch_pyproject_text(original: str, *, override_name: str | None, deps_file def _maybe_patch_name() -> Generator[None, None, None]: """Context manager that rewrites pyproject.toml during PEP 517 hook execution. - Always rewrites ORT/GenAI version pins from the appropriate deps JSON + Always rewrites ORT/GenAI version pins from deps_versions.json (single source of truth). Conditionally rewrites the project name when - ``FL_PYTHON_PACKAGE_NAME`` selects the WinML variant. + ``FL_PYTHON_PACKAGE_NAME`` overrides the default. """ override = os.environ.get(_ENV_VAR, "").strip() or None - is_winml = override == _WINML_PKG_NAME - deps_file = _DEPS_JSON_WINML if is_winml else _DEPS_JSON_STD + deps_file = _DEPS_JSON_STD original = _PYPROJECT.read_text(encoding="utf-8") patched = _patch_pyproject_text(original, override_name=override, deps_file=deps_file) diff --git a/sdk_v2/python/pyproject.toml b/sdk_v2/python/pyproject.toml index cb8cf3d3e..b31bd7b7b 100644 --- a/sdk_v2/python/pyproject.toml +++ b/sdk_v2/python/pyproject.toml @@ -38,10 +38,9 @@ classifiers = [ ] # ORT/GenAI version pins below use sentinel ``0.0.0``. The real versions -# come from sdk_v2/deps_versions.json (or deps_versions_winml.json for the -# WinML variant) — the _build_backend rewrites these pins from JSON at -# wheel-build time. JSON is the single source of truth; bumping ORT -# versions is a one-file edit. +# come from sdk_v2/deps_versions.json — the _build_backend rewrites these +# pins from JSON at wheel-build time. JSON is the single source of truth; +# bumping ORT versions is a one-file edit. # # If a wheel ever ships with ``==0.0.0`` it means the backend wasn't # invoked (e.g. raw setuptools bypass) — pip install will fail loudly