From 1f96323cddcf8b763cb06509e2b4b0176e8769b1 Mon Sep 17 00:00:00 2001 From: Chester Liu <4710575+skyline75489@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:10:14 +0800 Subject: [PATCH] Improve Windows ARM64 building & packaging (#687) A major overhaul of the NuGet packaging pipeline, including: * Restructure capi & NuGet packaging pipeline to make multi-platform nupkg possible. The NuGet artifacts are separated by EP(CPU, Cuda and DirectML). A single nupkg contains native libraries for different os & arch. * Make win-arm64 CPU packages use DLLs from NuGet package, just like win-x64. * Enable win-arm64 DirectML NuGet build & packaging (Internal work item: https://task.ms/aii/40037) * Enable linux-x64 CPU & CUDA NuGet build & packaging (Internal work item: https://task.ms/aii/34234) * Continue the work of #683 to make it work with ARM64. Run: https://dev.azure.com/aiinfra/ONNX%20Runtime/_build/results?buildId=507547&view=results Prior work: #498 Supports: #637 Future work: Needs #693 to fix Linux NuGet. --------- Co-authored-by: Baiju Meswani Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com> --- .github/workflows/win-cpu-arm64-build.yml | 35 +- .github/workflows/win-cpu-x64-build.yml | 13 +- .github/workflows/win-cuda-x64-build.yml | 13 +- .github/workflows/win-directml-x64-build.yml | 4 +- .pipelines/nuget-publishing.yml | 21 +- .pipelines/pypl-publishing.yml | 2 +- .pipelines/stages/capi-packaging-stage.yml | 94 +++++ .pipelines/stages/jobs/capi-packaging-job.yml | 136 +++++++ .../stages/jobs/nuget-packaging-job.yml | 340 +++++++++++------- .../stages/jobs/nuget-validation-job.yml | 28 +- .pipelines/stages/jobs/py-packaging-job.yml | 18 +- .pipelines/stages/jobs/py-validation-job.yml | 13 +- .../stages/jobs/steps/capi-linux-step.yml | 2 +- .../stages/jobs/steps/capi-win-step.yml | 37 +- .../stages/jobs/steps/nuget-win-step.yml | 79 ---- .../utils/download-huggingface-model.yml | 4 +- .../jobs/steps/utils/set-genai-version.yml | 12 +- .pipelines/stages/nuget-packaging-stage.yml | 112 +++--- .pipelines/stages/nuget-validation-stage.yml | 14 +- .pipelines/stages/py-packaging-stage.yml | 1 - .pipelines/stages/py-validation-stage.yml | 1 - cmake/presets/CMakeWinBuildPresets.json | 10 + cmake/presets/CMakeWinConfigPresets.json | 56 ++- examples/csharp/HelloPhi/HelloPhi.sln | 4 +- nuget/Microsoft.ML.OnnxRuntimeGenAI.nuspec | 56 --- .../nuget/generate_nuspec_for_native_nuget.py | 174 +++++++++ 26 files changed, 833 insertions(+), 446 deletions(-) create mode 100644 .pipelines/stages/capi-packaging-stage.yml create mode 100644 .pipelines/stages/jobs/capi-packaging-job.yml delete mode 100644 .pipelines/stages/jobs/steps/nuget-win-step.yml delete mode 100644 nuget/Microsoft.ML.OnnxRuntimeGenAI.nuspec create mode 100644 tools/nuget/generate_nuspec_for_native_nuget.py diff --git a/.github/workflows/win-cpu-arm64-build.yml b/.github/workflows/win-cpu-arm64-build.yml index 1d0705a4f..b4fd00e99 100644 --- a/.github/workflows/win-cpu-arm64-build.yml +++ b/.github/workflows/win-cpu-arm64-build.yml @@ -11,10 +11,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: - ort_dir: "onnxruntime-win-arm64-1.17.3" - ort_zip: "$(ort_dir).zip" - ort_url: "https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/$(ort_zip)" - binaryDir: 'build/cpu' + binaryDir: 'build/cpu/win-arm64' + ORT_NIGHTLY_REST_API: "https://feeds.dev.azure.com/aiinfra/PublicPackages/_apis/packaging/Feeds/ORT-Nightly/packages?packageNameQuery=Microsoft.ML.OnnxRuntime&api-version=6.0-preview.1" + ORT_PACKAGE_NAME: "Microsoft.ML.OnnxRuntime" jobs: windows-cpu-arm64-build: @@ -31,19 +30,27 @@ jobs: vs-version: '17.4' msbuild-architecture: arm64 - - name: Download OnnxRuntime - run: | - $env:ort_url = "https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/onnxruntime-win-arm64-1.17.3.zip" - Invoke-WebRequest -Uri $env:ort_url -OutFile $env:ort_zip + - uses: nuget/setup-nuget@v2 + with: + nuget-version: '5.x' - - name: Unzip OnnxRuntime + - name: Download OnnxRuntime Nightly + shell: powershell run: | - Expand-Archive $env:ort_zip -DestinationPath . - Remove-Item -Path $env:ort_zip + $resp = Invoke-RestMethod "${{ env.ORT_NIGHTLY_REST_API }}" + $ORT_NIGHTLY_VERSION = $resp.value[0].versions[0].normalizedVersion + Write-Host "$ORT_NIGHTLY_VERSION" + "ORT_NIGHTLY_VERSION=$ORT_NIGHTLY_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append + nuget install ${{ env.ORT_PACKAGE_NAME }} -version $ORT_NIGHTLY_VERSION -x -NonInteractive + + - run: Get-ChildItem ${{ env.ORT_PACKAGE_NAME }} -Recurse + continue-on-error: true - - name: Rename OnnxRuntime to ort + - name: Extract OnnxRuntime library and header files run: | - Rename-Item -Path $env:ort_dir -NewName ort + mkdir ort/lib + move ${{ env.ORT_PACKAGE_NAME }}/build/native/include ort/ + move ${{ env.ORT_PACKAGE_NAME }}/runtimes/win-arm64/native/* ort/lib/ - name: Configure CMake run: | @@ -80,4 +87,4 @@ jobs: - name: Run tests run: | - .\build\cpu\test\Release\unit_tests.exe \ No newline at end of file + & .\$env:binaryDir\test\Release\unit_tests.exe \ No newline at end of file diff --git a/.github/workflows/win-cpu-x64-build.yml b/.github/workflows/win-cpu-x64-build.yml index 41fe0b035..9b6415550 100644 --- a/.github/workflows/win-cpu-x64-build.yml +++ b/.github/workflows/win-cpu-x64-build.yml @@ -11,7 +11,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: - binaryDir: 'build/cpu' + binaryDir: 'build/cpu/win-x64' ORT_NIGHTLY_REST_API: "https://feeds.dev.azure.com/aiinfra/PublicPackages/_apis/packaging/Feeds/ORT-Nightly/packages?packageNameQuery=Microsoft.ML.OnnxRuntime&api-version=6.0-preview.1" ORT_PACKAGE_NAME: "Microsoft.ML.OnnxRuntime" @@ -41,15 +41,12 @@ jobs: with: dotnet-version: '8.0.x' - - name : Install jq and curl - run: | - choco install -y jq curl - - name: Download OnnxRuntime Nightly shell: pwsh run: | - $ORT_NIGHTLY_VERSION = $(curl -s "${{ env.ORT_NIGHTLY_REST_API }}" | jq -r '.value[0].versions[0].normalizedVersion') - echo "$ORT_NIGHTLY_VERSION" + $resp = Invoke-RestMethod "${{ env.ORT_NIGHTLY_REST_API }}" + $ORT_NIGHTLY_VERSION = $resp.value[0].versions[0].normalizedVersion + Write-Host "$ORT_NIGHTLY_VERSION" "ORT_NIGHTLY_VERSION=$ORT_NIGHTLY_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append nuget install ${{ env.ORT_PACKAGE_NAME }} -version $ORT_NIGHTLY_VERSION -x -NonInteractive @@ -108,7 +105,7 @@ jobs: - name: Run tests run: | - .\build\cpu\test\Release\unit_tests.exe + & .\$env:binaryDir\test\Release\unit_tests.exe - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/win-cuda-x64-build.yml b/.github/workflows/win-cuda-x64-build.yml index 3fa8df7c5..e26c7ba41 100644 --- a/.github/workflows/win-cuda-x64-build.yml +++ b/.github/workflows/win-cuda-x64-build.yml @@ -17,7 +17,7 @@ env: cuda_dir: "${{ github.workspace }}\\cuda_sdk" cuda_version: "11.8" CUDA_PATH: ${{ github.workspace }}\\cuda_sdk\\v11.8 - binaryDir: 'build/cuda' + binaryDir: 'build/cuda/win-x64' ORT_NIGHTLY_REST_API: "https://feeds.dev.azure.com/aiinfra/PublicPackages/_apis/packaging/Feeds/ORT-Nightly/packages?packageNameQuery=Microsoft.ML.OnnxRuntime.Gpu.Windows&api-version=6.0-preview.1" ORT_PACKAGE_NAME: "Microsoft.ML.OnnxRuntime.Gpu.Windows" @@ -43,15 +43,12 @@ jobs: with: dotnet-version: '8.0.x' - - name : Install jq and curl - run: | - choco install -y jq curl - - name: Download OnnxRuntime Nightly shell: pwsh run: | - $ORT_NIGHTLY_VERSION=$(curl -s "${{ env.ORT_NIGHTLY_REST_API }}" | jq -r '.value[0].versions[0].normalizedVersion') - echo "$ORT_NIGHTLY_VERSION" + $resp = Invoke-RestMethod "${{ env.ORT_NIGHTLY_REST_API }}" + $ORT_NIGHTLY_VERSION = $resp.value[0].versions[0].normalizedVersion + Write-Host "$ORT_NIGHTLY_VERSION" "ORT_NIGHTLY_VERSION=$ORT_NIGHTLY_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append nuget install ${{ env.ORT_PACKAGE_NAME }} -version $ORT_NIGHTLY_VERSION -ExcludeVersion -NonInteractive @@ -110,4 +107,4 @@ jobs: run: | $env:PATH = "${{ env.cuda_dir }}\\v${{ env.cuda_version }}\\bin;" + $env:PATH echo "Current PATH variable is: $env:PATH" - .\build\cuda\test\Release\unit_tests.exe \ No newline at end of file + & .\$env:binaryDir\test\Release\unit_tests.exe \ No newline at end of file diff --git a/.github/workflows/win-directml-x64-build.yml b/.github/workflows/win-directml-x64-build.yml index a6a6043f0..c46967ad5 100644 --- a/.github/workflows/win-directml-x64-build.yml +++ b/.github/workflows/win-directml-x64-build.yml @@ -24,7 +24,7 @@ env: d3d12_dir: "Microsoft.Direct3D.D3D12.1.614.0" d3d12_zip: "Microsoft.Direct3D.D3D12.1.614.0.zip" d3d12_url: "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/1.614.0" - binaryDir: 'build/directml' + binaryDir: 'build/directml/win-x64' jobs: @@ -102,4 +102,4 @@ jobs: - name: Run tests run: | - .\build\directml\test\Release\unit_tests.exe \ No newline at end of file + & .\$env:binaryDir\test\Release\unit_tests.exe \ No newline at end of file diff --git a/.pipelines/nuget-publishing.yml b/.pipelines/nuget-publishing.yml index d0a522c54..3f67a1f1a 100644 --- a/.pipelines/nuget-publishing.yml +++ b/.pipelines/nuget-publishing.yml @@ -28,7 +28,7 @@ parameters: type: boolean default: true -- name: enable_win_arm64_cpu +- name: enable_win_arm64 displayName: 'Whether Windows ARM64 package is built.' type: boolean default: true @@ -75,19 +75,32 @@ resources: trigger: none stages: -- template: stages/nuget-packaging-stage.yml +- template: stages/capi-packaging-stage.yml parameters: enable_win_cpu: ${{ parameters.enable_win_cpu }} enable_win_cuda: ${{ parameters.enable_win_cuda }} enable_linux_cpu: ${{ parameters.enable_linux_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} - enable_win_arm64_cpu: ${{ parameters.enable_win_arm64_cpu }} + enable_win_arm64: ${{ parameters.enable_win_arm64 }} ort_version: ${{ parameters.ort_version }} ort_cuda_version: ${{ parameters.ort_cuda_version }} ort_dml_version: ${{ parameters.ort_dml_version }} cuda_version: ${{ parameters.cuda_version }} build_config: ${{ parameters.build_config }} + +- template: stages/nuget-packaging-stage.yml + parameters: + enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_cuda: ${{ parameters.enable_win_cuda }} + enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_linux_cuda: ${{ parameters.enable_linux_cuda }} + enable_win_dml: ${{ parameters.enable_win_dml }} + enable_win_arm64: ${{ parameters.enable_win_arm64 }} + ort_version: ${{ parameters.ort_version }} + ort_dml_version: ${{ parameters.ort_dml_version }} + build_config: ${{ parameters.build_config }} + - ${{ if eq(parameters.enable_post_packaging_validation, true) }}: - template: stages/nuget-validation-stage.yml parameters: @@ -96,7 +109,7 @@ stages: enable_linux_cpu: ${{ parameters.enable_linux_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} - enable_win_arm64_cpu: ${{ parameters.enable_win_arm64_cpu }} + enable_win_arm64: ${{ parameters.enable_win_arm64 }} ort_version: ${{ parameters.ort_version }} ort_cuda_version: ${{ parameters.ort_cuda_version }} ort_dml_version: ${{ parameters.ort_dml_version }} diff --git a/.pipelines/pypl-publishing.yml b/.pipelines/pypl-publishing.yml index 82557b543..2c4b93da5 100644 --- a/.pipelines/pypl-publishing.yml +++ b/.pipelines/pypl-publishing.yml @@ -119,4 +119,4 @@ stages: ort_rocm_version: ${{ parameters.ort_rocm_version }} ort_dml_version: ${{ parameters.ort_dml_version }} cuda_versions: ${{ parameters.cuda_versions }} - SpecificArtifact: false + SpecificArtifact: false \ No newline at end of file diff --git a/.pipelines/stages/capi-packaging-stage.yml b/.pipelines/stages/capi-packaging-stage.yml new file mode 100644 index 000000000..1b9021a72 --- /dev/null +++ b/.pipelines/stages/capi-packaging-stage.yml @@ -0,0 +1,94 @@ +parameters: +- name: enable_win_cpu + type: boolean +- name: enable_win_cuda + type: boolean +- name: enable_win_dml + type: boolean +- name: enable_win_arm64 + type: boolean +- name: enable_linux_cpu + type: boolean +- name: enable_linux_cuda + type: boolean +- name: ort_version + type: string +- name: ort_cuda_version + type: string +- name: ort_dml_version + type: string +- name: cuda_version + type: string + default: '' +- name: build_config + type: string + default: 'release' + + +stages: +- stage: capi_packaging + jobs: + - ${{ if eq(parameters.enable_win_cpu, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'x64' + ep: 'cpu' + ort_version: ${{ parameters.ort_version }} + os: 'win' + build_config: ${{ parameters.build_config }} + + - ${{ if eq(parameters.enable_win_arm64, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'arm64' + ep: 'cpu' + ort_version: ${{ parameters.ort_version }} + os: 'win' + build_config: ${{ parameters.build_config }} + + - ${{ if eq(parameters.enable_win_dml, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'x64' + ep: 'directml' + ort_version: ${{ parameters.ort_dml_version }} + os: 'win' + build_config: ${{ parameters.build_config }} + + - ${{ if and(eq(parameters.enable_win_arm64, true), eq(parameters.enable_win_dml, true)) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'arm64' + ep: 'directml' + ort_version: ${{ parameters.ort_dml_version }} + os: 'win' + build_config: ${{ parameters.build_config }} + + - ${{ if eq(parameters.enable_win_cuda, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'x64' + cuda_version: ${{ parameters.cuda_version }} + ep: 'cuda' + ort_version: ${{ parameters.ort_cuda_version }} + os: 'win' + build_config: ${{ parameters.build_config }} + + - ${{ if eq(parameters.enable_linux_cpu, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'x64' + ep: 'cpu' + ort_version: ${{ parameters.ort_version }} + os: 'linux' + build_config: ${{ parameters.build_config }} + + - ${{ if eq(parameters.enable_linux_cuda, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'x64' + cuda_version: ${{ parameters.cuda_version }} + ep: 'cuda' + ort_version: ${{ parameters.ort_cuda_version }} + os: 'linux' + build_config: ${{ parameters.build_config }} \ No newline at end of file diff --git a/.pipelines/stages/jobs/capi-packaging-job.yml b/.pipelines/stages/jobs/capi-packaging-job.yml new file mode 100644 index 000000000..4530bbb86 --- /dev/null +++ b/.pipelines/stages/jobs/capi-packaging-job.yml @@ -0,0 +1,136 @@ +parameters: +- name: arch + type: string +- name: ep + type: string +- name: ort_version + type: string +- name: cuda_version + type: string + default: '' +- name: os + type: string + values: + - 'linux' + - 'win' +- name: build_config + type: string + default: 'release' + +jobs: +- job: capi_${{ parameters.os }}_${{ parameters.ep }}_${{ parameters.arch }}_packaging + ${{ if eq(parameters.os, 'linux') }}: + ${{ if eq(parameters.arch, 'x64') }}: + pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + ${{ elseif eq(parameters.arch, 'arm64') }}: + pool: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' + ${{ else }}: + pool: 'nnxruntime-Ubuntu2204-AMD-CPU' + ${{ if eq(parameters.os, 'win') }}: + ${{ if eq(parameters.arch, 'x64') }}: + pool: 'onnxruntime-Win-CPU-2022' + ${{ elseif eq(parameters.arch, 'arm64') }}: + pool: 'onnxruntime-genai-windows-vs-2022-arm64' + ${{ else }}: + pool: 'onnxruntime-Win-CPU-2022' + timeoutInMinutes: 180 + # set variables here to be used in the template and steps + variables: + - name: arch + value: ${{ parameters.arch }} + - name: artifactName + value: 'onnxruntime-genai-${{ parameters.os }}-${{ parameters.ep }}-${{ parameters.arch }}' + - name: build_config + value: ${{ parameters.build_config }} + - name: buildDir + value: 'build/${{ parameters.ep }}' + - name: cuda_version + value: ${{ parameters.cuda_version }} + - name: ep + value: ${{ parameters.ep }} + - name: ort_version + value: ${{ parameters.ort_version }} + - name: GDN_CODESIGN_TARGETDIRECTORY + value: '$(Build.ArtifactStagingDirectory)/nuget' + - name: os + value: ${{ parameters.os }} + - name: feed_name + ${{ if and(eq(parameters.cuda_version, '12.2'), eq(parameters.ep, 'cuda')) }}: + value: 'ort-cuda-12-nightly' + ${{ else }}: + value: '7982ae20-ed19-4a35-a362-a96ac99897b7' + - name: ort_filename + ${{ if eq(parameters.ep, 'cpu') }}: + value: 'Microsoft.ML.OnnxRuntime' + ${{ elseif eq(parameters.ep, 'cuda') }}: + ${{if eq(parameters.os, 'win') }}: + value: 'Microsoft.ML.OnnxRuntime.Gpu.Windows' + ${{ else }}: + value: 'Microsoft.ML.OnnxRuntime.Gpu.Linux' + ${{ elseif eq(parameters.ep, 'directml')}}: + value: 'Microsoft.ML.OnnxRuntime.DirectML' + ${{ elseif eq(parameters.ep, 'rocm')}}: + value: 'Microsoft.ML.OnnxRuntime.ROCm' + ${{ else }}: + value: 'Microsoft.ML.OnnxRuntime' + + - name: ortHome + value: 'ort' + - name: dml_dir + value: 'Microsoft.AI.DirectML.1.15.0' + - name: dml_zip + value: 'Microsoft.AI.DirectML.1.15.0.zip' + - name: dml_url + value: "https://www.nuget.org/api/v2/package/Microsoft.AI.DirectML/1.15.0" + + - name: d3d12_dir + value: 'Microsoft.Direct3D.D3D12.1.614.0' + - name: d3d12_zip + value: 'Microsoft.Direct3D.D3D12.1.614.0.zip' + - name: d3d12_url + value: "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/1.614.0" + + workspace: + clean: all + steps: + - script: | + MKDIR $(Agent.ToolsDirectory)\Python\3.11.0\arm64 + XCOPY /s /y /h /e /c /q "C:\Python\Python311\*.*" $(Agent.ToolsDirectory)\Python\3.11.0\arm64\ + COPY NUL $(Agent.ToolsDirectory)\Python\3.11.0\arm64.complete + DIR $(Agent.ToolsDirectory)\Python + DIR $(Agent.ToolsDirectory)\Python\3.11.0 + DIR $(Agent.ToolsDirectory)\Python\3.11.0\arm64 + DIR "C:\Python" + displayName: Copy python 3.11.0 version to agent tools directory + condition: and(eq(variables['arch'], 'arm64'), eq(variables['os'], 'win')) + + - ${{ if eq(parameters.arch, 'arm64') }}: + - task: UsePythonVersion@0 + inputs: + versionSpec: 3.11 + addToPath: true + architecture: $(arch) + - ${{ else }}: + - task: UsePythonVersion@0 + inputs: + versionSpec: 3.10 + addToPath: true + architecture: $(arch) + + - ${{ if eq(parameters.os, 'linux') }}: + - template: steps/capi-linux-step.yml + parameters: + target: 'onnxruntime-genai' + arch: ${{ parameters.arch }} + ep: ${{ parameters.ep }} + build_config: ${{ parameters.build_config }} + + - ${{ if eq(parameters.os, 'win') }}: + - template: steps/capi-win-step.yml + parameters: + target: 'onnxruntime-genai' + arch: ${{ parameters.arch }} + ep: ${{ parameters.ep }} + build_config: ${{ parameters.build_config }} + + - template: steps/compliant-and-cleanup-step.yml diff --git a/.pipelines/stages/jobs/nuget-packaging-job.yml b/.pipelines/stages/jobs/nuget-packaging-job.yml index d8e0ebc70..02699db52 100644 --- a/.pipelines/stages/jobs/nuget-packaging-job.yml +++ b/.pipelines/stages/jobs/nuget-packaging-job.yml @@ -1,40 +1,57 @@ parameters: -- name: arch - type: string - name: ep type: string + +- name: enable_win_cpu + displayName: 'Whether Windows CPU package is built.' + type: boolean + default: false + +- name: enable_win_cuda + displayName: 'Whether Windows CUDA package is built.' + type: boolean + default: false + +- name: enable_linux_cpu + displayName: 'Whether Linux CPU package is built.' + type: boolean + default: false + +- name: enable_linux_cuda + displayName: 'Whether Linux CUDA package is built.' + type: boolean + default: false + +- name: enable_win_dml + displayName: 'Whether Windows DirectML package is built.' + type: boolean + default: false + +- name: enable_win_arm64 + displayName: 'Whether Windows ARM64 package is built.' + type: boolean + default: false + - name: ort_version type: string -- name: cuda_version - type: string - default: '' -- name: os - type: string - values: - - 'linux' - - 'win' + - name: build_config type: string default: 'release' jobs: -- job: nuget_${{ parameters.os }}_${{ parameters.ep }}_${{ parameters.arch }}_packaging - ${{ if eq(parameters.os, 'linux') }}: - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' - ${{ if eq(parameters.os, 'win') }}: - ${{ if eq(parameters.ep, 'directml') }}: - pool: 'onnxruntime-Win2022-GPU-dml-A10' - ${{ elseif eq(parameters.arch, 'arm64') }}: - pool: 'onnxruntime-genai-windows-vs-2022-arm64' - ${{ else }}: - pool: 'onnxruntime-Win-CPU-2022' - timeoutInMinutes: 180 - # set variables here to be used in the template and steps +- job: nuget_${{ parameters.ep }}_packaging + pool: 'onnxruntime-Win-CPU-2022' variables: - - name: arch - value: ${{ parameters.arch }} - - name: artifactName - value: 'onnxruntime-genai-${{ parameters.os }}-${{ parameters.ep }}-${{ parameters.arch }}' + - name: ep + value: ${{ parameters.ep }} + + - name: ort_version + value: ${{ parameters.ort_version }} + + - name: buildDir + value: 'build/${{ parameters.ep }}' + - name: buildConfig ${{ if eq(parameters.build_config, 'release') }}: value: 'Release' @@ -44,125 +61,184 @@ jobs: value: 'Debug' ${{ else }}: value: 'MinSizeRel' - - name: build_config - value: ${{ parameters.build_config }} - - name: buildDir - value: 'build/${{ parameters.ep }}' - - name: cuda_version - value: ${{ parameters.cuda_version }} - - name: ep - value: ${{ parameters.ep }} - - name: ort_version - value: ${{ parameters.ort_version }} - - name: GDN_CODESIGN_TARGETDIRECTORY - value: '$(Build.ArtifactStagingDirectory)/nuget' - - name: os - value: ${{ parameters.os }} - - name: feed_name - ${{ if and(eq(parameters.cuda_version, '12.2'), eq(parameters.ep, 'cuda')) }}: - value: 'ort-cuda-12-nightly' - ${{ else }}: - value: '7982ae20-ed19-4a35-a362-a96ac99897b7' - - name: ort_filename - ${{ if eq(parameters.ep, 'cpu') }}: - value: 'Microsoft.ML.OnnxRuntime' - ${{ elseif eq(parameters.ep, 'cuda') }}: - ${{if eq(parameters.os, 'win') }}: - value: 'Microsoft.ML.OnnxRuntime.Gpu.Windows' - ${{ else }}: - value: 'Microsoft.ML.OnnxRuntime.Gpu.Linux' - ${{ elseif eq(parameters.ep, 'directml')}}: - value: 'Microsoft.ML.OnnxRuntime.DirectML' - ${{ elseif eq(parameters.ep, 'rocm')}}: - value: 'Microsoft.ML.OnnxRuntime.ROCm' - ${{ else }}: - value: 'Microsoft.ML.OnnxRuntime' - - name: genai_nuget_ext + - name: artifactName + value: 'onnxruntime-genai-${{ parameters.ep }}' + + - name: genai_nuget_package_name ${{ if eq(parameters.ep, 'cpu') }}: - value: '' + value: 'Microsoft.ML.OnnxRuntimeGenAI' ${{ if eq(parameters.ep, 'cuda') }}: - value: '.Cuda' + value: 'Microsoft.ML.OnnxRuntimeGenAI.Cuda' ${{ if eq(parameters.ep, 'directml') }}: - value: '.DirectML' - - name: ort_nuget_ext + value: 'Microsoft.ML.OnnxRuntimeGenAI.DirectML' + + - name: ort_nuget_package_name ${{ if eq(parameters.ep, 'cpu') }}: - value: '' + value: 'Microsoft.ML.OnnxRuntime' ${{ if eq(parameters.ep, 'cuda') }}: - value: '.Gpu' + value: 'Microsoft.ML.OnnxRuntime.Gpu' ${{ if eq(parameters.ep, 'directml') }}: - value: '.DirectML' - - name: ortHome - value: 'ort' - - name: dml_dir - value: 'Microsoft.AI.DirectML.1.14.2' - - name: dml_zip - value: 'Microsoft.AI.DirectML.1.14.2.zip' - - name: dml_url - value: "https://www.nuget.org/api/v2/package/Microsoft.AI.DirectML/1.14.2" - - - name: ort_arm64_dir - value: 'onnxruntime-win-arm64-1.17.3' - - name: ort_arm64_zip - value: 'onnxruntime-win-arm64-1.17.3.zip' - - name: ort_arm64_url - value: "https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/onnxruntime-win-arm64-1.17.3.zip" - - - name: d3d12_dir - value: 'Microsoft.Direct3D.D3D12.1.614.0' - - name: d3d12_zip - value: 'Microsoft.Direct3D.D3D12.1.614.0.zip' - - name: d3d12_url - value: "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/1.614.0" - - workspace: - clean: all + value: 'Microsoft.ML.OnnxRuntime.DirectML' steps: - - script: | - MKDIR $(Agent.ToolsDirectory)\Python\3.11.0\arm64 - XCOPY /s /y /h /e /c /q "C:\Python\Python311\*.*" $(Agent.ToolsDirectory)\Python\3.11.0\arm64\ - COPY NUL $(Agent.ToolsDirectory)\Python\3.11.0\arm64.complete - DIR $(Agent.ToolsDirectory)\Python - DIR $(Agent.ToolsDirectory)\Python\3.11.0 - DIR $(Agent.ToolsDirectory)\Python\3.11.0\arm64 - DIR "C:\Python" - displayName: Copy python 3.11.0 version to agent tools directory - condition: and(eq(variables['arch'], 'arm64'), eq(variables['os'], 'win')) - - - ${{ if eq(parameters.arch, 'arm64') }}: - - task: UsePythonVersion@0 - inputs: - versionSpec: 3.11 - addToPath: true - architecture: $(arch) - - ${{ else }}: - - task: UsePythonVersion@0 - inputs: - versionSpec: 3.10 - addToPath: true - architecture: $(arch) - - - ${{ if eq(parameters.os, 'linux') }}: - - template: steps/capi-linux-step.yml + - ${{ if and(eq(parameters.enable_win_cpu, true), eq(parameters.ep, 'cpu')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml + parameters: + StepName: 'Download win-cpu-x64 capi Artifacts' + ArtifactName: onnxruntime-genai-win-cpu-x64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + + - ${{ if and(eq(parameters.enable_win_cuda, true), eq(parameters.ep, 'cuda')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml + parameters: + StepName: 'Download win-cuda-x64 capi Artifacts' + ArtifactName: onnxruntime-genai-win-cuda-x64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + + - ${{ if and(eq(parameters.enable_win_dml, true), eq(parameters.ep, 'directml')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml + parameters: + StepName: 'Download win-directml-x64 capi Artifacts' + ArtifactName: onnxruntime-genai-win-directml-x64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + + - ${{ if and(eq(parameters.enable_win_arm64, true), eq(parameters.ep, 'cpu')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml parameters: - target: 'onnxruntime-genai' - arch: ${{ parameters.arch }} - ep: ${{ parameters.ep }} - build_config: ${{ parameters.build_config }} + StepName: 'Download win-cpu-arm64 capi Artifacts' + ArtifactName: onnxruntime-genai-win-cpu-arm64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' - # TODO: Add a step to build the linux nuget package + - ${{ if and(eq(parameters.enable_win_arm64, true), eq(parameters.enable_win_dml, true), eq(parameters.ep, 'directml')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml + parameters: + StepName: 'Download win-directml-arm64 capi Artifacts' + ArtifactName: onnxruntime-genai-win-directml-arm64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' - - ${{ if eq(parameters.os, 'win') }}: - - template: steps/capi-win-step.yml + - ${{ if and(eq(parameters.enable_linux_cpu, true), eq(parameters.ep, 'cpu')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml parameters: - target: 'onnxruntime-genai' - arch: ${{ parameters.arch }} - ep: ${{ parameters.ep }} - build_config: ${{ parameters.build_config }} + StepName: 'Download linux-cpu-x64 capi Artifacts' + ArtifactName: onnxruntime-genai-linux-cpu-x64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' - - template: steps/nuget-win-step.yml + - ${{ if and(eq(parameters.enable_linux_cuda, true), eq(parameters.ep, 'cuda')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml parameters: - arch: ${{ parameters.arch }} + StepName: 'Download linux-cuda-x64 capi Artifacts' + ArtifactName: onnxruntime-genai-linux-cuda-x64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + + - checkout: self + path: onnxruntime-genai + clean: true + submodules: recursive + + - template: steps/utils/set-genai-version.yml + + - powershell: | + dotnet build Microsoft.ML.OnnxRuntimeGenAI.csproj -p:Configuration="$(buildConfig)" --verbosity normal + displayName: 'Build CSharp' + workingDirectory: '$(Build.Repository.LocalPath)\src\csharp' + + - task: BinSkim@4 + displayName: 'Run BinSkim' + inputs: + AnalyzeTargetGlob: '$(Build.Repository.LocalPath)\src\csharp\**\*.dll' + continueOnError: true + + - template: steps/compliant/win-esrp-dll-step.yml + parameters: + FolderPath: '$(Build.Repository.LocalPath)\src\csharp\bin\$(buildConfig)\' + DisplayName: 'ESRP - Sign C# dlls' + Pattern: '*OnnxRuntimeGenAI*.dll' + + - powershell: | + $artifacts_dir = '$(Build.BinariesDirectory)/artifact-downloads' + Write-Host "List downloaded artifacts" + $artifacts = Get-ChildItem -Path $artifacts_dir/* -Include *.zip,*.tar.gz + Write-Host $artifacts + + $outputDir = '$(Build.Repository.LocalPath)/$(buildDir)' + + mkdir -Force $outputDir + foreach ($file in $artifacts) { + $a = $file.Name + Write-Host "Extracting " $a + $rid_match = $a -match "onnxruntime-genai-$(genai_version)-(.+?)-?(?:cuda|dml)?(\.zip|\.tar\.gz)" + if ($rid_match) { + $rid = $Matches.1 + } + else { + Write-Host "Invalid artifact name" $file + return + } + mkdir -Force $outputDir/$rid + + if ($a -like "*.zip") { + Expand-Archive -Path $file -DestinationPath $outputDir/$rid + } + elseif ($a -like "*.tar.gz") { + tar -xf $file -C $outputDir/$rid + } + + mkdir -Force $outputDir/$rid/$(buildConfig) + $b = $file.Basename + $b = $b -split '.tar' + $b = $b[0] + Move-Item $outputDir/$rid/$b/lib/* $outputDir/$rid/$(buildConfig) -Force + } + + Write-Host "List extracted artifacts" + Get-ChildItem -Path $nativeBuildOutputDir -Recurse + + displayName: 'Extract Artifacts & Prepare Native Libraries' + workingDirectory: '$(Build.BinariesDirectory)/artifact-downloads' + + - task: UsePythonVersion@0 + inputs: + versionSpec: 3.10 + addToPath: true + + - powershell: | + python.exe $(Build.Repository.LocalPath)\tools\nuget\generate_nuspec_for_native_nuget.py ` + --package_name $(genai_nuget_package_name) ` + --package_version $(genai_version) ` + --ort_package_name $(ort_nuget_package_name) ` + --ort_package_version $(ort_version) ` + --build_config $(buildConfig) ` + --sources_path $(Build.Repository.LocalPath) ` + --native_build_path $(buildDir) ` + --nuspec_output_path $(Build.Repository.LocalPath)/nuget/$(genai_nuget_package_name).nuspec + + cat $(Build.Repository.LocalPath)\nuget\$(genai_nuget_package_name).nuspec + + displayName: 'Generate Nuspec for native' + + - task: NuGetCommand@2 + displayName: 'Nuget Packaging' + inputs: + command: 'pack' + packagesToPack: $(Build.Repository.LocalPath)\nuget\$(genai_nuget_package_name).nuspec + packDestination: $(Build.ArtifactStagingDirectory)\nuget + + - task: NuGetCommand@2 + displayName: 'Nuget Managed Packaging' + inputs: + command: 'pack' + packagesToPack: $(Build.Repository.LocalPath)\nuget\Microsoft.ML.OnnxRuntimeGenAI.Managed.nuspec + buildProperties: 'version=$(genai_version);configuration=$(buildConfig)' + packDestination: $(Build.ArtifactStagingDirectory)\nuget - - template: steps/compliant-and-cleanup-step.yml + - template: steps/compliant/esrp_nuget.yml + parameters: + DisplayName: 'ESRP - sign NuGet package' + FolderPath: '$(Build.ArtifactStagingDirectory)\nuget' + DoEsrp: 'true' + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: ONNXRuntime Genai NuGet' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)\nuget' + ArtifactName: $(artifactName)-nuget \ No newline at end of file diff --git a/.pipelines/stages/jobs/nuget-validation-job.yml b/.pipelines/stages/jobs/nuget-validation-job.yml index 026fa8b16..c2fd44f92 100644 --- a/.pipelines/stages/jobs/nuget-validation-job.yml +++ b/.pipelines/stages/jobs/nuget-validation-job.yml @@ -27,13 +27,18 @@ jobs: ${{ if eq(parameters.os, 'linux') }}: ${{ if eq(parameters.ep, 'cuda') }}: pool: 'Onnxruntime-Linux-GPU' + ${{ elseif eq(parameters.arch, 'arm64') }}: + pool: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' ${{ else }}: pool: 'onnxruntime-Ubuntu2204-AMD-CPU' ${{ if eq(parameters.os, 'win') }}: - ${{ if eq(parameters.ep, 'directml') }}: - pool: 'onnxruntime-Win2022-GPU-dml-A10' - ${{ elseif eq(parameters.ep, 'cuda') }}: - pool: 'onnxruntime-Win2022-GPU-A10' + ${{ if eq(parameters.arch, 'x64') }}: + ${{ if eq(parameters.ep, 'directml') }}: + pool: 'onnxruntime-Win2022-GPU-dml-A10' + ${{ elseif eq(parameters.ep, 'cuda') }}: + pool: 'onnxruntime-Win2022-GPU-A10' + ${{ else }}: + pool: 'onnxruntime-Win-CPU-2022' ${{ elseif eq(parameters.arch, 'arm64') }}: pool: 'onnxruntime-genai-windows-vs-2022-arm64' ${{ else }}: @@ -45,7 +50,7 @@ jobs: - name: arch value: ${{ parameters.arch }} - name: artifactName - value: 'onnxruntime-genai-${{ parameters.os }}-${{ parameters.ep }}-${{ parameters.arch }}' + value: 'onnxruntime-genai-${{ parameters.ep }}' - name: buildConfig value: 'Release' - name: buildDir @@ -112,13 +117,24 @@ jobs: - template: steps/utils//flex-download-pipeline-artifact.yml parameters: StepName: 'Download NuGet Artifacts' - ArtifactName: $(ArtifactName)-nuget + ArtifactName: $(artifactName)-nuget TargetPath: '$(Build.BinariesDirectory)/nuget' SpecificArtifact: ${{ parameters.specificArtifact }} BuildId: ${{ parameters.BuildId }} - ${{ if eq(parameters.os, 'win') }}: + - ${{ if eq(parameters.ep, 'cuda') }}: + - powershell: | + $env:AZCOPY_MSI_CLIENT_ID = "63b63039-6328-442f-954b-5a64d124e5b4"; + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v$(cuda_version)" 'cuda_sdk' + displayName: 'Download CUDA $(cuda_version)' + workingDirectory: '$(Build.Repository.LocalPath)' - powershell: | + if ("$(ep)" -eq "cuda") { + $env:CUDA_PATH = '$(Build.Repository.LocalPath)\cuda_sdk\v$(cuda_version)' + $env:PATH = "$env:CUDA_PATH\bin;$env:CUDA_PATH\extras\CUPTI\lib64;$env:PATH" + Write-Host $env:PATH + } dotnet --info Copy-Item -Force -Recurse -Verbose $(Build.BinariesDirectory)/nuget/* -Destination examples/csharp/HelloPhi/ cd examples/csharp/HelloPhi diff --git a/.pipelines/stages/jobs/py-packaging-job.yml b/.pipelines/stages/jobs/py-packaging-job.yml index 400394b72..4e65e0454 100644 --- a/.pipelines/stages/jobs/py-packaging-job.yml +++ b/.pipelines/stages/jobs/py-packaging-job.yml @@ -24,10 +24,15 @@ parameters: jobs: - job: python_${{ parameters.os }}_${{ parameters.ep }}${{ parameters.cuda_display_version }}_${{ parameters.arch }}_packaging ${{ if eq(parameters.os, 'linux') }}: - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + ${{ if eq(parameters.arch, 'x64') }}: + pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + ${{ elseif eq(parameters.arch, 'arm64') }}: + pool: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' + ${{ else }}: + pool: 'nnxruntime-Ubuntu2204-AMD-CPU' ${{ if eq(parameters.os, 'win') }}: - ${{ if eq(parameters.ep, 'directml') }}: - pool: 'onnxruntime-Win2022-GPU-dml-A10' + ${{ if eq(parameters.arch, 'x64') }}: + pool: 'onnxruntime-Win-CPU-2022' ${{ elseif eq(parameters.arch, 'arm64') }}: pool: 'onnxruntime-genai-windows-vs-2022-arm64' ${{ else }}: @@ -115,13 +120,6 @@ jobs: - name: dml_url value: "https://www.nuget.org/api/v2/package/Microsoft.AI.DirectML/1.14.2" - - name: ort_arm64_dir - value: 'onnxruntime-win-arm64-1.17.3' - - name: ort_arm64_zip - value: 'onnxruntime-win-arm64-1.17.3.zip' - - name: ort_arm64_url - value: "https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/onnxruntime-win-arm64-1.17.3.zip" - - name: d3d12_dir value: 'Microsoft.Direct3D.D3D12.1.614.0' - name: d3d12_zip diff --git a/.pipelines/stages/jobs/py-validation-job.yml b/.pipelines/stages/jobs/py-validation-job.yml index af8d8a890..0e1310288 100644 --- a/.pipelines/stages/jobs/py-validation-job.yml +++ b/.pipelines/stages/jobs/py-validation-job.yml @@ -30,13 +30,18 @@ jobs: ${{ if eq(parameters.os, 'linux') }}: ${{ if eq(parameters.ep, 'cuda') }}: pool: 'Onnxruntime-Linux-GPU' + ${{ elseif eq(parameters.arch, 'arm64') }}: + pool: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' ${{ else }}: pool: 'onnxruntime-Ubuntu2204-AMD-CPU' ${{ if eq(parameters.os, 'win') }}: - ${{ if eq(parameters.ep, 'directml') }}: - pool: 'onnxruntime-Win2022-GPU-dml-A10' - ${{ elseif eq(parameters.ep, 'cuda') }}: - pool: 'onnxruntime-Win2022-GPU-A10' + ${{ if eq(parameters.arch, 'x64') }}: + ${{ if eq(parameters.ep, 'directml') }}: + pool: 'onnxruntime-Win2022-GPU-dml-A10' + ${{ elseif eq(parameters.ep, 'cuda') }}: + pool: 'onnxruntime-Win2022-GPU-A10' + ${{ else }}: + pool: 'onnxruntime-Win-CPU-2022' ${{ elseif eq(parameters.arch, 'arm64') }}: pool: 'onnxruntime-genai-windows-vs-2022-arm64' ${{ else }}: diff --git a/.pipelines/stages/jobs/steps/capi-linux-step.yml b/.pipelines/stages/jobs/steps/capi-linux-step.yml index 9e8255756..89412932a 100644 --- a/.pipelines/stages/jobs/steps/capi-linux-step.yml +++ b/.pipelines/stages/jobs/steps/capi-linux-step.yml @@ -53,7 +53,7 @@ steps: --manylinux-src manylinux \ --multiple_repos \ --repository ortgenai$(ep)build$(arch) - displayName: 'Get CUDA Docker Image' + displayName: 'Get CUDA Docker Image $(cuda_version)' condition: eq(variables['ep'], 'cuda') workingDirectory: '$(Build.Repository.LocalPath)' diff --git a/.pipelines/stages/jobs/steps/capi-win-step.yml b/.pipelines/stages/jobs/steps/capi-win-step.yml index a8b7f62c9..3000f244d 100644 --- a/.pipelines/stages/jobs/steps/capi-win-step.yml +++ b/.pipelines/stages/jobs/steps/capi-win-step.yml @@ -52,34 +52,21 @@ steps: Expand-Archive $(dml_zip) -DestinationPath $(dml_dir) Remove-Item -Path $(dml_zip) Get-ChildItem -Recurse $(dml_dir) - mv $(dml_dir)\bin\x64-win\DirectML.dll ort\lib + mv $(dml_dir)\bin\$(arch)-win\DirectML.dll ort\lib mv $(dml_dir)\include\DirectML.h ort\include Invoke-WebRequest -Uri $(d3d12_url) -OutFile $(d3d12_zip) Expand-Archive $(d3d12_zip) -DestinationPath $(d3d12_dir) Remove-Item -Path $(d3d12_zip) Get-ChildItem -Recurse $(d3d12_dir) - mv $(d3d12_dir)\build\native\bin\x64\D3D12Core.dll ort\lib + mv $(d3d12_dir)\build\native\bin\$(arch)\D3D12Core.dll ort\lib workingDirectory: '$(Build.Repository.LocalPath)' + displayName: 'Download DirectML & Direct3D DLLs' continueOnError: true -- ${{ if eq(parameters.arch, 'arm64') }}: - - powershell: | - Invoke-WebRequest -Uri $(ort_arm64_url) -OutFile $(ort_arm64_zip) - Expand-Archive $(ort_arm64_zip) -DestinationPath . - Remove-Item -Path $(ort_arm64_zip) - $ort_folder_name = "ort" - if (Test-Path -Path $ort_folder_name) - { - Remove-Item -Path $ort_folder_name -Recurse -Force - } - Rename-Item -Path $(ort_arm64_dir) -NewName $ort_folder_name - workingDirectory: '$(Build.Repository.LocalPath)' - continueOnError: false - - powershell: | azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v$(cuda_version)" 'cuda_sdk' - displayName: 'Download CUDA' + displayName: 'Download CUDA $(cuda_version)' condition: eq(variables['ep'], 'cuda') workingDirectory: '$(Build.Repository.LocalPath)' @@ -92,14 +79,9 @@ steps: - powershell: | cmake --preset windows_$(arch)_$(ep)_$(build_config) displayName: 'Configure CMake C API without CUDA' - condition: and(ne(variables['ep'], 'cuda'), ne(variables['arch'], 'arm64')) + condition: ne(variables['ep'], 'cuda') workingDirectory: '$(Build.Repository.LocalPath)' -- powershell: | - cmake --preset windows_$(arch)_$(ep)_$(build_config) - displayName: 'Configure CMake C API for ARM64 CPU' - condition: eq(variables['arch'], 'arm64') - workingDirectory: '$(Build.Repository.LocalPath)' - powershell: | cmake --build --preset windows_$(arch)_$(ep)_$(build_config) --parallel --target ${{ parameters.target }} @@ -132,7 +114,7 @@ steps: displayName: 'Publish Artifact: ONNXRuntime Genai capi' inputs: ArtifactName: $(artifactName)-capi - PathtoPublish: '$(Build.Repository.LocalPath)\build\$(ep)\package' + PathtoPublish: '$(Build.Repository.LocalPath)\build\$(ep)\$(os)-$(arch)\package' - ${{ if eq(parameters.target, 'python') }}: - task: BinSkim@4 @@ -143,7 +125,7 @@ steps: - template: compliant/win-esrp-dll-step.yml parameters: - FolderPath: '$(Build.Repository.LocalPath)\build\$(ep)\wheel\onnxruntime_genai' + FolderPath: '$(Build.Repository.LocalPath)\build\$(ep)\$(os)-$(arch)\wheel\onnxruntime_genai' DisplayName: 'ESRP - PYD Sign' DoEsrp: true Pattern: '*.pyd' @@ -158,11 +140,12 @@ steps: - powershell: | Get-ChildItem -Path $(Build.Repository.LocalPath) -Recurse + displayName: 'List all files in the repo for debugging' - task: CopyFiles@2 displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' inputs: - SourceFolder: '$(Build.Repository.LocalPath)\build\$(ep)\wheel' + SourceFolder: '$(Build.Repository.LocalPath)\build\$(ep)\$(os)-$(arch)\wheel' Contents: '*.whl' TargetFolder: '$(Build.ArtifactStagingDirectory)\wheel' @@ -176,7 +159,7 @@ steps: displayName: 'Publish Build Symbols' condition: and(succeeded(), eq(variables['build_config'], 'relwithdebinfo')) inputs: - SymbolsFolder: '$(Build.Repository.LocalPath)\build\$(ep)\src\python\RelWithDebInfo\' + SymbolsFolder: '$(Build.Repository.LocalPath)\build\$(ep)\$(os)-$(arch)\src\python\RelWithDebInfo\' SearchPattern: 'onnxruntime_genai.pdb' SymbolServerType: teamServices SymbolExpirationInDays: 365 diff --git a/.pipelines/stages/jobs/steps/nuget-win-step.yml b/.pipelines/stages/jobs/steps/nuget-win-step.yml deleted file mode 100644 index bc4a65e51..000000000 --- a/.pipelines/stages/jobs/steps/nuget-win-step.yml +++ /dev/null @@ -1,79 +0,0 @@ -parameters: -- name: arch - type: string - default: 'x64' - -steps: -- powershell: | - dotnet build Microsoft.ML.OnnxRuntimeGenAI.csproj -p:Configuration="$(buildConfig)" -p:NativeBuildOutputDir="$(buildDir)\$(buildConfig)" - displayName: 'Build CSharp' - workingDirectory: '$(Build.Repository.LocalPath)\src\csharp' - -- task: BinSkim@4 - displayName: 'Run BinSkim' - inputs: - AnalyzeTargetGlob: '$(Build.Repository.LocalPath)\src\csharp\**\*.dll' - continueOnError: true - -- template: compliant/win-esrp-dll-step.yml - parameters: - FolderPath: '$(Build.Repository.LocalPath)\src\csharp\bin\$(buildConfig)\' - DisplayName: 'ESRP - Sign C# dlls' - Pattern: '*OnnxRuntimeGenAI*.dll' -- powershell: | - $VERSION = '0.4.0-dev' - $nugetPath = Join-Path "C:\Program Files" "NuGet\nuget.exe" - & $nugetPath pack Microsoft.ML.OnnxRuntimeGenAI.nuspec ` - -Prop version=$VERSION ` - -Prop genai_nuget_ext=$(genai_nuget_ext) ` - -Prop configuration=$(buildConfig) ` - -Prop buildPath=$(buildDir) ` - -Prop ort_nuget_ext=$(ort_nuget_ext) ` - -Prop ort_version=$(ort_version) - & $nugetPath pack Microsoft.ML.OnnxRuntimeGenAI.Managed.nuspec ` - -Prop version=$VERSION ` - -Prop configuration=$(buildConfig) - condition: eq(variables['arch'], 'arm64') - displayName: 'Nuget Packaging' - workingDirectory: '$(Build.Repository.LocalPath)\nuget' - -- powershell: | - $VERSION = '0.4.0-dev' - nuget.exe pack Microsoft.ML.OnnxRuntimeGenAI.nuspec ` - -Prop version=$VERSION ` - -Prop genai_nuget_ext=$(genai_nuget_ext) ` - -Prop configuration=$(buildConfig) ` - -Prop buildPath=$(buildDir) ` - -Prop ort_nuget_ext=$(ort_nuget_ext) ` - -Prop ort_version=$(ort_version) - nuget.exe pack Microsoft.ML.OnnxRuntimeGenAI.Managed.nuspec ` - -Prop version=$VERSION ` - -Prop configuration=$(buildConfig) - condition: ne(variables['arch'], 'arm64') - displayName: 'Nuget Packaging' - workingDirectory: '$(Build.Repository.LocalPath)\nuget' - -- powershell: | - Get-ChildItem -Path $(Build.Repository.LocalPath) -Recurse - displayName: 'List all files in the repo for' - -- powershell: | - Get-ChildItem -Path $(Build.Repository.LocalPath) -Recurse -- task: CopyFiles@2 - displayName: 'Copy Nuget to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.Repository.LocalPath)\nuget' - Contents: '*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)\nuget' - -- template: compliant/esrp_nuget.yml - parameters: - DisplayName: 'ESRP - sign NuGet package' - FolderPath: '$(Build.ArtifactStagingDirectory)\nuget' - DoEsrp: 'true' - -- task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: ONNXRuntime Genai capi' - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)\nuget' - ArtifactName: $(artifactName)-nuget \ No newline at end of file diff --git a/.pipelines/stages/jobs/steps/utils/download-huggingface-model.yml b/.pipelines/stages/jobs/steps/utils/download-huggingface-model.yml index dfceca4a2..30014e6ff 100644 --- a/.pipelines/stages/jobs/steps/utils/download-huggingface-model.yml +++ b/.pipelines/stages/jobs/steps/utils/download-huggingface-model.yml @@ -19,7 +19,7 @@ steps: - bash: | python -m pip install "huggingface_hub[cli]" huggingface-cli login --token $HF_TOKEN - huggingface-cli download ${{ parameters.HuggingFaceRepo }} --include ${{ parameters.RepoFolder }}/* --local-dir ${{ parameters.LocalFolder }} + huggingface-cli download ${{ parameters.HuggingFaceRepo }} --include ${{ parameters.RepoFolder }}/* --local-dir ${{ parameters.LocalFolder }} --local-dir-use-symlinks False displayName: ${{ parameters.StepName }} workingDirectory: ${{ parameters.WorkingDirectory }} env: @@ -28,7 +28,7 @@ steps: - powershell: | python -m pip install "huggingface_hub[cli]" huggingface-cli login --token $env:HF_TOKEN - huggingface-cli download ${{ parameters.HuggingFaceRepo }} --include ${{ parameters.RepoFolder }}/* --local-dir ${{ parameters.LocalFolder }} + huggingface-cli download ${{ parameters.HuggingFaceRepo }} --include ${{ parameters.RepoFolder }}/* --local-dir ${{ parameters.LocalFolder }} --local-dir-use-symlinks False displayName: ${{ parameters.StepName }} workingDirectory: ${{ parameters.WorkingDirectory }} env: diff --git a/.pipelines/stages/jobs/steps/utils/set-genai-version.yml b/.pipelines/stages/jobs/steps/utils/set-genai-version.yml index 2942573d1..72826e785 100644 --- a/.pipelines/stages/jobs/steps/utils/set-genai-version.yml +++ b/.pipelines/stages/jobs/steps/utils/set-genai-version.yml @@ -1,12 +1,10 @@ steps: -- task: PythonScript@0 +- task: PowerShell@2 displayName: 'Set genai_version variable from VERSION_INFO' inputs: - pythonInterpreter: '/usr/bin/python3' workingDirectory: $(Build.SourcesDirectory) - scriptSource: inline + targetType: inline script: | - with open('VERSION_INFO') as vi: - version = vi.readline().strip() - print(f"Setting variable: genai_version = '{version}'") - print(f"##vso[task.setvariable variable=genai_version]{version}") + $version = (Get-Content -Path .\VERSION_INFO).Trim() + Write-Host "Setting variable: genai_version = ${version}" + Write-Host "##vso[task.setvariable variable=genai_version]${version}" diff --git a/.pipelines/stages/nuget-packaging-stage.yml b/.pipelines/stages/nuget-packaging-stage.yml index e865e52e2..ab89c0cb1 100644 --- a/.pipelines/stages/nuget-packaging-stage.yml +++ b/.pipelines/stages/nuget-packaging-stage.yml @@ -1,85 +1,67 @@ parameters: - name: enable_win_cpu + displayName: 'Whether Windows CPU package is built.' type: boolean + default: true + - name: enable_win_cuda + displayName: 'Whether Windows CUDA package is built.' type: boolean -- name: enable_win_dml - type: boolean -- name: enable_win_arm64_cpu - type: boolean + default: true + - name: enable_linux_cpu + displayName: 'Whether Linux CPU package is built.' type: boolean + default: true + - name: enable_linux_cuda + displayName: 'Whether Linux CUDA package is built.' + type: boolean + default: true + +- name: enable_win_dml + displayName: 'Whether Windows DirectML package is built.' + type: boolean + default: true + +- name: enable_win_arm64 + displayName: 'Whether Windows ARM64 package is built.' type: boolean + default: true + - name: ort_version type: string -- name: ort_cuda_version - type: string - name: ort_dml_version type: string -- name: cuda_version - type: string - default: '' - name: build_config type: string default: 'release' - stages: - stage: nuget_packaging jobs: - - ${{ if eq(parameters.enable_win_cpu, true) }}: - - template: jobs/nuget-packaging-job.yml - parameters: - arch: 'x64' - ep: 'cpu' - ort_version: ${{ parameters.ort_version }} - os: 'win' - build_config: ${{ parameters.build_config }} - - - ${{ if eq(parameters.enable_win_arm64_cpu, true) }}: - - template: jobs/nuget-packaging-job.yml - parameters: - arch: 'arm64' - ep: 'cpu' - ort_version: ${{ parameters.ort_version }} - os: 'win' - build_config: ${{ parameters.build_config }} - - - ${{ if eq(parameters.enable_win_dml, true) }}: - - template: jobs/nuget-packaging-job.yml - parameters: - arch: 'x64' - ep: 'directml' - ort_version: ${{ parameters.ort_dml_version }} - os: 'win' - build_config: ${{ parameters.build_config }} - - - ${{ if eq(parameters.enable_win_cuda, true) }}: - - template: jobs/nuget-packaging-job.yml - parameters: - arch: 'x64' - cuda_version: ${{ parameters.cuda_version }} - ep: 'cuda' - ort_version: ${{ parameters.ort_cuda_version }} - os: 'win' - build_config: ${{ parameters.build_config }} - - - ${{ if eq(parameters.enable_linux_cpu, true) }}: - - template: jobs/nuget-packaging-job.yml - parameters: - arch: 'x64' - ep: 'cpu' - ort_version: ${{ parameters.ort_version }} - os: 'linux' - build_config: ${{ parameters.build_config }} - - - ${{ if eq(parameters.enable_linux_cuda, true) }}: - - template: jobs/nuget-packaging-job.yml - parameters: - arch: 'x64' - cuda_version: ${{ parameters.cuda_version }} - ep: 'cuda' - ort_version: ${{ parameters.ort_cuda_version }} - os: 'linux' - build_config: ${{ parameters.build_config }} + - ${{ if or(eq(parameters.enable_linux_cpu, true), eq(parameters.enable_win_cpu, true)) }}: + - template: jobs/nuget-packaging-job.yml + parameters: + ep: 'cpu' + ort_version: ${{ parameters.ort_version }} + build_config: ${{ parameters.build_config }} + enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_arm64: ${{ parameters.enable_win_arm64 }} + - ${{ if or(eq(parameters.enable_linux_cuda, true), eq(parameters.enable_win_cuda, true)) }}: + - template: jobs/nuget-packaging-job.yml + parameters: + ep: 'cuda' + ort_version: ${{ parameters.ort_version }} + build_config: ${{ parameters.build_config }} + enable_linux_cuda: ${{ parameters.enable_linux_cuda }} + enable_win_cuda: ${{ parameters.enable_win_cuda }} + - ${{ if eq(parameters.enable_win_dml, true) }}: + - template: jobs/nuget-packaging-job.yml + parameters: + ep: 'directml' + ort_version: ${{ parameters.ort_dml_version }} + build_config: ${{ parameters.build_config }} + enable_win_dml: ${{ parameters.enable_win_dml }} + enable_win_arm64: ${{ parameters.enable_win_arm64 }} diff --git a/.pipelines/stages/nuget-validation-stage.yml b/.pipelines/stages/nuget-validation-stage.yml index aa0be9129..380fda54b 100644 --- a/.pipelines/stages/nuget-validation-stage.yml +++ b/.pipelines/stages/nuget-validation-stage.yml @@ -13,7 +13,7 @@ parameters: type: boolean - name: enable_win_dml type: boolean -- name: enable_win_arm64_cpu +- name: enable_win_arm64 type: boolean - name: enable_linux_cpu type: boolean @@ -43,7 +43,7 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - - ${{ if eq(parameters.enable_win_arm64_cpu, true) }}: + - ${{ if eq(parameters.enable_win_arm64, true) }}: - template: jobs/nuget-validation-job.yml parameters: arch: 'arm64' @@ -63,6 +63,16 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} + - ${{ if and(eq(parameters.enable_win_dml, true), eq(parameters.enable_win_arm64, true)) }}: + - template: jobs/nuget-validation-job.yml + parameters: + arch: 'arm64' + ep: 'directml' + ort_version: ${{ parameters.ort_dml_version }} + os: 'win' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + - ${{ if eq(parameters.enable_win_cuda, true) }}: - template: jobs/nuget-validation-job.yml parameters: diff --git a/.pipelines/stages/py-packaging-stage.yml b/.pipelines/stages/py-packaging-stage.yml index cb382d7c0..d43868ed0 100644 --- a/.pipelines/stages/py-packaging-stage.yml +++ b/.pipelines/stages/py-packaging-stage.yml @@ -123,4 +123,3 @@ stages: build_config: ${{ parameters.build_config }} - diff --git a/.pipelines/stages/py-validation-stage.yml b/.pipelines/stages/py-validation-stage.yml index e6f2b9c38..6bbee518a 100644 --- a/.pipelines/stages/py-validation-stage.yml +++ b/.pipelines/stages/py-validation-stage.yml @@ -111,4 +111,3 @@ stages: os: 'linux' SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - diff --git a/cmake/presets/CMakeWinBuildPresets.json b/cmake/presets/CMakeWinBuildPresets.json index 8822e039e..f7ac7616a 100644 --- a/cmake/presets/CMakeWinBuildPresets.json +++ b/cmake/presets/CMakeWinBuildPresets.json @@ -133,6 +133,16 @@ "name": "windows_arm64_cpu_release", "configuration": "Release", "configurePreset": "windows_arm64_cpu_release" + }, + { + "name": "windows_arm64_directml_relwithdebinfo", + "configuration": "RelWithDebInfo", + "configurePreset": "windows_arm64_directml_relwithdebinfo" + }, + { + "name": "windows_arm64_directml_release", + "configuration": "Release", + "configurePreset": "windows_arm64_directml_release" } ] } \ No newline at end of file diff --git a/cmake/presets/CMakeWinConfigPresets.json b/cmake/presets/CMakeWinConfigPresets.json index 862e6ad2c..3ff252456 100644 --- a/cmake/presets/CMakeWinConfigPresets.json +++ b/cmake/presets/CMakeWinConfigPresets.json @@ -141,7 +141,7 @@ "windows_cpu_default" ], "displayName": "windows x64 cpu release", - "binaryDir": "${sourceDir}/build/cpu" + "binaryDir": "${sourceDir}/build/cpu/win-x64" }, { "name": "windows_x64_cpu_debug", @@ -150,7 +150,7 @@ "windows_cpu_default" ], "displayName": "windows x64 cpu debug", - "binaryDir": "${sourceDir}/build/cpu" + "binaryDir": "${sourceDir}/build/cpu/win-x64" }, { "name": "windows_x64_cpu_relwithdebinfo", @@ -159,7 +159,7 @@ "windows_cpu_default" ], "displayName": "windows x64 cpu relwithdebinfo", - "binaryDir": "${sourceDir}/build/cpu" + "binaryDir": "${sourceDir}/build/cpu/win-x64" }, { "name": "windows_x64_cpu_minsizerel", @@ -168,7 +168,7 @@ "windows_cpu_default" ], "displayName": "windows x64 cpu minsizerel", - "binaryDir": "${sourceDir}/build/cpu" + "binaryDir": "${sourceDir}/build/cpu/win-x64" }, { "name": "windows_x64_cuda_release_asan", @@ -225,7 +225,7 @@ "windows_cuda_default" ], "displayName": "windows x64 cuda release", - "binaryDir": "${sourceDir}/build/cuda", + "binaryDir": "${sourceDir}/build/cuda/win-x64", "cacheVariables": { "USE_CUDA": "ON" } @@ -237,7 +237,7 @@ "windows_cuda_default" ], "displayName": "windows x64 cuda debug", - "binaryDir": "${sourceDir}/build/cuda", + "binaryDir": "${sourceDir}/build/cuda/win-x64", "cacheVariables": { "USE_CUDA": "ON" } @@ -249,7 +249,7 @@ "windows_cuda_default" ], "displayName": "windows x64 cuda relwithdebinfo", - "binaryDir": "${sourceDir}/build/cuda", + "binaryDir": "${sourceDir}/build/cuda/win-x64", "cacheVariables": { "USE_CUDA": "ON" } @@ -261,7 +261,7 @@ "windows_cuda_default" ], "displayName": "windows x64 cuda minsizerel", - "binaryDir": "${sourceDir}/build/cuda", + "binaryDir": "${sourceDir}/build/cuda/win-x64", "cacheVariables": { "USE_CUDA": "ON" } @@ -309,7 +309,7 @@ "windows_directml_default" ], "displayName": "windows x64 directml release", - "binaryDir": "${sourceDir}/build/directml" + "binaryDir": "${sourceDir}/build/directml/win-x64" }, { "name": "windows_x64_directml_debug", @@ -318,7 +318,7 @@ "windows_directml_default" ], "displayName": "windows x64 directml debug", - "binaryDir": "${sourceDir}/build/directml" + "binaryDir": "${sourceDir}/build/directml/win-x64" }, { "name": "windows_x64_directml_relwithdebinfo", @@ -327,7 +327,7 @@ "windows_directml_default" ], "displayName": "windows x64 directml relwithdebinfo", - "binaryDir": "${sourceDir}/build/directml" + "binaryDir": "${sourceDir}/build/directml/win-x64" }, { "name": "windows_x64_directml_minsizerel", @@ -336,18 +336,46 @@ "windows_directml_default" ], "displayName": "windows x64 directml minsizerel", - "binaryDir": "${sourceDir}/build/directml" + "binaryDir": "${sourceDir}/build/directml/win-x64" }, { "name": "windows_arm64_cpu_relwithdebinfo", - "inherits": "windows_x64_cpu_relwithdebinfo", + "inherits": [ + "windows_relwithdebinfo_default", + "windows_cpu_default" + ], "displayName": "windows arm64 cpu relwithdebinfo", + "binaryDir": "${sourceDir}/build/cpu/win-arm64", "architecture": "arm64" }, { "name": "windows_arm64_cpu_release", - "inherits": "windows_x64_cpu_release", + "inherits": [ + "windows_release_default", + "windows_cpu_default" + ], "displayName": "windows arm64 cpu release", + "binaryDir": "${sourceDir}/build/cpu/win-arm64", + "architecture": "arm64" + }, + { + "name": "windows_arm64_directml_relwithdebinfo", + "inherits": [ + "windows_relwithdebinfo_default", + "windows_directml_default" + ], + "displayName": "windows arm64 directml relwithdebinfo", + "binaryDir": "${sourceDir}/build/directml/win-arm64", + "architecture": "arm64" + }, + { + "name": "windows_arm64_directml_release", + "inherits": [ + "windows_release_default", + "windows_directml_default" + ], + "displayName": "windows arm64 directml release", + "binaryDir": "${sourceDir}/build/directml/win-arm64", "architecture": "arm64" } ] diff --git a/examples/csharp/HelloPhi/HelloPhi.sln b/examples/csharp/HelloPhi/HelloPhi.sln index 778372f00..ed4468ddc 100644 --- a/examples/csharp/HelloPhi/HelloPhi.sln +++ b/examples/csharp/HelloPhi/HelloPhi.sln @@ -21,8 +21,8 @@ Global {89932021-18FC-490C-8675-73F2AD1DEB2A}.Debug_DirectML|Any CPU.Build.0 = Debug_DirectML|Any CPU {89932021-18FC-490C-8675-73F2AD1DEB2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {89932021-18FC-490C-8675-73F2AD1DEB2A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release_Cuda|Any CPU.ActiveCfg = Debug|Any CPU - {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release_Cuda|Any CPU.Build.0 = Debug|Any CPU + {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release_Cuda|Any CPU.ActiveCfg = Release_Cuda|Any CPU + {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release_Cuda|Any CPU.Build.0 = Release_Cuda|Any CPU {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release_DirectML|Any CPU.ActiveCfg = Release_DirectML|Any CPU {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release_DirectML|Any CPU.Build.0 = Release_DirectML|Any CPU {89932021-18FC-490C-8675-73F2AD1DEB2A}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/nuget/Microsoft.ML.OnnxRuntimeGenAI.nuspec b/nuget/Microsoft.ML.OnnxRuntimeGenAI.nuspec deleted file mode 100644 index bb576e3b1..000000000 --- a/nuget/Microsoft.ML.OnnxRuntimeGenAI.nuspec +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - Microsoft.ML.OnnxRuntimeGenAI$genai_nuget_ext$ - $version$ - Microsoft - Microsoft - ONNX Runtime Generative AI Native Package - LICENSE - README.md - © Microsoft Corporation. All rights reserved. - https://github.com/microsoft/onnxruntime-genai/ - Introducing the ONNX Runtime GenAI Library. - ONNX;ONNX Runtime;ONNX Runtime Gen AI;Machine Learning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/nuget/generate_nuspec_for_native_nuget.py b/tools/nuget/generate_nuspec_for_native_nuget.py new file mode 100644 index 000000000..ecc8f8a31 --- /dev/null +++ b/tools/nuget/generate_nuspec_for_native_nuget.py @@ -0,0 +1,174 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import argparse +import os +from pathlib import Path + + +def get_env_var(key): + return os.environ.get(key) + +def generate_nuspec(args): + lines = [''] + lines.append("") + generate_metadata(lines, args) + generate_files(lines, args) + lines.append("") + return lines + +def generate_metadata(line_list, args): + tags = "ONNX;ONNX Runtime;ONNX Runtime Gen AI;Machine Learning" + + metadata_list = [""] + generate_id(metadata_list, args.package_name) + generate_version(metadata_list, args.package_version) + generate_authors(metadata_list, "Microsoft") + generate_owners(metadata_list, "Microsoft") + generate_description(metadata_list, args.package_name) + generate_license(metadata_list) + generate_readme(metadata_list) + generate_copyright(metadata_list, "\xc2\xa9 " + "Microsoft Corporation. All rights reserved.") + generate_project_url(metadata_list, "https://github.com/microsoft/onnxruntime-genai") + generate_release_notes(metadata_list) + generate_tags(metadata_list, tags) + generate_dependencies(metadata_list, args.package_version, args.ort_package_name, args.ort_package_version) + metadata_list.append("") + + line_list += metadata_list + +def generate_id(line_list, package_name): + line_list.append("" + package_name + "") + + +def generate_version(line_list, package_version): + line_list.append("" + package_version + "") + + +def generate_authors(line_list, authors): + line_list.append("" + authors + "") + + +def generate_owners(line_list, owners): + line_list.append("" + owners + "") + + +def generate_description(line_list, package_name): + description = "ONNX Runtime Generative AI Native Package" + line_list.append("" + description + "") + + +def generate_copyright(line_list, copyright): + line_list.append("" + copyright + "") + + +def generate_tags(line_list, tags): + line_list.append("" + tags + "") + + +def generate_icon(line_list, icon_file): + line_list.append("" + icon_file + "") + + +def generate_license(line_list): + line_list.append('LICENSE') + +def generate_readme(line_list): + line_list.append('README.md') + +def generate_project_url(line_list, project_url): + line_list.append("" + project_url + "") + + +def generate_repo_url(line_list, repo_url, commit_id): + line_list.append('') + +def generate_release_notes(line_list): + line_list.append("") + line_list.append("Release Def:") + + branch = get_env_var("BUILD_SOURCEBRANCH") + line_list.append("\t" + "Branch: " + (branch if branch is not None else "")) + + version = get_env_var("BUILD_SOURCEVERSION") + line_list.append("\t" + "Commit: " + (version if version is not None else "")) + + line_list.append("") + +def generate_dependencies(xml_text, package_version, ort_package_name, ort_package_version): + xml_text.append("") + target_frameworks = ["NETSTANDARD" , "NETCOREAPP", "NETFRAMEWORK"] + for framework in target_frameworks: + xml_text.append(f'') + xml_text.append(f'') + xml_text.append(f'') + xml_text.append("") + + xml_text.append("") + +def generate_files(lines, args): + lines.append('') + + lines.append(f'') + lines.append(f'') + lines.append(f'') + + def add_native_artifact_if_exists(xml_lines, runtime, artifact): + p = Path(f"{args.sources_path}/{args.native_build_path}/{runtime}/{args.build_config}/{artifact}") + if p.exists(): + xml_lines.append( + f'' + ) + + runtimes = ["win-x64", "win-arm64", "linux-x64"] + for runtime in runtimes: + if runtime.startswith("win"): + add_native_artifact_if_exists(lines, runtime, "onnxruntime-genai.lib") + add_native_artifact_if_exists(lines, runtime, "onnxruntime-genai.dll") + if runtime.startswith("linux"): + add_native_artifact_if_exists(lines, runtime, "libonnxruntime-genai.so") + + # targets + for dotnet in ["netstandard2.0", "net8.0", "native"]: + lines.append(f'') + lines.append(f'') + # include + + lines.append(f'') + lines.append('') + + +def parse_arguments(): + parser = argparse.ArgumentParser( + description="ONNX Runtime GenAI create nuget spec script (for hosting native shared library artifacts)", + usage="", + ) + # Main arguments + parser.add_argument("--package_name", required=True, help="ORT GenAI package name") + parser.add_argument("--package_version", required=True, help="ORT GenAI package version") + parser.add_argument("--ort_package_name", required=True, help="ORT package name") + parser.add_argument("--ort_package_version", required=True, help="ORT package version") + parser.add_argument("--sources_path", required=True, help="OnnxRuntime GenAI source code root.") + parser.add_argument("--build_config", required=True, help="Eg: RelWithDebInfo") + parser.add_argument("--native_build_path", required=True, help="Native build output directory.") + parser.add_argument("--nuspec_output_path", required=True, type=str, help="nuget spec output path.") + return parser.parse_args() + +def main(): + args = parse_arguments() + print(args) + # Generate nuspec + lines = generate_nuspec(args) + + # Create the nuspec needed to generate the Nuget + print(f"nuspec_output_path: {args.nuspec_output_path}") + with open(args.nuspec_output_path, "w") as f: + for line in lines: + # Uncomment the printing of the line if you need to debug what's produced on a CI machine + # print(line) + f.write(line) + f.write("\n") + + +if __name__ == '__main__': + main()