diff --git a/.github/workflows/linux-cpu-arm64-build.yml b/.github/workflows/linux-cpu-arm64-build.yml index 819b47e941..764d82e426 100644 --- a/.github/workflows/linux-cpu-arm64-build.yml +++ b/.github/workflows/linux-cpu-arm64-build.yml @@ -117,3 +117,29 @@ jobs: docker run --rm \ --volume $GITHUB_WORKSPACE:/onnxruntime_src \ -w /onnxruntime_src ort_genai_linux_arm64_gha bash -c "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/onnxruntime_src/ort/lib/ /onnxruntime_src/build/cpu/unit_tests" + + - name: Docker -- Build and Run the C# Tests + run: | + docker run --rm \ + --volume $GITHUB_WORKSPACE:/onnxruntime_src \ + --volume $DOTNET_INSTALL_DIR:/opt/dotnet \ + -e PATH="/opt/dotnet:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ + -e DOTNET_ROOT=/opt/dotnet \ + -e DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \ + -w /onnxruntime_src ort_genai_linux_arm64_gha bash -c " \ + export ORTGENAI_LOG_ORT_LIB=1 && \ + cd /onnxruntime_src/test/csharp && \ + dotnet test /p:Configuration=Release /p:NativeBuildOutputDir=../../build/cpu/ /p:OrtLibDir=../../ort/lib/ --verbosity normal" + + - name: Docker -- Build the C# Examples + run: | + docker run --rm \ + --volume $GITHUB_WORKSPACE:/onnxruntime_src \ + --volume $DOTNET_INSTALL_DIR:/opt/dotnet \ + -e PATH="/opt/dotnet:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ + -e DOTNET_ROOT=/opt/dotnet \ + -e DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \ + -w /onnxruntime_src ort_genai_linux_arm64_gha bash -c " \ + export ORTGENAI_LOG_ORT_LIB=1 && \ + cd /onnxruntime_src/examples/csharp/ModelChat && dotnet build -c Release && \ + cd /onnxruntime_src/examples/csharp/ModelMM && dotnet build -c Release" diff --git a/.pipelines/nuget-publishing.yml b/.pipelines/nuget-publishing.yml index ee50efbac2..a47580d877 100644 --- a/.pipelines/nuget-publishing.yml +++ b/.pipelines/nuget-publishing.yml @@ -3,8 +3,8 @@ parameters: displayName: Whether Post Packaging validation is run type: boolean default: false - - name: enable_win_cpu - displayName: 'Whether Windows CPU package is built.' + - name: enable_win_x64_cpu + displayName: 'Whether Windows x64 CPU package is built.' type: boolean default: true @@ -13,8 +13,13 @@ parameters: type: boolean default: true - - name: enable_linux_cpu - displayName: 'Whether Linux CPU package is built.' + - name: enable_linux_x64_cpu + displayName: 'Whether Linux x64 CPU package is built.' + type: boolean + default: true + + - name: enable_linux_arm64_cpu + displayName: 'Whether Linux ARM64 CPU package is built.' type: boolean default: true @@ -145,9 +150,10 @@ extends: stages: - template: stages/capi-packaging-stage.yml parameters: - enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_x64_cpu: ${{ parameters.enable_win_x64_cpu }} enable_win_cuda: ${{ parameters.enable_win_cuda }} - enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_linux_x64_cpu: ${{ parameters.enable_linux_x64_cpu }} + enable_linux_arm64_cpu: ${{ parameters.enable_linux_arm64_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} enable_win_arm64: ${{ parameters.enable_win_arm64 }} @@ -166,9 +172,10 @@ extends: - template: stages/nuget-packaging-stage.yml parameters: - enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_x64_cpu: ${{ parameters.enable_win_x64_cpu }} enable_win_cuda: ${{ parameters.enable_win_cuda }} - enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_linux_x64_cpu: ${{ parameters.enable_linux_x64_cpu }} + enable_linux_arm64_cpu: ${{ parameters.enable_linux_arm64_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} enable_win_arm64: ${{ parameters.enable_win_arm64 }} @@ -186,9 +193,10 @@ extends: - ${{ if eq(parameters.enable_post_packaging_validation, true) }}: - template: stages/nuget-validation-stage.yml parameters: - enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_x64_cpu: ${{ parameters.enable_win_x64_cpu }} enable_win_cuda: ${{ parameters.enable_win_cuda }} - enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_linux_x64_cpu: ${{ parameters.enable_linux_x64_cpu }} + enable_linux_arm64_cpu: ${{ parameters.enable_linux_arm64_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} enable_win_arm64: ${{ parameters.enable_win_arm64 }} diff --git a/.pipelines/pypl-publishing.yml b/.pipelines/pypl-publishing.yml index da7830ba85..243d00ba03 100644 --- a/.pipelines/pypl-publishing.yml +++ b/.pipelines/pypl-publishing.yml @@ -4,8 +4,8 @@ parameters: type: boolean default: false - - name: enable_win_cpu - displayName: 'Whether Windows CPU package is built.' + - name: enable_win_x64_cpu + displayName: 'Whether Windows x64 CPU package is built.' type: boolean default: true @@ -24,8 +24,13 @@ parameters: type: boolean default: true - - name: enable_linux_cpu - displayName: 'Whether Linux CPU package is built.' + - name: enable_linux_x64_cpu + displayName: 'Whether Linux x64 CPU package is built.' + type: boolean + default: true + + - name: enable_linux_arm64_cpu + displayName: 'Whether Linux ARM64 CPU package is built.' type: boolean default: true @@ -104,9 +109,10 @@ extends: stages: - template: stages/py-packaging-stage.yml parameters: - enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_linux_x64_cpu: ${{ parameters.enable_linux_x64_cpu }} + enable_linux_arm64_cpu: ${{ parameters.enable_linux_arm64_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} - enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_x64_cpu: ${{ parameters.enable_win_x64_cpu }} enable_win_cuda: ${{ parameters.enable_win_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} enable_win_arm64_cpu: ${{ parameters.enable_win_arm64_cpu }} @@ -124,9 +130,10 @@ extends: - ${{ if eq(parameters.enable_post_packaging_validation, true) }}: - template: stages/py-validation-stage.yml parameters: - enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_linux_x64_cpu: ${{ parameters.enable_linux_x64_cpu }} + enable_linux_arm64_cpu: ${{ parameters.enable_linux_arm64_cpu }} enable_linux_cuda: ${{ parameters.enable_linux_cuda }} - enable_win_cpu: ${{ parameters.enable_win_cpu }} + enable_win_x64_cpu: ${{ parameters.enable_win_x64_cpu }} enable_win_cuda: ${{ parameters.enable_win_cuda }} enable_win_dml: ${{ parameters.enable_win_dml }} enable_win_arm64_cpu: ${{ parameters.enable_win_arm64_cpu }} diff --git a/.pipelines/stages/capi-packaging-stage.yml b/.pipelines/stages/capi-packaging-stage.yml index 6724b59435..9ea8c777e4 100644 --- a/.pipelines/stages/capi-packaging-stage.yml +++ b/.pipelines/stages/capi-packaging-stage.yml @@ -1,7 +1,7 @@ parameters: - name: enable_winml type: boolean -- name: enable_win_cpu +- name: enable_win_x64_cpu type: boolean - name: enable_win_cuda type: boolean @@ -9,8 +9,11 @@ parameters: type: boolean - name: enable_win_arm64 type: boolean -- name: enable_linux_cpu +- name: enable_linux_x64_cpu type: boolean +- name: enable_linux_arm64_cpu + type: boolean + default: false - name: enable_linux_cuda type: boolean - name: enable_macos_cpu @@ -65,7 +68,7 @@ stages: ort_version: ${{ parameters.ort_winml_version }} build_config: ${{ parameters.build_config }} - - ${{ if eq(parameters.enable_win_cpu, true) }}: + - ${{ if eq(parameters.enable_win_x64_cpu, true) }}: - template: jobs/capi-packaging-job.yml parameters: arch: 'x64' @@ -77,7 +80,7 @@ stages: ort_build_version: ${{ parameters.ort_build_version }} ort_build_source: ${{ parameters.ort_build_source }} - - ${{ if and(eq(parameters.enable_win_arm64, true), eq(parameters.enable_win_cpu, true)) }}: + - ${{ if and(eq(parameters.enable_win_arm64, true), eq(parameters.enable_win_x64_cpu, true)) }}: - template: jobs/capi-packaging-job.yml parameters: arch: 'arm64' @@ -89,7 +92,7 @@ stages: ort_build_version: ${{ parameters.ort_build_version }} ort_build_source: ${{ parameters.ort_build_source }} - - ${{ if and(eq(parameters.enable_win_cpu, true), eq(parameters.enable_win_dml, true)) }}: + - ${{ if and(eq(parameters.enable_win_x64_cpu, true), eq(parameters.enable_win_dml, true)) }}: - template: jobs/capi-packaging-job.yml parameters: arch: 'x64' @@ -126,7 +129,7 @@ stages: ort_build_version: ${{ parameters.ort_build_version }} ort_build_source: ${{ parameters.ort_build_source }} - - ${{ if eq(parameters.enable_linux_cpu, true) }}: + - ${{ if eq(parameters.enable_linux_x64_cpu, true) }}: - template: jobs/capi-packaging-job.yml parameters: arch: 'x64' @@ -138,6 +141,18 @@ stages: ort_build_version: ${{ parameters.ort_build_version }} ort_build_source: ${{ parameters.ort_build_source }} + - ${{ if eq(parameters.enable_linux_arm64_cpu, true) }}: + - template: jobs/capi-packaging-job.yml + parameters: + arch: 'arm64' + ep: 'cpu' + ort_version: ${{ parameters.ort_version }} + os: 'linux' + build_config: ${{ parameters.build_config }} + enable_winml: ${{ parameters.enable_winml }} + ort_build_version: ${{ parameters.ort_build_version }} + ort_build_source: ${{ parameters.ort_build_source }} + - ${{ if eq(parameters.enable_linux_cuda, true) }}: - template: jobs/capi-packaging-job.yml parameters: diff --git a/.pipelines/stages/jobs/capi-packaging-job.yml b/.pipelines/stages/jobs/capi-packaging-job.yml index 79c7af5372..98489985eb 100644 --- a/.pipelines/stages/jobs/capi-packaging-job.yml +++ b/.pipelines/stages/jobs/capi-packaging-job.yml @@ -34,7 +34,7 @@ jobs: ${{ if eq(parameters.arch, 'x64') }}: name: 'onnxruntime-Ubuntu2204-AMD-CPU' ${{ elseif eq(parameters.arch, 'arm64') }}: - name: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' + name: 'onnxruntime-linux-ARM64-CPU-2019' hostArchitecture: 'Arm64' ${{ else }}: name: 'onnxruntime-Ubuntu2204-AMD-CPU' @@ -97,7 +97,14 @@ jobs: displayName: Copy python 3.11.0 version to agent tools directory condition: and(eq(variables['arch'], 'arm64'), eq(variables['os'], 'win')) + # UsePythonVersion is skipped on linux-arm64 because the + # 'onnxruntime-linux-ARM64-CPU-2019' self-hosted pool does not provide + # Python in the agent tools cache (no arm64 Python available from the + # GitHub Actions python-versions registry). The Linux build runs inside + # Docker, so the host's system 'python3' is sufficient for the few + # helper scripts (e.g., get_docker_image.py). - task: UsePythonVersion@0 + condition: not(and(eq(variables['os'], 'linux'), eq(variables['arch'], 'arm64'))) inputs: versionSpec: 3.11 addToPath: true diff --git a/.pipelines/stages/jobs/custom-nuget-packaging-job.yml b/.pipelines/stages/jobs/custom-nuget-packaging-job.yml index 34a3f2d19f..a32d80f3ed 100644 --- a/.pipelines/stages/jobs/custom-nuget-packaging-job.yml +++ b/.pipelines/stages/jobs/custom-nuget-packaging-job.yml @@ -38,6 +38,12 @@ jobs: ArtifactName: onnxruntime-genai-linux-cuda-x64-capi TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + - template: steps/utils/flex-download-pipeline-artifact.yml + parameters: + StepName: 'Download linux-cpu-arm64 capi Artifacts' + ArtifactName: onnxruntime-genai-linux-cpu-arm64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + - checkout: self path: onnxruntime-genai clean: true @@ -67,6 +73,8 @@ jobs: $rid = "win-arm64" } elseif ($a -like "*osx-arm64*") { $rid = "osx-arm64" + } elseif ($a -like "*linux-arm64*") { + $rid = "linux-arm64" } elseif ($a -like "*linux-x64*") { $rid = "linux-x64" } else { @@ -113,11 +121,13 @@ jobs: $win_arm64_artifact_path = (Get-ChildItem -Path '$(Build.BinariesDirectory)/artifact-downloads/win-arm64/')[0].FullName $osx_arm64_artifact_path = (Get-ChildItem -Path '$(Build.BinariesDirectory)/artifact-downloads/osx-arm64/')[0].FullName $linux_x64_artifact_path = (Get-ChildItem -Path '$(Build.BinariesDirectory)/artifact-downloads/linux-x64/')[0].FullName + $linux_arm64_artifact_path = (Get-ChildItem -Path '$(Build.BinariesDirectory)/artifact-downloads/linux-arm64/')[0].FullName Write-Host "Win x64 artifact path " $win_x64_artifact_path Write-Host "Win arm64 artifact path " $win_arm64_artifact_path Write-Host "OSX arm64 artifact path " $osx_arm64_artifact_path Write-Host "Linux x64 artifact path " $linux_x64_artifact_path + Write-Host "Linux arm64 artifact path " $linux_arm64_artifact_path $ort_package_version = $versioned_name.Substring($ort_nuget_package_name.Length + 1, $versioned_name.Length - $ort_nuget_package_name.Length - 1 - ".nupkg".Length) python.exe $(Build.Repository.LocalPath)\tools\nuget\generate_nuspec_for_custom_nuget.py ` --package_name $genai_nuget_package_name ` @@ -130,6 +140,7 @@ jobs: --win_arm64 $win_arm64_artifact_path ` --osx_arm64 $osx_arm64_artifact_path ` --linux_x64 $linux_x64_artifact_path ` + --linux_arm64 $linux_arm64_artifact_path ` --commit_id $(Build.SourceVersion) cat $(Build.Repository.LocalPath)\nuget\$genai_nuget_package_name.nuspec diff --git a/.pipelines/stages/jobs/nuget-packaging-job.yml b/.pipelines/stages/jobs/nuget-packaging-job.yml index 41b9a47e74..b0f9d2b468 100644 --- a/.pipelines/stages/jobs/nuget-packaging-job.yml +++ b/.pipelines/stages/jobs/nuget-packaging-job.yml @@ -2,8 +2,8 @@ parameters: - name: ep type: string -- name: enable_win_cpu - displayName: 'Whether Windows CPU package is built.' +- name: enable_win_x64_cpu + displayName: 'Whether Windows x64 CPU package is built.' type: boolean default: false @@ -12,8 +12,13 @@ parameters: type: boolean default: false -- name: enable_linux_cpu - displayName: 'Whether Linux CPU package is built.' +- name: enable_linux_x64_cpu + displayName: 'Whether Linux x64 CPU package is built.' + type: boolean + default: false + +- name: enable_linux_arm64_cpu + displayName: 'Whether Linux ARM64 CPU package is built.' type: boolean default: false @@ -125,7 +130,7 @@ jobs: ArtifactName: onnxruntime-genai-win-winml-arm64-capi TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' - - ${{ if and(eq(parameters.enable_win_cpu, true), eq(parameters.ep, 'cpu')) }}: + - ${{ if and(eq(parameters.enable_win_x64_cpu, true), eq(parameters.ep, 'cpu')) }}: - template: steps/utils/flex-download-pipeline-artifact.yml parameters: StepName: 'Download win-cpu-x64 capi Artifacts' @@ -160,13 +165,20 @@ jobs: ArtifactName: onnxruntime-genai-win-directml-arm64-capi TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' - - ${{ if and(eq(parameters.enable_linux_cpu, true), eq(parameters.ep, 'cpu')) }}: + - ${{ if and(eq(parameters.enable_linux_x64_cpu, true), eq(parameters.ep, 'cpu')) }}: - template: steps/utils/flex-download-pipeline-artifact.yml parameters: StepName: 'Download linux-cpu-x64 capi Artifacts' ArtifactName: onnxruntime-genai-linux-cpu-x64-capi TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + - ${{ if and(eq(parameters.enable_linux_arm64_cpu, true), eq(parameters.ep, 'cpu')) }}: + - template: steps/utils/flex-download-pipeline-artifact.yml + parameters: + StepName: 'Download linux-cpu-arm64 capi Artifacts' + ArtifactName: onnxruntime-genai-linux-cpu-arm64-capi + TargetPath: '$(Build.BinariesDirectory)/artifact-downloads' + - ${{ if and(eq(parameters.enable_linux_cuda, true), eq(parameters.ep, 'cuda')) }}: - template: steps/utils/flex-download-pipeline-artifact.yml parameters: @@ -253,6 +265,8 @@ jobs: $rid = "win-arm64" } elseif ($a -like "*linux-x64*") { $rid = "linux-x64" + } elseif ($a -like "*linux-arm64*") { + $rid = "linux-arm64" } elseif ($a -like "*osx-arm64*") { $rid = "osx-arm64" } elseif ($a -like "*android*") { @@ -260,8 +274,7 @@ jobs: } elseif ($a -like "*ios*") { $rid = "ios" } else { - Write-Host "Unknown artifact name" $a - return + throw "Unknown artifact name $a" } mkdir -Force $outputDir/$rid @@ -290,6 +303,20 @@ jobs: Get-ChildItem -Path $outputDir/$rid -Recurse } + # Verify all enabled RIDs produced the expected native library. + $expected = @{} + if ('${{ parameters.enable_win_x64_cpu }}' -eq 'True') { $expected['win-x64'] = 'onnxruntime-genai.dll' } + if ('${{ parameters.enable_win_arm64 }}' -eq 'True') { $expected['win-arm64'] = 'onnxruntime-genai.dll' } + if ('${{ parameters.enable_linux_x64_cpu }}' -eq 'True') { $expected['linux-x64'] = 'libonnxruntime-genai.so' } + if ('${{ parameters.enable_linux_arm64_cpu }}' -eq 'True'){ $expected['linux-arm64']= 'libonnxruntime-genai.so' } + if ('${{ parameters.enable_macos_cpu }}' -eq 'True') { $expected['osx-arm64'] = 'libonnxruntime-genai.dylib' } + foreach ($rid in $expected.Keys) { + $lib = "$outputDir/$rid/$(buildConfig)/$($expected[$rid])" + if (-not (Test-Path $lib)) { + throw "Expected native library missing for enabled RID '$rid': $lib" + } + } + displayName: 'Extract Artifacts & Prepare Native Libraries' workingDirectory: '$(Build.BinariesDirectory)/artifact-downloads' diff --git a/.pipelines/stages/jobs/py-packaging-job.yml b/.pipelines/stages/jobs/py-packaging-job.yml index 2532dfe63d..e2b1e50719 100644 --- a/.pipelines/stages/jobs/py-packaging-job.yml +++ b/.pipelines/stages/jobs/py-packaging-job.yml @@ -45,7 +45,8 @@ jobs: ${{ if eq(parameters.arch, 'x64') }}: name: 'onnxruntime-Ubuntu2204-AMD-CPU' ${{ elseif eq(parameters.arch, 'arm64') }}: - name: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' + name: 'onnxruntime-linux-ARM64-CPU-2019' + hostArchitecture: 'Arm64' ${{ else }}: name: 'nnxruntime-Ubuntu2204-AMD-CPU' os: linux @@ -153,12 +154,20 @@ jobs: displayName: Copy python 3.11.0 version to agent tools directory condition: and(eq(variables['arch'], 'arm64'), eq(variables['os'], 'win'), eq(variables['PyDotVer'], '3.11')) + # UsePythonVersion is skipped on linux-arm64. The + # 'onnxruntime-linux-ARM64-CPU-2019' self-hosted pool does not provide + # Python in the agent tools cache (no arm64 Python is published in the + # GitHub Actions python-versions registry). The Linux wheel build runs + # inside the manylinux aarch64 Docker image, which supplies its own + # /opt/python/cp3XX-cp3XX interpreters, so no host Python is required. - task: UsePythonVersion@0 + condition: not(and(eq(variables['os'], 'linux'), eq(variables['arch'], 'arm64'))) inputs: versionSpec: $(PyDotVer) addToPath: true architecture: $(arch) - task: PythonScript@0 + condition: not(and(eq(variables['os'], 'linux'), eq(variables['arch'], 'arm64'))) inputs: scriptSource: inline script: | diff --git a/.pipelines/stages/jobs/py-validation-job.yml b/.pipelines/stages/jobs/py-validation-job.yml index 5cc8d9c958..82840a2a20 100644 --- a/.pipelines/stages/jobs/py-validation-job.yml +++ b/.pipelines/stages/jobs/py-validation-job.yml @@ -30,7 +30,9 @@ jobs: ${{ if eq(parameters.ep, 'cuda') }}: pool: 'Onnxruntime-Linux-GPU' ${{ elseif eq(parameters.arch, 'arm64') }}: - pool: 'onnxruntime-genai-Ubuntu2004-ARM-CPU' + pool: + name: 'onnxruntime-linux-ARM64-CPU-2019' + hostArchitecture: 'Arm64' ${{ else }}: pool: 'onnxruntime-Ubuntu2204-AMD-CPU' ${{ if eq(parameters.os, 'win') }}: @@ -155,7 +157,14 @@ jobs: displayName: Copy python 3.11.0 version to agent tools directory condition: and(eq(variables['arch'], 'arm64'), eq(variables['os'], 'win'), eq(variables['py_dot_ver'], '3.11')) + # UsePythonVersion is skipped on linux-arm64. The + # 'onnxruntime-linux-ARM64-CPU-2019' self-hosted pool does not provide + # Python in the agent tools cache (no arm64 Python is published in the + # GitHub Actions python-versions registry). Validation steps below run + # inside the manylinux aarch64 Docker image or use the agent's system + # python3, so no host Python install is required. - task: UsePythonVersion@0 + condition: not(and(eq(variables['os'], 'linux'), eq(variables['arch'], 'arm64'))) inputs: versionSpec: $(py_dot_ver) addToPath: true diff --git a/.pipelines/stages/jobs/steps/capi-linux-step.yml b/.pipelines/stages/jobs/steps/capi-linux-step.yml index 17d1a74809..b5091e54c9 100644 --- a/.pipelines/stages/jobs/steps/capi-linux-step.yml +++ b/.pipelines/stages/jobs/steps/capi-linux-step.yml @@ -64,7 +64,12 @@ steps: - bash: | set -e -x python3 -m pip install requests - python3 tools/ci_build/get_docker_image.py --dockerfile tools/ci_build/github/linux/docker/manylinux/Dockerfile.manylinux2_28_$(ep) \ + if [ "$(arch)" = "arm64" ]; then + dockerfile="tools/ci_build/github/linux/docker/manylinux/Dockerfile.manylinux2_28_$(ep)_aarch64" + else + dockerfile="tools/ci_build/github/linux/docker/manylinux/Dockerfile.manylinux2_28_$(ep)" + fi + python3 tools/ci_build/get_docker_image.py --dockerfile "$dockerfile" \ --context tools/ci_build/github/linux/docker/manylinux \ --docker-build-args "--build-arg BUILD_UID=$( id -u )" \ --container-registry onnxruntimebuildcache \ diff --git a/.pipelines/stages/nuget-packaging-stage.yml b/.pipelines/stages/nuget-packaging-stage.yml index 5dac68c7c3..c44f32243e 100644 --- a/.pipelines/stages/nuget-packaging-stage.yml +++ b/.pipelines/stages/nuget-packaging-stage.yml @@ -1,6 +1,6 @@ parameters: -- name: enable_win_cpu - displayName: 'Whether Windows CPU package is built.' +- name: enable_win_x64_cpu + displayName: 'Whether Windows x64 CPU package is built.' type: boolean default: true @@ -9,11 +9,16 @@ parameters: type: boolean default: true -- name: enable_linux_cpu - displayName: 'Whether Linux CPU package is built.' +- name: enable_linux_x64_cpu + displayName: 'Whether Linux x64 CPU package is built.' type: boolean default: true +- name: enable_linux_arm64_cpu + displayName: 'Whether Linux ARM64 CPU package is built.' + type: boolean + default: false + - name: enable_linux_cuda displayName: 'Whether Linux CUDA package is built.' type: boolean @@ -78,14 +83,15 @@ stages: ort_winml_version: ${{ parameters.ort_winml_version }} build_config: ${{ parameters.build_config }} - - ${{ if or(eq(parameters.enable_linux_cpu, true), eq(parameters.enable_win_cpu, true), eq(parameters.enable_macos_cpu, true)) }}: + - ${{ if or(eq(parameters.enable_linux_x64_cpu, true), eq(parameters.enable_linux_arm64_cpu, true), eq(parameters.enable_win_x64_cpu, true), eq(parameters.enable_macos_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_linux_x64_cpu: ${{ parameters.enable_linux_x64_cpu }} + enable_linux_arm64_cpu: ${{ parameters.enable_linux_arm64_cpu }} + enable_win_x64_cpu: ${{ parameters.enable_win_x64_cpu }} enable_win_arm64: ${{ parameters.enable_win_arm64 }} enable_macos_cpu: ${{ parameters.enable_macos_cpu }} enable_android: ${{ parameters.enable_android }} diff --git a/.pipelines/stages/nuget-validation-stage.yml b/.pipelines/stages/nuget-validation-stage.yml index d8c8b3ca4c..34e7b036c3 100644 --- a/.pipelines/stages/nuget-validation-stage.yml +++ b/.pipelines/stages/nuget-validation-stage.yml @@ -7,7 +7,7 @@ parameters: displayName: Specific Artifact's BuildId type: string default: '0' -- name: enable_win_cpu +- name: enable_win_x64_cpu type: boolean - name: enable_win_cuda type: boolean @@ -15,8 +15,11 @@ parameters: type: boolean - name: enable_win_arm64 type: boolean -- name: enable_linux_cpu +- name: enable_linux_x64_cpu type: boolean +- name: enable_linux_arm64_cpu + type: boolean + default: false - name: enable_linux_cuda type: boolean - name: enable_macos_cpu @@ -35,7 +38,7 @@ parameters: stages: - stage: nuget_validation jobs: - - ${{ if eq(parameters.enable_win_cpu, true) }}: + - ${{ if eq(parameters.enable_win_x64_cpu, true) }}: - template: jobs/nuget-validation-job.yml parameters: arch: 'x64' @@ -86,7 +89,7 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - - ${{ if eq(parameters.enable_linux_cpu, true) }}: + - ${{ if eq(parameters.enable_linux_x64_cpu, true) }}: - template: jobs/nuget-validation-job.yml parameters: arch: 'x64' @@ -96,6 +99,16 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} + - ${{ if eq(parameters.enable_linux_arm64_cpu, true) }}: + - template: jobs/nuget-validation-job.yml + parameters: + arch: 'arm64' + ep: 'cpu' + ort_version: ${{ parameters.ort_version }} + os: 'linux' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + - ${{ if eq(parameters.enable_linux_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 fdde9231e9..3d011667c6 100644 --- a/.pipelines/stages/py-packaging-stage.yml +++ b/.pipelines/stages/py-packaging-stage.yml @@ -1,5 +1,5 @@ parameters: -- name: enable_win_cpu +- name: enable_win_x64_cpu type: boolean - name: enable_win_cuda type: boolean @@ -7,8 +7,11 @@ parameters: type: boolean - name: enable_win_arm64_cpu type: boolean -- name: enable_linux_cpu +- name: enable_linux_x64_cpu type: boolean +- name: enable_linux_arm64_cpu + type: boolean + default: false - name: enable_linux_cuda type: boolean - name: enable_macos_cpu @@ -66,7 +69,7 @@ stages: build_config: ${{ parameters.build_config }} ort_version: ${{ parameters.ort_version }} - - ${{ if eq(parameters.enable_win_cpu, true) }}: + - ${{ if eq(parameters.enable_win_x64_cpu, true) }}: - template: jobs/py-packaging-job.yml parameters: arch: 'x64' @@ -125,7 +128,7 @@ stages: ort_build_version: ${{ parameters.ort_build_version }} ort_build_source: ${{ parameters.ort_build_source }} - - ${{ if eq(parameters.enable_linux_cpu, true) }}: + - ${{ if eq(parameters.enable_linux_x64_cpu, true) }}: - template: jobs/py-packaging-job.yml parameters: arch: 'x64' @@ -136,6 +139,17 @@ stages: ort_build_version: ${{ parameters.ort_build_version }} ort_build_source: ${{ parameters.ort_build_source }} + - ${{ if eq(parameters.enable_linux_arm64_cpu, true) }}: + - template: jobs/py-packaging-job.yml + parameters: + arch: 'arm64' + ep: 'cpu' + os: 'linux' + build_config: ${{ parameters.build_config }} + ort_version: ${{ parameters.ort_version }} + ort_build_version: ${{ parameters.ort_build_version }} + ort_build_source: ${{ parameters.ort_build_source }} + - ${{ if and(eq(parameters.enable_linux_cuda, true), contains(parameters.cuda_versions, '13.0')) }}: - template: jobs/py-packaging-job.yml parameters: diff --git a/.pipelines/stages/py-validation-stage.yml b/.pipelines/stages/py-validation-stage.yml index e1bbb1168f..86ebed1dd8 100644 --- a/.pipelines/stages/py-validation-stage.yml +++ b/.pipelines/stages/py-validation-stage.yml @@ -7,7 +7,7 @@ parameters: displayName: Specific Artifact's BuildId type: string default: '0' -- name: enable_win_cpu +- name: enable_win_x64_cpu type: boolean - name: enable_win_cuda type: boolean @@ -15,8 +15,11 @@ parameters: type: boolean - name: enable_win_arm64_cpu type: boolean -- name: enable_linux_cpu +- name: enable_linux_x64_cpu type: boolean +- name: enable_linux_arm64_cpu + type: boolean + default: false - name: enable_linux_cuda type: boolean - name: enable_macos_cpu @@ -29,7 +32,7 @@ parameters: stages: - stage: python_validation jobs: - - ${{ if eq(parameters.enable_win_cpu, true) }}: + - ${{ if eq(parameters.enable_win_x64_cpu, true) }}: - template: jobs/py-validation-job.yml parameters: arch: 'x64' @@ -78,7 +81,7 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - - ${{ if eq(parameters.enable_linux_cpu, true) }}: + - ${{ if eq(parameters.enable_linux_x64_cpu, true) }}: - template: jobs/py-validation-job.yml parameters: arch: 'x64' @@ -87,6 +90,15 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} + - ${{ if eq(parameters.enable_linux_arm64_cpu, true) }}: + - template: jobs/py-validation-job.yml + parameters: + arch: 'arm64' + ep: 'cpu' + os: 'linux' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + - ${{ if and(eq(parameters.enable_linux_cuda, true), contains(parameters.cuda_versions, '13.0')) }}: - template: jobs/py-validation-job.yml parameters: diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 2bbd0d866a..d15b4b3430 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -86,10 +86,13 @@ if(BUILD_WHEEL) endif() if(MANYLINUX) + # auditwheel produces a wheel tagged with the platform (e.g. linux_x86_64 + # or linux_aarch64) — use a glob that matches all Linux platform tags so + # this target works on every supported manylinux architecture. add_custom_target(PyPackageBuild COMMAND ${PYTHON_EXECUTABLE} -m pip wheel --no-deps . COMMAND ${CMAKE_COMMAND} -E remove ${WHEEL_TARGET_NAME}/onnxruntime_genai.cpython-* - COMMAND auditwheel repair onnxruntime_genai*linux_x86_64.whl -w ${WHEEL_FILES_DIR} ${modified_exclude_list} + COMMAND auditwheel repair onnxruntime_genai*linux_*.whl -w ${WHEEL_FILES_DIR} ${modified_exclude_list} WORKING_DIRECTORY "${WHEEL_FILES_DIR}" COMMENT "Building wheel with MANYLINUX on ${WHEEL_FILES_DIR}" EXCLUDE_FROM_ALL diff --git a/tools/ci_build/github/linux/docker/manylinux/Dockerfile.manylinux2_28_cpu_aarch64 b/tools/ci_build/github/linux/docker/manylinux/Dockerfile.manylinux2_28_cpu_aarch64 new file mode 100644 index 0000000000..36373bcabc --- /dev/null +++ b/tools/ci_build/github/linux/docker/manylinux/Dockerfile.manylinux2_28_cpu_aarch64 @@ -0,0 +1,13 @@ +FROM onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cpu_aarch64_almalinux8_gcc14:20251017.1 + +ADD scripts /tmp/scripts +RUN cd /tmp/scripts && /tmp/scripts/install_centos.sh && /tmp/scripts/install_deps.sh && rm -rf /tmp/scripts +RUN yum update -y && yum install -y pkgconfig openssl-devel +ENV PATH="/usr/.cargo/bin:$PATH" +ENV RUSTUP_HOME="/usr/.rustup" +ENV CARGO_HOME="/usr/.cargo" +ARG BUILD_UID=1001 +ARG BUILD_USER=onnxruntimedev +RUN adduser --uid $BUILD_UID $BUILD_USER +WORKDIR /home/$BUILD_USER +USER $BUILD_USER diff --git a/tools/ci_build/github/linux/docker/manylinux/scripts/install_deps.sh b/tools/ci_build/github/linux/docker/manylinux/scripts/install_deps.sh index abeeadd742..f0d7eb659c 100755 --- a/tools/ci_build/github/linux/docker/manylinux/scripts/install_deps.sh +++ b/tools/ci_build/github/linux/docker/manylinux/scripts/install_deps.sh @@ -9,6 +9,10 @@ export CMAKE_ARGS="-DONNX_GEN_PB_TYPE_STUBS=OFF -DONNX_WERROR=OFF" for PYTHON_EXE in "${PYTHON_EXES[@]}" do + if [ ! -x "${PYTHON_EXE}" ]; then + echo "Skipping ${PYTHON_EXE}: not found in this base image" + continue + fi ${PYTHON_EXE} -m pip install -r requirements.txt done diff --git a/tools/nuget/generate_nuspec_for_custom_nuget.py b/tools/nuget/generate_nuspec_for_custom_nuget.py index a14ad79b4d..bf2267969e 100644 --- a/tools/nuget/generate_nuspec_for_custom_nuget.py +++ b/tools/nuget/generate_nuspec_for_custom_nuget.py @@ -15,6 +15,7 @@ def generate_files(lines, args): "win-x64": args.win_x64, "osx-arm64": args.osx_arm64, "linux-x64": args.linux_x64, + "linux-arm64": args.linux_arm64, } avoid_keywords = {"pdb", "onnxruntime-genai-cuda.dll", "onnxruntime-genai-cuda.lib"} @@ -74,6 +75,7 @@ def parse_arguments(): parser.add_argument("--win_x64", required=True, help="Ort-genai win-x64 directory") parser.add_argument("--osx_arm64", required=True, help="Ort-genai osx-arm64 directory") parser.add_argument("--linux_x64", required=True, help="Ort-genai linux-x64 directory") + parser.add_argument("--linux_arm64", required=True, help="Ort-genai linux-arm64 directory") args = parser.parse_args() args.sdk_info = "" diff --git a/tools/nuget/generate_nuspec_for_native_nuget.py b/tools/nuget/generate_nuspec_for_native_nuget.py index 92708a5910..4a0e4f8816 100644 --- a/tools/nuget/generate_nuspec_for_native_nuget.py +++ b/tools/nuget/generate_nuspec_for_native_nuget.py @@ -133,7 +133,7 @@ def add_native_artifact_if_exists(xml_lines, runtime, artifact): if p.exists(): xml_lines.append(f'') - runtimes = ["win-x64", "win-arm64", "linux-x64", "osx-arm64", "ios", "android"] + runtimes = ["win-x64", "win-arm64", "linux-x64", "linux-arm64", "osx-arm64", "ios", "android"] for runtime in runtimes: if runtime.startswith("win"): add_native_artifact_if_exists(lines, runtime, "onnxruntime-genai.lib")