diff --git a/.pipelines/v2/templates/stages-js.yml b/.pipelines/v2/templates/stages-js.yml index 5fa3d1b2..7837e5cc 100644 --- a/.pipelines/v2/templates/stages-js.yml +++ b/.pipelines/v2/templates/stages-js.yml @@ -1,313 +1,475 @@ -# Build + test + pack stages for the sdk_v2 JS SDK. +# Build + test + pack stages for the sdk_v2 JS SDK, parameterized by variant. # -# Unlike Python and C#, the JS SDK ships a single multi-platform npm tarball. -# Each per-platform build stage produces a `js-prebuild-` artifact -# containing prebuilds/-/ (two .node addons + the matching -# foundry_local shared library). The final `js_pack` stage downloads all -# four prebuild artifacts, merges them under sdk_v2/js/prebuilds/, stamps -# the version, and runs `npm pack` to produce a single .tgz. +# 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) +# +# Unlike Python and C#, the JS SDK ships a single multi-platform npm tarball +# per variant. Each per-platform build stage produces a `js-prebuild-` +# (base) or `js-prebuild-winml-` (winml) artifact containing +# prebuilds/-/ (two .node addons + the matching foundry_local +# shared library, and for the WinML variant the additional +# Microsoft.Windows.AI.MachineLearning.dll). The final pack stage downloads +# all prebuild artifacts for the variant, merges them under +# sdk_v2/js/prebuilds/, stamps the version (and for WinML rewrites the +# package name), and runs `npm pack` to produce a single .tgz. # # Build stages depend on: # * compute_version (sdkVersion.txt for the eventual pack stamp) -# * cpp_build_ (matching native foundry_local lib + import lib) +# * cpp_build_[_winml] (matching native foundry_local lib + import lib; +# WinML variant also brings the WinML EP DLL) # * cpp_build_win_x64 (the cpp-native-include artifact, which is -# stage-headers-only on the win-x64 build) +# stage-headers-only on the base win-x64 build) # # Tests run on the same platform as the build, except win-arm64 (no # Windows-ARM64 pool; build-only, matching the C# + Python matrices). +parameters: +- name: variant + type: string + default: 'base' + values: ['base', 'winml'] + stages: # ===================================================================== -# Build stages +# Base variant: build win-x64 + win-arm64 + linux-x64 + osx-arm64 # ===================================================================== +- ${{ if eq(parameters.variant, 'base') }}: -- stage: js_build_win_x64 - displayName: 'JS SDK: Build Windows x64' - dependsOn: - - compute_version - - cpp_build_win_x64 - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - variables: - - group: FoundryLocal-ESRP-Signing - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-win-x64' - targetPath: '$(Pipeline.Workspace)/cpp-native-win-x64' - - input: pipelineArtifact - artifactName: 'cpp-native-include' - targetPath: '$(Pipeline.Workspace)/cpp-native-include' - outputs: - - output: pipelineArtifact - artifactName: 'js-prebuild-win-x64' - targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' - steps: - - checkout: self - clean: true - - template: steps-build-js.yml - parameters: - rid: 'win-x64' - nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-x64' - includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' - outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' - signWindows: true + - stage: js_build_win_x64 + displayName: 'JS SDK: Build Windows x64' + dependsOn: + - compute_version + - cpp_build_win_x64 + jobs: + - job: build + pool: + name: onnxruntime-Win-CPU-2022 + os: windows + variables: + - group: FoundryLocal-ESRP-Signing + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'version-info' + targetPath: '$(Pipeline.Workspace)/version-info' + - input: pipelineArtifact + artifactName: 'cpp-native-win-x64' + targetPath: '$(Pipeline.Workspace)/cpp-native-win-x64' + - input: pipelineArtifact + artifactName: 'cpp-native-include' + targetPath: '$(Pipeline.Workspace)/cpp-native-include' + outputs: + - output: pipelineArtifact + artifactName: 'js-prebuild-win-x64' + targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' + steps: + - checkout: self + clean: true + - template: steps-build-js.yml + parameters: + rid: 'win-x64' + nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-x64' + includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' + outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' + signWindows: true -- stage: js_build_win_arm64 - displayName: 'JS SDK: Build Windows ARM64' - dependsOn: - - compute_version - - cpp_build_win_arm64 - - cpp_build_win_x64 - jobs: - - job: build - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - variables: - - group: FoundryLocal-ESRP-Signing - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-win-arm64' - targetPath: '$(Pipeline.Workspace)/cpp-native-win-arm64' - - input: pipelineArtifact - artifactName: 'cpp-native-include' - targetPath: '$(Pipeline.Workspace)/cpp-native-include' - outputs: - - output: pipelineArtifact - artifactName: 'js-prebuild-win-arm64' - targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' - steps: - - checkout: self - clean: true - - template: steps-build-js.yml - parameters: - rid: 'win-arm64' - nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-arm64' - includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' - outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' - targetArch: 'arm64' - signWindows: true + - stage: js_build_win_arm64 + displayName: 'JS SDK: Build Windows ARM64' + dependsOn: + - compute_version + - cpp_build_win_arm64 + - cpp_build_win_x64 + jobs: + - job: build + pool: + name: onnxruntime-Win-CPU-2022 + os: windows + variables: + - group: FoundryLocal-ESRP-Signing + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'version-info' + targetPath: '$(Pipeline.Workspace)/version-info' + - input: pipelineArtifact + artifactName: 'cpp-native-win-arm64' + targetPath: '$(Pipeline.Workspace)/cpp-native-win-arm64' + - input: pipelineArtifact + artifactName: 'cpp-native-include' + targetPath: '$(Pipeline.Workspace)/cpp-native-include' + outputs: + - output: pipelineArtifact + artifactName: 'js-prebuild-win-arm64' + targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' + steps: + - checkout: self + clean: true + - template: steps-build-js.yml + parameters: + rid: 'win-arm64' + nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-arm64' + includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' + outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' + targetArch: 'arm64' + signWindows: true -- stage: js_build_linux_x64 - displayName: 'JS SDK: Build Linux x64' - dependsOn: - - compute_version - - cpp_build_linux_x64 - - cpp_build_win_x64 - jobs: - - job: build - pool: - name: onnxruntime-Ubuntu2404-AMD-CPU - os: linux - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-linux-x64' - targetPath: '$(Pipeline.Workspace)/cpp-native-linux-x64' - - input: pipelineArtifact - artifactName: 'cpp-native-include' - targetPath: '$(Pipeline.Workspace)/cpp-native-include' - outputs: - - output: pipelineArtifact - artifactName: 'js-prebuild-linux-x64' - targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' - steps: - - checkout: self - clean: true - - template: steps-build-js.yml - parameters: - rid: 'linux-x64' - nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-linux-x64' - includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' - outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' + - stage: js_build_linux_x64 + displayName: 'JS SDK: Build Linux x64' + dependsOn: + - compute_version + - cpp_build_linux_x64 + - cpp_build_win_x64 + jobs: + - job: build + pool: + name: onnxruntime-Ubuntu2404-AMD-CPU + os: linux + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'version-info' + targetPath: '$(Pipeline.Workspace)/version-info' + - input: pipelineArtifact + artifactName: 'cpp-native-linux-x64' + targetPath: '$(Pipeline.Workspace)/cpp-native-linux-x64' + - input: pipelineArtifact + artifactName: 'cpp-native-include' + targetPath: '$(Pipeline.Workspace)/cpp-native-include' + outputs: + - output: pipelineArtifact + artifactName: 'js-prebuild-linux-x64' + targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' + steps: + - checkout: self + clean: true + - template: steps-build-js.yml + parameters: + rid: 'linux-x64' + nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-linux-x64' + includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' + outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' -- stage: js_build_osx_arm64 - displayName: 'JS SDK: Build macOS ARM64' - dependsOn: - - compute_version - - cpp_build_osx_arm64 - - cpp_build_win_x64 - jobs: - - job: build - pool: - name: AcesShared - os: macOS - demands: - - ImageOverride -equals ACES_VM_SharedPool_Sequoia - variables: - - group: FoundryLocal-ESRP-Signing - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'version-info' - targetPath: '$(Pipeline.Workspace)/version-info' - - input: pipelineArtifact - artifactName: 'cpp-native-osx-arm64' - targetPath: '$(Pipeline.Workspace)/cpp-native-osx-arm64' - - input: pipelineArtifact - artifactName: 'cpp-native-include' - targetPath: '$(Pipeline.Workspace)/cpp-native-include' - outputs: - - output: pipelineArtifact - artifactName: 'js-prebuild-osx-arm64' - targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' - steps: - - checkout: self - clean: true - - template: steps-build-js.yml - parameters: - rid: 'osx-arm64' - nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-osx-arm64' - includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' - outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' - signMac: true + - stage: js_build_osx_arm64 + displayName: 'JS SDK: Build macOS ARM64' + dependsOn: + - compute_version + - cpp_build_osx_arm64 + - cpp_build_win_x64 + jobs: + - job: build + pool: + name: AcesShared + os: macOS + demands: + - ImageOverride -equals ACES_VM_SharedPool_Sequoia + variables: + - group: FoundryLocal-ESRP-Signing + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'version-info' + targetPath: '$(Pipeline.Workspace)/version-info' + - input: pipelineArtifact + artifactName: 'cpp-native-osx-arm64' + targetPath: '$(Pipeline.Workspace)/cpp-native-osx-arm64' + - input: pipelineArtifact + artifactName: 'cpp-native-include' + targetPath: '$(Pipeline.Workspace)/cpp-native-include' + outputs: + - output: pipelineArtifact + artifactName: 'js-prebuild-osx-arm64' + targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' + steps: + - checkout: self + clean: true + - template: steps-build-js.yml + parameters: + rid: 'osx-arm64' + nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-osx-arm64' + includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' + outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' + signMac: true -# ===================================================================== -# Test stages — same-platform only. win-arm64 is build-only. -# ===================================================================== + # ===================================================================== + # Tests — base variant. Same-platform only; win-arm64 is build-only. + # ===================================================================== + + - stage: js_test_win_x64 + displayName: 'JS SDK: Test Windows x64' + dependsOn: + - js_build_win_x64 + jobs: + - job: test + pool: + name: onnxruntime-Win-CPU-2022 + os: windows + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'js-prebuild-win-x64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-win-x64' + steps: + - checkout: self + clean: true + - template: ../../templates/checkout-steps.yml@self + parameters: + repoName: test-data-shared + - template: steps-test-js.yml + parameters: + rid: 'win-x64' + prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-win-x64' + testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' -- stage: js_test_win_x64 - displayName: 'JS SDK: Test Windows x64' - dependsOn: - - js_build_win_x64 - jobs: - - job: test - pool: - name: onnxruntime-Win-CPU-2022 - os: windows - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'js-prebuild-win-x64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-win-x64' - steps: - - checkout: self - clean: true - - template: ../../templates/checkout-steps.yml@self - parameters: - repoName: test-data-shared - - template: steps-test-js.yml - parameters: - rid: 'win-x64' - prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-win-x64' - testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' + - stage: js_test_linux_x64 + displayName: 'JS SDK: Test Linux x64' + dependsOn: + - js_build_linux_x64 + jobs: + - job: test + pool: + name: onnxruntime-Ubuntu2404-AMD-CPU + os: linux + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'js-prebuild-linux-x64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-linux-x64' + steps: + - checkout: self + clean: true + - template: ../../templates/checkout-steps.yml@self + parameters: + repoName: test-data-shared + - template: steps-test-js.yml + parameters: + rid: 'linux-x64' + prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-linux-x64' + testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' -- stage: js_test_linux_x64 - displayName: 'JS SDK: Test Linux x64' - dependsOn: - - js_build_linux_x64 - jobs: - - job: test - pool: - name: onnxruntime-Ubuntu2404-AMD-CPU - os: linux - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'js-prebuild-linux-x64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-linux-x64' - steps: - - checkout: self - clean: true - - template: ../../templates/checkout-steps.yml@self - parameters: - repoName: test-data-shared - - template: steps-test-js.yml - parameters: - rid: 'linux-x64' - prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-linux-x64' - testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' + - stage: js_test_osx_arm64 + displayName: 'JS SDK: Test macOS ARM64' + dependsOn: + - js_build_osx_arm64 + jobs: + - job: test + pool: + name: AcesShared + os: macOS + demands: + - ImageOverride -equals ACES_VM_SharedPool_Sequoia + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'js-prebuild-osx-arm64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-osx-arm64' + steps: + - checkout: self + clean: true + - bash: | + set -euo pipefail + if ! command -v git-lfs >/dev/null 2>&1; then + brew install git-lfs + fi + git lfs install + displayName: 'Install git-lfs (macOS)' + - template: ../../templates/checkout-steps.yml@self + parameters: + repoName: test-data-shared + - template: steps-test-js.yml + parameters: + rid: 'osx-arm64' + prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-osx-arm64' + testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' -- stage: js_test_osx_arm64 - displayName: 'JS SDK: Test macOS ARM64' - dependsOn: - - js_build_osx_arm64 - jobs: - - job: test - pool: - name: AcesShared - os: macOS - demands: - - ImageOverride -equals ACES_VM_SharedPool_Sequoia - templateContext: - inputs: - - input: pipelineArtifact - artifactName: 'js-prebuild-osx-arm64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-osx-arm64' - steps: - - checkout: self - clean: true - - bash: | - set -euo pipefail - if ! command -v git-lfs >/dev/null 2>&1; then - brew install git-lfs - fi - git lfs install - displayName: 'Install git-lfs (macOS)' - - template: ../../templates/checkout-steps.yml@self - parameters: - repoName: test-data-shared - - template: steps-test-js.yml - parameters: - rid: 'osx-arm64' - prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-osx-arm64' - testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' + # ===================================================================== + # Pack — base variant. Runs after all four builds. Pure packaging on + # Windows. + # ===================================================================== + + - stage: js_pack + displayName: 'JS SDK: Pack multi-platform npm tarball' + dependsOn: + - js_build_win_x64 + - js_build_win_arm64 + - js_build_linux_x64 + - js_build_osx_arm64 + 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: 'js-prebuild-win-x64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-win-x64' + - input: pipelineArtifact + artifactName: 'js-prebuild-win-arm64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-win-arm64' + - input: pipelineArtifact + artifactName: 'js-prebuild-linux-x64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-linux-x64' + - input: pipelineArtifact + artifactName: 'js-prebuild-osx-arm64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-osx-arm64' + outputs: + - output: pipelineArtifact + artifactName: 'js-sdk' + targetPath: '$(Build.ArtifactStagingDirectory)/js-sdk' + steps: + - checkout: self + clean: true + - template: steps-pack-js.yml + parameters: + outputDir: '$(Build.ArtifactStagingDirectory)/js-sdk' # ===================================================================== -# Pack stage — runs after all four builds. Pure packaging on Windows. +# WinML variant: Windows only (x64 + arm64); only x64 is tested. +# Produces the `foundry-local-sdk-winml` npm tarball. # ===================================================================== +- ${{ if eq(parameters.variant, 'winml') }}: + + - stage: js_build_winml_win_x64 + displayName: 'JS SDK: Build Windows x64 (WinML)' + dependsOn: + - compute_version + - cpp_build_win_x64_winml + - cpp_build_win_x64 + jobs: + - job: build + pool: + name: onnxruntime-Win-CPU-2022 + os: windows + variables: + - group: FoundryLocal-ESRP-Signing + 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-include' + targetPath: '$(Pipeline.Workspace)/cpp-native-include' + outputs: + - output: pipelineArtifact + artifactName: 'js-prebuild-winml-win-x64' + targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' + steps: + - checkout: self + clean: true + - template: steps-build-js.yml + parameters: + rid: 'win-x64' + nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-x64-winml' + includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' + outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' + isWinML: true + signWindows: true + + - stage: js_build_winml_win_arm64 + displayName: 'JS SDK: Build Windows ARM64 (WinML)' + dependsOn: + - compute_version + - cpp_build_win_arm64_winml + - cpp_build_win_x64 + jobs: + - job: build + pool: + name: onnxruntime-Win-CPU-2022 + os: windows + variables: + - group: FoundryLocal-ESRP-Signing + 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' + - input: pipelineArtifact + artifactName: 'cpp-native-include' + targetPath: '$(Pipeline.Workspace)/cpp-native-include' + outputs: + - output: pipelineArtifact + artifactName: 'js-prebuild-winml-win-arm64' + targetPath: '$(Build.ArtifactStagingDirectory)/js-prebuild' + steps: + - checkout: self + clean: true + - template: steps-build-js.yml + parameters: + rid: 'win-arm64' + nativeArtifactDir: '$(Pipeline.Workspace)/cpp-native-win-arm64-winml' + includeArtifactDir: '$(Pipeline.Workspace)/cpp-native-include' + outputDir: '$(Build.ArtifactStagingDirectory)/js-prebuild' + targetArch: 'arm64' + isWinML: true + signWindows: true + + - stage: js_test_winml_win_x64 + displayName: 'JS SDK: Test Windows x64 (WinML)' + dependsOn: + - js_build_winml_win_x64 + jobs: + - job: test + pool: + name: onnxruntime-Win-CPU-2022 + os: windows + templateContext: + inputs: + - input: pipelineArtifact + artifactName: 'js-prebuild-winml-win-x64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-winml-win-x64' + steps: + - checkout: self + clean: true + - template: ../../templates/checkout-steps.yml@self + parameters: + repoName: test-data-shared + - template: steps-test-js.yml + parameters: + rid: 'win-x64' + prebuildArtifactDir: '$(Pipeline.Workspace)/js-prebuild-winml-win-x64' + testDataSharedDir: '$(Build.SourcesDirectory)/test-data-shared' -- stage: js_pack - displayName: 'JS SDK: Pack multi-platform npm tarball' - dependsOn: - - js_build_win_x64 - - js_build_win_arm64 - - js_build_linux_x64 - - js_build_osx_arm64 - 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: 'js-prebuild-win-x64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-win-x64' - - input: pipelineArtifact - artifactName: 'js-prebuild-win-arm64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-win-arm64' - - input: pipelineArtifact - artifactName: 'js-prebuild-linux-x64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-linux-x64' - - input: pipelineArtifact - artifactName: 'js-prebuild-osx-arm64' - targetPath: '$(Pipeline.Workspace)/js-prebuild-osx-arm64' - outputs: - - output: pipelineArtifact - artifactName: 'js-sdk' - targetPath: '$(Build.ArtifactStagingDirectory)/js-sdk' - steps: - - checkout: self - clean: true - - template: steps-pack-js.yml - parameters: - outputDir: '$(Build.ArtifactStagingDirectory)/js-sdk' + - stage: js_pack_winml + displayName: 'JS SDK: Pack foundry-local-sdk-winml npm tarball' + dependsOn: + - js_build_winml_win_x64 + - js_build_winml_win_arm64 + 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: 'js-prebuild-winml-win-x64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-winml-win-x64' + - input: pipelineArtifact + artifactName: 'js-prebuild-winml-win-arm64' + targetPath: '$(Pipeline.Workspace)/js-prebuild-winml-win-arm64' + outputs: + - output: pipelineArtifact + artifactName: 'js-sdk-winml' + targetPath: '$(Build.ArtifactStagingDirectory)/js-sdk' + steps: + - checkout: self + clean: true + - template: steps-pack-js.yml + parameters: + outputDir: '$(Build.ArtifactStagingDirectory)/js-sdk' + isWinML: true diff --git a/.pipelines/v2/templates/stages-sdk-v2.yml b/.pipelines/v2/templates/stages-sdk-v2.yml index 5a1c59ba..224cb56a 100644 --- a/.pipelines/v2/templates/stages-sdk-v2.yml +++ b/.pipelines/v2/templates/stages-sdk-v2.yml @@ -4,6 +4,7 @@ # 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) +# 4. JS SDK base + WinML (templates/stages-js.yml × 2) # # Assumes the caller has already emitted a `compute_version` stage that # publishes the `version-info` pipeline artifact (containing sdkVersion.txt @@ -51,5 +52,12 @@ stages: parameters: variant: winml -# ── JS SDK (single multi-platform tarball) ── +# ── JS SDK (base) ── - template: stages-js.yml + parameters: + variant: base + +# ── JS SDK (WinML) ── +- template: stages-js.yml + parameters: + variant: winml diff --git a/.pipelines/v2/templates/steps-build-js.yml b/.pipelines/v2/templates/steps-build-js.yml index 5e6ab1e7..faa6b58f 100644 --- a/.pipelines/v2/templates/steps-build-js.yml +++ b/.pipelines/v2/templates/steps-build-js.yml @@ -35,6 +35,10 @@ parameters: default: 'native' values: ['native', 'arm64'] displayName: 'Cross-compile target arch for node-gyp on Windows x64 host. "native" = no cross.' +- name: isWinML + type: boolean + default: false + displayName: 'When true, also stage Microsoft.Windows.AI.MachineLearning.dll for the WinML SKU' - name: signWindows type: boolean default: false @@ -145,6 +149,20 @@ steps: Copy-Item $nativeLibPath -Destination $dst -Force Write-Host " staged $(nativeLib)" + # WinML SKU: bundle Microsoft.Windows.AI.MachineLearning.dll next to + # foundry_local.dll. winml_ep_bootstrapper.cc::LoadWinMLDllFromOwnDirectory + # resolves it relative to foundry_local.dll's own directory at load time, + # so packagers must keep these two files co-located in prebuilds/-/. + # The DLL is signed by Microsoft via NuGet, so it is intentionally + # excluded from the ESRP signing pattern below (no re-sign needed). + $isWinML = $${{ parameters.isWinML }} + if ($isWinML) { + $winmlDllPath = Join-Path "${{ parameters.nativeArtifactDir }}" "Microsoft.Windows.AI.MachineLearning.dll" + if (-not (Test-Path $winmlDllPath)) { throw "WinML DLL not found: $winmlDllPath" } + Copy-Item $winmlDllPath -Destination $dst -Force + Write-Host " staged Microsoft.Windows.AI.MachineLearning.dll" + } + Get-ChildItem $dst | ForEach-Object { Write-Host " $($_.Name) $($_.Length) bytes" } displayName: 'Stage prebuild directory' diff --git a/.pipelines/v2/templates/steps-pack-js.yml b/.pipelines/v2/templates/steps-pack-js.yml index 439ab41f..daa76e96 100644 --- a/.pipelines/v2/templates/steps-pack-js.yml +++ b/.pipelines/v2/templates/steps-pack-js.yml @@ -19,6 +19,10 @@ parameters: type: string default: '$(Build.ArtifactStagingDirectory)/js-sdk' displayName: 'Directory where the packed .tgz is staged for upload' +- name: isWinML + type: boolean + default: false + displayName: 'When true, pack as foundry-local-sdk-winml (Windows-only prebuilds).' steps: @@ -32,12 +36,22 @@ steps: if (Test-Path $dst) { Remove-Item -Recurse -Force $dst } New-Item -ItemType Directory -Force -Path $dst | Out-Null - $sources = @( - @{ rid = 'win-x64'; plat = 'win32-x64' }, - @{ rid = 'win-arm64'; plat = 'win32-arm64' }, - @{ rid = 'linux-x64'; plat = 'linux-x64' }, - @{ rid = 'osx-arm64'; plat = 'darwin-arm64' } - ) + $isWinML = $${{ parameters.isWinML }} + if ($isWinML) { + # WinML SKU is Windows-only — mirrors the foundry-local-sdk-winml + # Python wheel matrix. WinML 2.x is a Windows-only runtime. + $sources = @( + @{ rid = 'winml-win-x64'; plat = 'win32-x64' }, + @{ rid = 'winml-win-arm64'; plat = 'win32-arm64' } + ) + } else { + $sources = @( + @{ rid = 'win-x64'; plat = 'win32-x64' }, + @{ rid = 'win-arm64'; plat = 'win32-arm64' }, + @{ rid = 'linux-x64'; plat = 'linux-x64' }, + @{ rid = 'osx-arm64'; plat = 'darwin-arm64' } + ) + } foreach ($entry in $sources) { $src = "$(Pipeline.Workspace)/js-prebuild-$($entry.rid)/prebuilds/$($entry.plat)" @@ -64,6 +78,19 @@ steps: if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } displayName: 'Stamp package version' +# Rewrite the package name for the WinML SKU. Mirrors the Python build backend's +# FL_PYTHON_PACKAGE_NAME env-var mechanism; npm exposes a first-class JSON +# editor (`npm pkg set`) so no PEP-517-style shim is needed. The same source +# tree produces either `foundry-local-sdk` or `foundry-local-sdk-winml`. +- ${{ if eq(parameters.isWinML, true) }}: + - pwsh: | + Set-Location "$(Build.SourcesDirectory)/sdk_v2/js" + npm pkg set name=foundry-local-sdk-winml + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + $name = (npm pkg get name) -replace '"', '' + Write-Host "Package name is now: $name" + displayName: 'Rename package to foundry-local-sdk-winml' + - pwsh: | Set-Location "$(Build.SourcesDirectory)/sdk_v2/js" npm run build:ts diff --git a/sdk_v2/js/README.md b/sdk_v2/js/README.md index 05528f70..41a140ef 100644 --- a/sdk_v2/js/README.md +++ b/sdk_v2/js/README.md @@ -1,8 +1,28 @@ # Foundry Local SDK — JavaScript / TypeScript (v2) -Native bindings around the Foundry Local **C++ SDK**, surfaced as an ESM npm package -(`foundry-local-sdk`). This README is the orientation guide for a developer who has just -cloned the repo and wants to build, test, and debug the JS SDK. +Native bindings around the Foundry Local **C++ SDK**, surfaced as an ESM npm package. +This README is the orientation guide for a developer who has just cloned the repo and +wants to build, test, and debug the JS SDK. + +Two package variants are published — choose the one that matches your target hardware: + +| Variant | Package | Native backends | +|---------|---------|-----------------| +| Standard (cross-platform) | `foundry-local-sdk` | CPU + CUDA + WebGPU (DirectML) | +| WinML (Windows only) | `foundry-local-sdk-winml` | Windows ML execution providers + standard backends | + +```pwsh +# Standard +npm install foundry-local-sdk + +# WinML (Windows only) +npm install foundry-local-sdk-winml +``` + +The WinML tarball additionally ships `Microsoft.Windows.AI.MachineLearning.dll` next +to `foundry_local.dll` so EP discovery returns the WinML 2.x execution providers +(OpenVINO, NvTensorRTRTX, etc.) out of the box. The two variants are mutually +exclusive — install only one per project. > The architectural plan lives in [docs/PortJsToSdkV2.md](docs/PortJsToSdkV2.md). The > implementation conventions live in