Split Onnxruntime Nuget GPU package (#18819)

### Description
1. Update donwload-artifacts to flex-downloadartifacts to make it eaiser
to debug.
2. Move the native files into Gpu.Windows and Gpu-linux packages.
Onnxruntime-Gpu has dependency on them.
3. update the package validation as well
4. Add 2 stages to run E2E test for GPU.Windows and GPU.Linux
   for example:
   

![image](https://github.com/microsoft/onnxruntime/assets/16190118/35c6730b-8080-4f52-a17c-b9c61f41b6bb)



### Motivation and Context
Single Onnxruntime.Gpu Package size has already excceded the Nuget size
limit.
We split the package into some smaller packages to make them can be
published.

For compatibility, the user can install or upgrade Onnxruntime.Gpu,
which will install Gpu.Windows and Gpu.Linux automatically.
And the user can only install Gpu.Windows and Gpu.Linux directly. 

### Test Link
1. In ORT_NIGHTLY

2. Install the preview version in nuget-int. (nuget source:
https://apiint.nugettest.org/v3/index.json)

---------

Co-authored-by: Scott McKay <skottmckay@gmail.com>
This commit is contained in:
Yi Zhang 2023-12-22 16:57:16 +08:00 committed by GitHub
parent 985acda28c
commit 3f03c12986
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 295 additions and 136 deletions

View file

@ -20,6 +20,8 @@ CMake creates a target to this project
<IsWindowsBuild Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindowsBuild>
<IsLinuxBuild Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinuxBuild>
<ExecutionProvider Condition=" '$(ExecutionProvider)' == '' ">None</ExecutionProvider>
<IsPlatformSpecificSubPackage Condition=" '$(IsPlatformSpecificSubPackage)' == '' ">false</IsPlatformSpecificSubPackage>
<NuSpecName Condition=" '$(NuSpecName)' == '' ">NativeNuget.nuspec</NuSpecName>
<!-- include Xamarin/MAUI Android and iOS target frameworks? Command line property overrides this value. -->
<IncludeMobileTargets>true</IncludeMobileTargets>
@ -45,6 +47,13 @@ CMake creates a target to this project
<PythonExe>python</PythonExe>
</PropertyGroup>
<PropertyGroup>
<!-- If we create multiple nuget packages in one job, major package and dependent packages version should be the same-->
<!-- CurrentDate and CurrentTime are only used for dev packages-->
<CurrentDate Condition="'$(CurrentDate)'==''">$([System.DateTime]::UtcNow.ToString(yyyyMMdd))</CurrentDate>
<CurrentTime Condition="'$(CurrentTime)'==''">$([System.DateTime]::UtcNow.ToString(hhmm))</CurrentTime>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="Build">
@ -58,7 +67,7 @@ CMake creates a target to this project
</Exec>
</Target>
<Target Name="ObtainPackageVersion" BeforeTargets="Build;CreatePackage;CreateWindowsAIPackage">
<Target Name="ObtainPackageVersion" BeforeTargets="Build;CreatePackage;CreateWindowsAIPackage;CreateNativePackage">
<ReadLinesFromFile File="..\VERSION_NUMBER">
<Output TaskParameter="Lines" ItemName="MajorVersionNumber"/>
</ReadLinesFromFile>
@ -81,8 +90,6 @@ CMake creates a target to this project
<Output TaskParameter="AbsolutePaths" PropertyName="OnnxRuntimeSourceDirectoryAbs"/>
</ConvertToAbsolutePath>
<PropertyGroup>
<CurrentDate>$([System.DateTime]::UtcNow.ToString(yyyyMMdd))</CurrentDate>
<CurrentTime>$([System.DateTime]::UtcNow.ToString(hhmm))</CurrentTime>
<PackageVersion>@(MajorVersionNumber)</PackageVersion>
<PackageVersion>$(PackageVersion)$(ReleaseVersionSuffix)</PackageVersion>
<Version>$(PackageVersion)</Version>
@ -91,23 +98,10 @@ CMake creates a target to this project
<Message Importance="High" Text="PackageVersion=$(PackageVersion)" />
</Target>
<Target Name="CreatePackage">
<!-- Validate no missing UnmanagedFunctionPointer attributes on delegates. -->
<Exec Condition="'$(IsWindowsBuild)' == 'true' AND $(OrtPackageId) == 'Microsoft.ML.OnnxRuntime'"
Command="$(PythonExe) tools/ValidateNativeDelegateAttributes.py"
ContinueOnError="False">
<Output TaskParameter="ConsoleOutput" PropertyName="GenerateNuspecOutput" />
</Exec>
<!-- Create Microsoft.ML.OnnxRuntime.Managed with the C# bindings using the C# project -->
<Message Importance="High" Text="Creating Microsoft.ML.OnnxRuntime.Managed nuget package..." />
<MSBuild Projects="src\Microsoft.ML.OnnxRuntime\Microsoft.ML.OnnxRuntime.csproj"
Targets="CopyMiscFiles;Pack"
Properties="NoBuild=true;Platform=AnyCPU;PackageVersion=$(PackageVersion);OrtPackageId=$(OrtPackageId);IncludeMobileTargets=$(IncludeMobileTargets)"/>
<!-- Manually create the nuspec for the native Microsoft.ML.OnnxRuntime package -->
<Message Importance="High" Text="Generating nuspec for the native Microsoft.ML.OnnxRuntime nuget package..." />
<Exec Command="$(PythonExe) $(GenerateNuspecScript) --package_version $(PackageVersion) --package_name $(OrtPackageId) --target_architecture $(TargetArchitecture) --build_config $(Configuration) --native_build_path $(NativeBuildOutputDirAbs) --packages_path $(OnnxRuntimePackagesDirectoryAbs) --ort_build_path $(OnnxRuntimeBuildDirectoryAbs) --sources_path $(OnnxRuntimeSourceDirectoryAbs) --commit_id $(GitCommitHash) --is_release_build $(IsReleaseBuild) --execution_provider $(ExecutionProvider)"
<Target Name="CreateNativePackage">
<!-- Create the nuspec for the native OnnxRuntime package -->
<Message Importance="High" Text="Generating nuspec for the native $(OrtPackageId) nuget package..." />
<Exec Command="$(PythonExe) $(GenerateNuspecScript) --package_version $(PackageVersion) --package_name $(OrtPackageId) --target_architecture $(TargetArchitecture) --build_config $(Configuration) --native_build_path $(NativeBuildOutputDirAbs) --packages_path $(OnnxRuntimePackagesDirectoryAbs) --ort_build_path $(OnnxRuntimeBuildDirectoryAbs) --sources_path $(OnnxRuntimeSourceDirectoryAbs) --commit_id $(GitCommitHash) --is_release_build $(IsReleaseBuild) --execution_provider $(ExecutionProvider) --nuspec_name $(NuSpecName)"
ContinueOnError="False"
ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="GenerateNuspecOutput" />
@ -116,7 +110,7 @@ CMake creates a target to this project
<!-- run `nuget pack` on Windows or `dotnet pack` on Linux to create the native nupkg -->
<Message Importance="High" Text="Bundling native shared library artifacts into Microsoft.ML.OnnxRuntime nuget package..." />
<Exec Condition=" '$(IsWindowsBuild)' == 'true'"
Command="$(NugetExe) pack NativeNuget.nuspec"
Command="$(NugetExe) pack $(NuSpecName)"
WorkingDirectory="$(NativeBuildOutputDirAbs)"
ContinueOnError="False"
ConsoleToMSBuild="true">
@ -144,6 +138,34 @@ CMake creates a target to this project
/>
</Target>
<Target Name="CreatePackage">
<!-- Validate no missing UnmanagedFunctionPointer attributes on delegates. -->
<Exec Condition="'$(IsWindowsBuild)' == 'true' AND $(OrtPackageId) == 'Microsoft.ML.OnnxRuntime'"
Command="$(PythonExe) tools/ValidateNativeDelegateAttributes.py"
ContinueOnError="False">
<Output TaskParameter="ConsoleOutput" PropertyName="GenerateNuspecOutput" />
</Exec>
<!-- Create Microsoft.ML.OnnxRuntime.Managed with the C# bindings using the C# project -->
<Message Condition="'$(IsPlatformSpecificSubPackage)'!='True'" Importance="High" Text="Creating Microsoft.ML.OnnxRuntime.Managed nuget package..." />
<MSBuild Condition="'$(IsPlatformSpecificSubPackage)'!='True'" Projects="src\Microsoft.ML.OnnxRuntime\Microsoft.ML.OnnxRuntime.csproj"
Targets="CopyMiscFiles;Pack"
Properties="NoBuild=true;Platform=AnyCPU;PackageVersion=$(PackageVersion);OrtPackageId=$(OrtPackageId);IncludeMobileTargets=$(IncludeMobileTargets)"/>
<MSBuild Projects ="$(MSBuildProjectFullPath)"
Targets ="CreateNativePackage" />
</Target>
<Target Name="CreateAllGpuPackages" AfterTargets="CreatePackage" Condition="'$(OrtPackageId)' == 'Microsoft.ML.OnnxRuntime.Gpu'">
<MSBuild Projects ="$(MSBuildProjectFullPath)"
Properties="NuSpecName=NativeGpuWinNuget.nuspec;OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu.Windows"
Targets ="CreateNativePackage" />
<MSBuild Projects ="$(MSBuildProjectFullPath)"
Properties="NuSpecName=NativeGpuLinuxNuget.nuspec;OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu.Linux"
Targets ="CreateNativePackage" />
</Target>
<ItemGroup>
<LicenseFile Include="$(OnnxRuntimeSourceDirectory)\LICENSE"/>
</ItemGroup>

View file

@ -37,7 +37,7 @@
<PropertyGroup>
<EnginePlatform Condition="'$(Platform)' == 'Win32'">x86</EnginePlatform>
<EnginePlatform Condition="'$(Platform)' == 'ARM64'">arm64</EnginePlatform>
<EnginePlatform Condition="'$(Platform)' == 'ARM'">arm</EnginePlatform>
<EnginePlatform Condition="'$(Platform)' == 'ARM'">arm</EnginePlatform>
<EnginePlatform Condition="'$(Platform)' != 'Win32' AND '$(Platform)' != 'ARM64'">$(Platform)</EnginePlatform>
</PropertyGroup>
@ -55,7 +55,8 @@
<ItemGroup>
<!-- x64 -->
<None Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\onnxruntime.dll"
Condition="'$(PlatformTarget)' == 'x64' OR ('$(PlatformTarget)' == 'AnyCPU' AND '$(Prefer32Bit)' != 'true')">
Condition="('$(PlatformTarget)' == 'x64' OR ('$(PlatformTarget)' == 'AnyCPU' AND '$(Prefer32Bit)' != 'true')) AND
Exists('$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\onnxruntime.dll')">
<Link>onnxruntime.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
@ -146,8 +147,8 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</None>
<!-- x86 -->
<!-- x86 -->
<None Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x86\native\onnxruntime.dll"
Condition="('$(PlatformTarget)' == 'x86' OR ('$(PlatformTarget)' == 'AnyCPU' AND '$(Prefer32Bit)' == 'true'))">
<Link>onnxruntime.dll</Link>

View file

@ -52,9 +52,12 @@ IF NOT errorlevel 0 (
%dn% list test\Microsoft.ML.OnnxRuntime.EndToEndTests\Microsoft.ML.OnnxRuntime.EndToEndTests.csproj package
dir test\Microsoft.ML.OnnxRuntime.EndToEndTests\packages\
IF "%PACKAGENAME%"=="Microsoft.ML.OnnxRuntime.Gpu" (
set gpu_package=F
IF "%PACKAGENAME%"=="Microsoft.ML.OnnxRuntime.Gpu" set gpu_package=T
IF "%PACKAGENAME%"=="Microsoft.ML.OnnxRuntime.Gpu.Windows" set gpu_package=T
IF %%gpu_package%%=="T" (
set TESTONGPU=ON
%dn% test -p:DefineConstants=USE_TENSORRT test\Microsoft.ML.OnnxRuntime.EndToEndTests\Microsoft.ML.OnnxRuntime.EndToEndTests.csproj --no-restore --filter TensorRT
%dn% test -p:DefineConstants=USE_TENSORRT test\Microsoft.ML.OnnxRuntime.EndToEndTests\Microsoft.ML.OnnxRuntime.EndToEndTests.csproj --no-restore --filter TensorRT
IF NOT errorlevel 0 (
@echo "Failed to build or execute the end-to-end test"

View file

@ -32,7 +32,7 @@ if [ $RunTestCsharp = "true" ]; then
exit 1
fi
if [ $PACKAGENAME = "Microsoft.ML.OnnxRuntime.Gpu" ]; then
if [ $PACKAGENAME = "Microsoft.ML.OnnxRuntime.Gpu" ] || [ $PACKAGENAME = "Microsoft.ML.OnnxRuntime.Gpu.Linux" ]; then
export TESTONGPU=ON
dotnet test -p:DefineConstants=USE_CUDA $BUILD_SOURCESDIRECTORY/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj --no-restore --verbosity detailed
if [ $? -ne 0 ]; then

View file

@ -708,39 +708,52 @@ stages:
variables:
breakCodesignValidationInjection: ${{ parameters.DoEsrp }}
ReleaseVersionSuffix: $[stageDependencies.Setup.Set_Variables.outputs['Set_Release_Version_Suffix.ReleaseVersionSuffix']]
BuildDate: $[format('{0:yyyyMMdd}', pipeline.startTime)]
BuildTime: $[format('{0:HHmm}', pipeline.startTime)]
steps:
- checkout: self
submodules: true
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact - NuGet'
inputs:
artifactName: 'onnxruntime-win-x64-cuda'
targetPath: '$(Build.BinariesDirectory)/nuget-artifact'
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact - NuGet'
inputs:
artifactName: 'onnxruntime-win-x64-tensorrt'
targetPath: '$(Build.BinariesDirectory)/nuget-artifact'
- template: templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact - NuGet'
ArtifactName: 'onnxruntime-win-x64-cuda'
TargetPath: '$(Build.BinariesDirectory)/nuget-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact - NuGet'
inputs:
artifactName: 'onnxruntime-linux-x64-cuda'
targetPath: '$(Build.BinariesDirectory)/nuget-artifact'
- template: templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact - NuGet'
ArtifactName: 'onnxruntime-win-x64-tensorrt'
TargetPath: '$(Build.BinariesDirectory)/nuget-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact - NuGet'
inputs:
artifactName: 'onnxruntime-linux-x64-tensorrt'
targetPath: '$(Build.BinariesDirectory)/nuget-artifact'
- template: templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact - NuGet'
ArtifactName: 'onnxruntime-linux-x64-cuda'
TargetPath: '$(Build.BinariesDirectory)/nuget-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact - NuGet'
inputs:
artifactName: 'drop-extra'
targetPath: '$(Build.BinariesDirectory)/extra-artifact'
- template: templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact - NuGet'
ArtifactName: 'onnxruntime-linux-x64-tensorrt'
TargetPath: '$(Build.BinariesDirectory)/nuget-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact - NuGet'
ArtifactName: 'drop-extra'
TargetPath: '$(Build.BinariesDirectory)/extra-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
# Reconstruct the build dir
- task: PowerShell@2
@ -797,12 +810,13 @@ stages:
DoEsrp: ${{ parameters.DoEsrp }}
- task: MSBuild@1
displayName: 'Build Nuget Packages'
displayName: 'Build Nuget Packages Microsoft.ML.OnnxRuntime.Gpu'
inputs:
solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj'
configuration: RelWithDebInfo
platform: 'Any CPU'
msbuildArguments: '-t:CreatePackage -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} -p:ReleaseVersionSuffix=$(ReleaseVersionSuffix)'
msbuildArguments: '-t:CreatePackage -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }}
-p:ReleaseVersionSuffix=$(ReleaseVersionSuffix) -p:CurrentDate=$(BuildDate) -p:CurrentTime=$(BuildTime)'
workingDirectory: '$(Build.SourcesDirectory)\csharp'
- task: BatchScript@1
@ -842,8 +856,25 @@ stages:
parameters:
PackageType: 'nuget'
PackagePath: '$(Build.ArtifactStagingDirectory)'
PackageName: 'Microsoft.ML.OnnxRuntime.*nupkg'
PlatformsSupported: 'win-x64,linux-x64'
# 1* stands for version number. we use it to fileter Gpu.Windows and Gpu.Linux packages
PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.1*nupkg'
VerifyNugetSigning: false
- template: templates/validate-package.yml
parameters:
PackageType: 'nuget'
PackagePath: '$(Build.ArtifactStagingDirectory)'
PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Windows.*nupkg'
PlatformsSupported: 'win-x64'
VerifyNugetSigning: false
- template: templates/validate-package.yml
parameters:
PackageType: 'nuget'
PackagePath: '$(Build.ArtifactStagingDirectory)'
PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Linux.*nupkg'
PlatformsSupported: 'linux-x64'
VerifyNugetSigning: false
- task: PublishPipelineArtifact@0
@ -1104,6 +1135,19 @@ stages:
ArtifactSuffix: 'GPU'
StageSuffix: 'GPU'
Skipx86Tests: 'true'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: nuget/templates/test_win.yml
parameters:
AgentPool : 'onnxruntime-Win2022-GPU-T4'
NugetPackageName : 'Microsoft.ML.OnnxRuntime.Gpu.Windows'
ArtifactSuffix: 'GPU'
StageSuffix: 'GPU'
MoreSuffix: '_Windows'
Skipx86Tests: 'true'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: nuget/templates/test_linux.yml
parameters:
@ -1114,6 +1158,16 @@ stages:
SpecificArtifact: ${{ parameters.specificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: nuget/templates/test_linux.yml
parameters:
AgentPool : Onnxruntime-Linux-GPU
ArtifactSuffix: 'GPU'
StageSuffix: 'GPU'
MoreSuffix: '_Linux'
NugetPackageName : 'Microsoft.ML.OnnxRuntime.Gpu.Linux'
SpecificArtifact: ${{ parameters.specificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: nuget/templates/test_linux.yml
parameters:
AgentPool: AMD-GPU
@ -1321,4 +1375,4 @@ stages:
displayName: 'Publish Pipeline NuGet Artifact'
inputs:
artifactName: 'drop-signed-nuget-dml'
targetPath: '$(Build.ArtifactStagingDirectory)'
targetPath: '$(Build.ArtifactStagingDirectory)'

View file

@ -160,6 +160,8 @@ stages:
StageSuffix: 'GPU'
Skipx86Tests: 'true'
CudaVersion: ${{ parameters.CudaVersion }}
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
## Linux GPU Testing
- template: nuget/templates/test_linux.yml
parameters:

View file

@ -3,13 +3,14 @@ parameters:
ArtifactSuffix: ''
NugetPackageName : ''
StageSuffix: 'CPU'
MoreSuffix: ''
NativePackagePrefix: 'onnxruntime'
SpecificArtifact: false
CustomOpArtifactName: 'onnxruntime-linux-x64'
BuildId: '0'
CudaVersion: '11.8'
stages:
- stage: NuGet_Test_Linux_${{ parameters.StageSuffix }}
- stage: NuGet_Test_Linux_${{ parameters.StageSuffix }}${{ parameters.MoreSuffix }}
dependsOn:
- NuGet_Packaging_${{ parameters.StageSuffix }}
condition: succeeded()

View file

@ -3,15 +3,19 @@ parameters:
NugetPackageName : ''
ArtifactSuffix: ''
StageSuffix: 'CPU'
# More Suffix is used to differentiate testing for GPU and GPU-Windows/GPU-Linux packages
MoreSuffix: ''
# For inference packages, the test data artifact name is drop-extra and no suffix is required.
# For training packages, to differentiate the artifact name we add '-training' suffix. This needs to be passed from
# the parent pipeline.
TestDataArtifactSuffix: ''
Skipx86Tests: 'false'
CudaVersion: ''
SpecificArtifact: false
BuildId: ''
stages:
- stage: NuGet_Test_Win_${{ parameters.StageSuffix }}
- stage: NuGet_Test_Win_${{ parameters.StageSuffix }}${{ parameters.MoreSuffix }}
dependsOn:
- NuGet_Packaging_${{ parameters.StageSuffix }}
condition: succeeded()
@ -58,11 +62,13 @@ stages:
arguments: 'amd64'
modifyEnvironment: true
- task: DownloadPipelineArtifact@0
displayName: 'Download Pipeline Artifact'
inputs:
artifactName: drop-signed-nuget-${{ parameters.ArtifactSuffix }}
targetPath: '$(Build.BinariesDirectory)\nuget-artifact'
- template: ../../templates/flex-downloadPipelineArtifact.yml
parameters:
StepName: 'Download Pipeline Artifact'
ArtifactName: drop-signed-nuget-${{ parameters.ArtifactSuffix }}
TargetPath: '$(Build.BinariesDirectory)\nuget-artifact'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: get-nuget-package-version-as-variable.yml
parameters:

View file

@ -779,6 +779,8 @@ stages:
Skipx86Tests : false
NugetPackageName : 'Microsoft.ML.OnnxRuntime'
ArtifactSuffix: 'CPU'
SpecificArtifact: ${{ parameters.SpecificArtifact }}
BuildId: ${{ parameters.BuildId }}
- template: ../nuget/templates/test_linux.yml
parameters:

View file

@ -39,7 +39,11 @@ def get_package_name(os, cpu_arch, ep, is_training_package):
# Currently we take onnxruntime_providers_cuda from CUDA build
# And onnxruntime, onnxruntime_providers_shared and
# onnxruntime_providers_tensorrt from tensorrt build
def is_this_file_needed(ep, filename):
# cuda binaries are split out into the platform dependent packages Microsoft.ML.OnnxRuntime.{Linux|Windows}
# and not included in the base Microsoft.ML.OnnxRuntime.Gpu package
def is_this_file_needed(ep, filename, package_name):
if package_name == "Microsoft.ML.OnnxRuntime.Gpu":
return False
return (ep != "cuda" or "cuda" in filename) and (ep != "tensorrt" or "cuda" not in filename)
@ -47,7 +51,7 @@ def is_this_file_needed(ep, filename):
# ep: cuda, tensorrt, None
# files_list: a list of xml string pieces to append
# This function has no return value. It updates files_list directly
def generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs, is_training_package):
def generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs, is_training_package, package_name):
for child in nuget_artifacts_dir.iterdir():
if not child.is_dir():
continue
@ -57,7 +61,11 @@ def generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs,
child = child / "lib" # noqa: PLW2901
for child_file in child.iterdir():
suffixes = [".dll", ".lib", ".pdb"] if include_pdbs else [".dll", ".lib"]
if child_file.suffix in suffixes and is_this_file_needed(ep, child_file.name):
if (
child_file.suffix in suffixes
and is_this_file_needed(ep, child_file.name, package_name)
and package_name != "Microsoft.ML.OnnxRuntime.Gpu.Linux"
):
files_list.append(
'<file src="' + str(child_file) + '" target="runtimes/win-%s/native"/>' % cpu_arch
)
@ -83,7 +91,11 @@ def generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs,
for child_file in child.iterdir():
if not child_file.is_file():
continue
if child_file.suffix == ".so" and is_this_file_needed(ep, child_file.name):
if (
child_file.suffix == ".so"
and is_this_file_needed(ep, child_file.name, package_name)
and package_name != "Microsoft.ML.OnnxRuntime.Gpu.Windows"
):
files_list.append(
'<file src="' + str(child_file) + '" target="runtimes/linux-%s/native"/>' % cpu_arch
)
@ -128,6 +140,9 @@ def parse_arguments():
help="The selected execution provider for this build.",
)
parser.add_argument("--sdk_info", required=False, default="", type=str, help="dependency SDK information.")
parser.add_argument(
"--nuspec_name", required=False, default="NativeNuget.nuspec", type=str, help="nuget spec name."
)
return parser.parse_args()
@ -161,11 +176,14 @@ def generate_description(line_list, package_name):
+ "See https://github.com/microsoft/onnxruntime-training-examples/tree/master/on_device_training for "
+ "more details."
)
elif "Microsoft.ML.OnnxRuntime.Gpu.Linux" in package_name:
description = "This package contains Linux native shared library artifacts for ONNX Runtime with CUDA."
elif "Microsoft.ML.OnnxRuntime.Gpu.Windows" in package_name:
description = "This package contains Windows native shared library artifacts for ONNX Runtime with CUDA."
elif "Microsoft.ML.OnnxRuntime" in package_name: # This is a Microsoft.ML.OnnxRuntime.* package
description = (
"This package contains native shared library artifacts for all supported platforms of ONNX Runtime."
)
line_list.append("<description>" + description + "</description>")
@ -193,6 +211,13 @@ def generate_repo_url(line_list, repo_url, commit_id):
line_list.append('<repository type="git" url="' + repo_url + '"' + ' commit="' + commit_id + '" />')
def add_common_dependencies(xml_text, package_name, version):
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
if package_name == "Microsoft.ML.OnnxRuntime.Gpu":
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Gpu.Windows"' + ' version="' + version + '"/>')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Gpu.Linux"' + ' version="' + version + '"/>')
def generate_dependencies(xml_text, package_name, version):
dml_dependency = '<dependency id="Microsoft.AI.DirectML" version="1.12.1"/>'
@ -215,21 +240,22 @@ def generate_dependencies(xml_text, package_name, version):
include_dml = package_name == "Microsoft.ML.OnnxRuntime.DirectML"
xml_text.append("<dependencies>")
# Support .Net Core
xml_text.append('<group targetFramework="NETCOREAPP">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
add_common_dependencies(xml_text, package_name, version)
if include_dml:
xml_text.append(dml_dependency)
xml_text.append("</group>")
# Support .Net Standard
xml_text.append('<group targetFramework="NETSTANDARD">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
add_common_dependencies(xml_text, package_name, version)
if include_dml:
xml_text.append(dml_dependency)
xml_text.append("</group>")
# Support .Net Framework
xml_text.append('<group targetFramework="NETFRAMEWORK">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
add_common_dependencies(xml_text, package_name, version)
if include_dml:
xml_text.append(dml_dependency)
xml_text.append("</group>")
@ -324,6 +350,8 @@ def generate_files(line_list, args):
]
is_mklml_package = args.package_name == "Microsoft.ML.OnnxRuntime.MKLML"
is_cuda_gpu_package = args.package_name == "Microsoft.ML.OnnxRuntime.Gpu"
is_cuda_gpu_win_sub_package = args.package_name == "Microsoft.ML.OnnxRuntime.Gpu.Windows"
is_cuda_gpu_linux_sub_package = args.package_name == "Microsoft.ML.OnnxRuntime.Gpu.Linux"
is_rocm_gpu_package = args.package_name == "Microsoft.ML.OnnxRuntime.ROCm"
is_dml_package = args.package_name == "Microsoft.ML.OnnxRuntime.DirectML"
is_windowsai_package = args.package_name == "Microsoft.AI.MachineLearning"
@ -389,24 +417,35 @@ def generate_files(line_list, args):
runtimes = f'{runtimes_target}{args.target_architecture}\\{runtimes_native_folder}"'
# Process headers
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\session\\onnxruntime_*.h")
+ '" target="build\\native\\include" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\framework\\provider_options.h")
+ '" target="build\\native\\include" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\providers\\cpu\\cpu_provider_factory.h")
+ '" target="build\\native\\include" />'
)
build_dir = "buildTransitive" if "Gpu" in args.package_name else "build"
include_dir = f"{build_dir}\\native\\include"
# Sub.Gpu packages do not include the onnxruntime headers
if args.package_name != "Microsoft.ML.OnnxRuntime.Gpu":
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\session\\onnxruntime_*.h")
+ '" target="'
+ include_dir
+ '" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\framework\\provider_options.h")
+ '" target="'
+ include_dir
+ '" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\providers\\cpu\\cpu_provider_factory.h")
+ '" target="'
+ include_dir
+ '" />'
)
if is_training_package:
files_list.append(
@ -531,37 +570,42 @@ def generate_files(line_list, args):
if nuget_artifacts_dir.exists():
# Code path for ADO build pipeline, the files under 'nuget-artifacts' are
# downloaded from other build jobs
if is_cuda_gpu_package:
if is_cuda_gpu_package or is_cuda_gpu_win_sub_package or is_cuda_gpu_linux_sub_package:
ep_list = ["tensorrt", "cuda", None]
elif is_rocm_gpu_package:
ep_list = ["rocm", None]
else:
ep_list = [None]
for ep in ep_list:
generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs, is_training_package)
generate_file_list_for_ep(
nuget_artifacts_dir, ep, files_list, include_pdbs, is_training_package, args.package_name
)
is_ado_packaging_build = True
else:
# Code path for local dev build
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime.lib") + runtimes + " />"
)
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime.dll") + runtimes + " />"
)
if include_pdbs and os.path.exists(os.path.join(args.native_build_path, "onnxruntime.pdb")):
# for local dev build, gpu linux package is also generated for compatibility though it is not used
if not is_cuda_gpu_linux_sub_package:
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime.pdb") + runtimes + " />"
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime.lib") + runtimes + " />"
)
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime.dll") + runtimes + " />"
)
if include_pdbs and os.path.exists(os.path.join(args.native_build_path, "onnxruntime.pdb")):
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime.pdb") + runtimes + " />"
)
else:
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, "libonnxruntime.so")
+ '" target="runtimes\\linux-'
+ args.target_architecture
+ '\\native" />'
)
ort_so = os.path.join(args.native_build_path, "libonnxruntime.so")
if os.path.exists(ort_so):
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, "libonnxruntime.so")
+ '" target="runtimes\\linux-'
+ args.target_architecture
+ '\\native" />'
)
if includes_winml:
# Process microsoft.ai.machinelearning import lib, dll, and pdb
@ -732,7 +776,7 @@ def generate_files(line_list, args):
+ '\\native" />'
)
if args.execution_provider == "cuda" or is_cuda_gpu_package and not is_ado_packaging_build:
if args.execution_provider == "cuda" or is_cuda_gpu_win_sub_package and not is_ado_packaging_build:
files_list.append(
"<file src="
+ '"'
@ -838,7 +882,7 @@ def generate_files(line_list, args):
windowsai_rules = "Microsoft.AI.MachineLearning.Rules.Project.xml"
windowsai_native_rules = os.path.join(args.sources_path, "csharp", "src", windowsai_src, windowsai_rules)
windowsai_native_targets = os.path.join(args.sources_path, "csharp", "src", windowsai_src, windowsai_targets)
build = "build\\native"
build = f"{build_dir}\\native"
files_list.append("<file src=" + '"' + windowsai_native_props + '" target="' + build + '" />')
# Process native targets
files_list.append("<file src=" + '"' + windowsai_native_targets + '" target="' + build + '" />')
@ -857,6 +901,8 @@ def generate_files(line_list, args):
if (
is_cpu_package
or is_cuda_gpu_package
or is_cuda_gpu_linux_sub_package
or is_cuda_gpu_win_sub_package
or is_rocm_gpu_package
or is_dml_package
or is_mklml_package
@ -877,9 +923,10 @@ def generate_files(line_list, args):
args.package_name + ".props",
)
os.system(copy_command + " " + source_props + " " + target_props)
files_list.append("<file src=" + '"' + target_props + '" target="build\\native" />')
files_list.append("<file src=" + '"' + target_props + '" target="' + build_dir + '\\native" />')
if not is_snpe_package and not is_qnn_package:
files_list.append("<file src=" + '"' + target_props + '" target="build\\netstandard2.0" />')
files_list.append("<file src=" + '"' + target_props + '" target="' + build_dir + '\\netstandard2.0" />')
files_list.append("<file src=" + '"' + target_props + '" target="' + build_dir + '\\netstandard2.1" />')
# Process targets file
source_targets = os.path.join(
@ -895,9 +942,10 @@ def generate_files(line_list, args):
args.package_name + ".targets",
)
os.system(copy_command + " " + source_targets + " " + target_targets)
files_list.append("<file src=" + '"' + target_targets + '" target="build\\native" />')
files_list.append("<file src=" + '"' + target_targets + '" target="' + build_dir + '\\native" />')
if not is_snpe_package and not is_qnn_package:
files_list.append("<file src=" + '"' + target_targets + '" target="build\\netstandard2.0" />')
files_list.append("<file src=" + '"' + target_targets + '" target="' + build_dir + '\\netstandard2.0" />')
files_list.append("<file src=" + '"' + target_targets + '" target="' + build_dir + '\\netstandard2.1" />')
# Process xamarin targets files
if args.package_name == "Microsoft.ML.OnnxRuntime":
@ -1148,7 +1196,8 @@ def main():
lines = generate_nuspec(args)
# Create the nuspec needed to generate the Nuget
with open(os.path.join(args.native_build_path, "NativeNuget.nuspec"), "w") as f:
print(f"nuspec_name: {args.nuspec_name}")
with open(os.path.join(args.native_build_path, args.nuspec_name), "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)

View file

@ -102,6 +102,7 @@ def check_if_dlls_are_present(
platforms_supported,
zip_file,
package_path,
is_gpu_dependent_package=False, # only used for nuget packages
):
platforms = platforms_supported.strip().split(",")
if package_type == "tarball":
@ -110,31 +111,44 @@ def check_if_dlls_are_present(
file_list_in_package += [os.path.join(dirpath, file) for file in filenames]
else:
file_list_in_package = zip_file.namelist()
print(file_list_in_package)
# In Nuget GPU package, onnxruntime.dll is in dependent package.
package_contains_library = not bool(package_type == "nuget" and is_gpu_package)
# In Nuget GPU package, gpu header files are not in dependent package.
package_contains_headers = bool(
(is_gpu_package and package_type != "nuget") or (package_type == "nuget" and not is_gpu_package)
)
# In Nuget GPU package, cuda ep and tensorrt ep dlls are in dependent package
package_contains_cuda_binaries = bool((is_gpu_package and package_type != "nuget") or is_gpu_dependent_package)
for platform in platforms:
if platform.startswith("win"):
native_folder = "_native" if is_windows_ai_package else "native"
if package_type == "nuget":
folder = "runtimes/" + platform + "/" + native_folder
header_folder = "build/native/include"
build_dir = "buildTransitive" if is_gpu_dependent_package else "build"
header_folder = f"{build_dir}/native/include"
else: # zip package
folder = package_path + "/lib"
header_folder = package_path + "/include"
path = folder + "/" + "onnxruntime.dll"
print("Checking path: " + path)
if path not in file_list_in_package:
print("onnxruntime.dll not found for " + platform)
raise Exception("onnxruntime.dll not found for " + platform)
# In Nuget GPU package, onnxruntime.dll is in dependent package.
if package_contains_library:
path = folder + "/" + "onnxruntime.dll"
print("Checking path: " + path)
if path not in file_list_in_package:
print("onnxruntime.dll not found for " + platform)
raise Exception("onnxruntime.dll not found for " + platform)
if is_gpu_package:
if package_contains_cuda_binaries:
for dll in win_gpu_package_libraries:
path = folder + "/" + dll
print("Checking path: " + path)
if path not in file_list_in_package:
print(dll + " not found for " + platform)
raise Exception(dll + " not found for " + platform)
if package_contains_headers:
check_if_headers_are_present(gpu_related_header_files, header_folder, file_list_in_package, platform)
if is_dml_package:
@ -148,24 +162,28 @@ def check_if_dlls_are_present(
elif platform.startswith("linux"):
if package_type == "nuget":
folder = "runtimes/" + platform + "/native"
header_folder = "build/native/include"
build_dir = "buildTransitive" if is_gpu_dependent_package else "build"
header_folder = f"{build_dir}/native/include"
else: # tarball package
folder = package_path + "/lib"
header_folder = package_path + "/include"
path = folder + "/" + "libonnxruntime.so"
print("Checking path: " + path)
if path not in file_list_in_package:
print("libonnxruntime.so not found for " + platform)
raise Exception("libonnxruntime.so not found for " + platform)
if package_contains_library:
path = folder + "/" + "libonnxruntime.so"
print("Checking path: " + path)
if path not in file_list_in_package:
print("libonnxruntime.so not found for " + platform)
raise Exception("libonnxruntime.so not found for " + platform)
if is_gpu_package:
if package_contains_cuda_binaries:
for so in linux_gpu_package_libraries:
path = folder + "/" + so
print("Checking path: " + path)
if path not in file_list_in_package:
print(so + " not found for " + platform)
raise Exception(so + " not found for " + platform)
if package_contains_headers:
for header in gpu_related_header_files:
path = header_folder + "/" + header
print("Checking path: " + path)
@ -275,11 +293,11 @@ def validate_nuget(args):
nuget_file_name = nuget_packages_found_in_path[0]
full_nuget_path = os.path.join(args.package_path, nuget_file_name)
if "Gpu" in nuget_file_name:
is_gpu_package = True
else:
is_gpu_package = False
is_gpu_package = bool("microsoft.ml.onnxruntime.gpu.1" in args.package_name.lower())
is_gpu_dependent_package = bool(
"microsoft.ml.onnxruntime.gpu.windows" in args.package_name.lower()
or "microsoft.ml.onnxruntime.gpu.linux" in args.package_name.lower()
)
if "directml" in nuget_file_name.lower():
is_dml_package = True
else:
@ -325,6 +343,7 @@ def validate_nuget(args):
args.platforms_supported,
zip_file,
None,
is_gpu_dependent_package,
)
verify_nuget_signing = args.verify_nuget_signing.lower()