onnxruntime/tools/nuget/generate_nuspec_for_native_nuget.py
Ashwini Khade 65201e47bf
Enable nuget packages for on device training (#13637)
### Description
This PR enables building nuget packages locally for on device training
using --build_nuget arg.
This PR also enables the C# bindings by default in the managed package.
If a user triggers any training apis when the native binary is not built
for training, an exception with message "Training is disabled in the
current build. Please build ONNXRuntime from source with the build flags
enable_training and enable_training_on_device. " is thrown.

Build command for creating nuget packes for on device training:
build.bat --enable_training --enable_training_on_device --build_nuget 

2 Nuget packages are built
1. Microsoft.ML.OnnxRuntime.Managed
2. Microsoft.ML.OnnxRuntime.Training OR
Microsoft.ML.OnnxRuntime.Training.Gpu



### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
2022-12-05 14:54:09 -08:00

1082 lines
44 KiB
Python

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import argparse
import os
import re
import sys
from pathlib import Path
# What does the names of our C API tarball/zip files looks like
# os: win, linux, osx
# ep: cuda, tensorrt, None
def get_package_name(os, cpu_arch, ep):
pkg_name = None
if os == "win":
pkg_name = "onnxruntime-win-"
pkg_name += cpu_arch
if ep == "cuda":
pkg_name += "-cuda"
elif ep == "tensorrt":
pkg_name += "-tensorrt"
elif os == "linux":
pkg_name = "onnxruntime-linux-"
pkg_name += cpu_arch
if ep == "cuda":
pkg_name += "-cuda"
elif ep == "tensorrt":
pkg_name += "-tensorrt"
elif os == "osx":
pkg_name = "onnxruntime-osx-" + cpu_arch
return pkg_name
# 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):
return (ep != "cuda" or "cuda" in filename) and (ep != "tensorrt" or "cuda" not in filename)
# nuget_artifacts_dir: the directory with uncompressed C API tarball/zip files
# 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):
for child in nuget_artifacts_dir.iterdir():
if not child.is_dir():
continue
for cpu_arch in ["x86", "x64", "arm", "arm64"]:
if child.name == get_package_name("win", cpu_arch, ep):
child = child / "lib"
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):
files_list.append(
'<file src="' + str(child_file) + '" target="runtimes/win-%s/native"/>' % cpu_arch
)
for cpu_arch in ["x86_64", "arm64"]:
if child.name == get_package_name("osx", cpu_arch, ep):
child = child / "lib"
if cpu_arch == "x86_64":
cpu_arch = "x64"
for child_file in child.iterdir():
# Check if the file has digits like onnxruntime.1.8.0.dylib. We can skip such things
is_versioned_dylib = re.match(r".*[\.\d+]+\.dylib$", child_file.name)
if child_file.is_file() and child_file.suffix == ".dylib" and not is_versioned_dylib:
files_list.append(
'<file src="' + str(child_file) + '" target="runtimes/osx.10.14-%s/native"/>' % cpu_arch
)
for cpu_arch in ["x64", "aarch64"]:
if child.name == get_package_name("linux", cpu_arch, ep):
child = child / "lib"
if cpu_arch == "x86_64":
cpu_arch = "x64"
elif cpu_arch == "aarch64":
cpu_arch = "arm64"
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):
files_list.append(
'<file src="' + str(child_file) + '" target="runtimes/linux-%s/native"/>' % cpu_arch
)
if child.name == "onnxruntime-android":
for child_file in child.iterdir():
if child_file.suffix in [".aar"]:
files_list.append('<file src="' + str(child_file) + '" target="runtimes/android/native"/>')
if child.name == "onnxruntime-ios-xcframework":
files_list.append('<file src="' + str(child) + "\\**" '" target="runtimes/ios/native"/>')
def parse_arguments():
parser = argparse.ArgumentParser(
description="ONNX Runtime create nuget spec script " "(for hosting native shared library artifacts)", usage=""
)
# Main arguments
parser.add_argument("--package_name", required=True, help="ORT package name. Eg: Microsoft.ML.OnnxRuntime.Gpu")
parser.add_argument("--package_version", required=True, help="ORT package version. Eg: 1.0.0")
parser.add_argument("--target_architecture", required=True, help="Eg: x64")
parser.add_argument("--build_config", required=True, help="Eg: RelWithDebInfo")
parser.add_argument("--ort_build_path", required=True, help="ORT build directory.")
parser.add_argument("--native_build_path", required=True, help="Native build output directory.")
parser.add_argument("--packages_path", required=True, help="Nuget packages output directory.")
parser.add_argument("--sources_path", required=True, help="OnnxRuntime source code root.")
parser.add_argument("--commit_id", required=True, help="The last commit id included in this package.")
parser.add_argument(
"--is_release_build",
required=False,
default=None,
type=str,
help="Flag indicating if the build is a release build. Accepted values: true/false.",
)
parser.add_argument(
"--execution_provider",
required=False,
default="None",
type=str,
choices=["cuda", "dnnl", "openvino", "tensorrt", "snpe", "tvm", "None"],
help="The selected execution provider for this build.",
)
parser.add_argument("--sdk_info", required=False, default="", type=str, help="dependency SDK information.")
return parser.parse_args()
def generate_id(line_list, package_name):
line_list.append("<id>" + package_name + "</id>")
def generate_version(line_list, package_version):
line_list.append("<version>" + package_version + "</version>")
def generate_authors(line_list, authors):
line_list.append("<authors>" + authors + "</authors>")
def generate_owners(line_list, owners):
line_list.append("<owners>" + owners + "</owners>")
def generate_description(line_list, package_name):
description = ""
if package_name == "Microsoft.AI.MachineLearning":
description = "This package contains Windows ML binaries."
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>")
def generate_copyright(line_list, copyright):
line_list.append("<copyright>" + copyright + "</copyright>")
def generate_tags(line_list, tags):
line_list.append("<tags>" + tags + "</tags>")
def generate_icon(line_list, icon_file):
line_list.append("<icon>" + icon_file + "</icon>")
def generate_license(line_list):
line_list.append('<license type="file">LICENSE.txt</license>')
def generate_project_url(line_list, project_url):
line_list.append("<projectUrl>" + project_url + "</projectUrl>")
def generate_repo_url(line_list, repo_url, commit_id):
line_list.append('<repository type="git" url="' + repo_url + '"' + ' commit="' + commit_id + '" />')
def generate_dependencies(xml_text, package_name, version):
dml_dependency = '<dependency id="Microsoft.AI.DirectML" version="1.10.0"/>'
if package_name == "Microsoft.AI.MachineLearning":
xml_text.append("<dependencies>")
# Support .Net Core
xml_text.append('<group targetFramework="net5.0">')
xml_text.append(dml_dependency)
xml_text.append("</group>")
# UAP10.0.16299, This is the earliest release of the OS that supports .NET Standard apps
xml_text.append('<group targetFramework="UAP10.0.16299">')
xml_text.append(dml_dependency)
xml_text.append("</group>")
# Support Native C++
xml_text.append('<group targetFramework="native">')
xml_text.append(dml_dependency)
xml_text.append("</group>")
xml_text.append("</dependencies>")
else:
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 + '"/>')
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 + '"/>')
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 + '"/>')
if include_dml:
xml_text.append(dml_dependency)
xml_text.append("</group>")
if package_name == "Microsoft.ML.OnnxRuntime":
# Support monoandroid11.0
xml_text.append('<group targetFramework="monoandroid11.0">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
xml_text.append("</group>")
# Support xamarinios10
xml_text.append('<group targetFramework="xamarinios10">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
xml_text.append("</group>")
# Support net6.0-android
xml_text.append('<group targetFramework="net6.0-android31.0">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
xml_text.append("</group>")
# Support net6.0-ios
xml_text.append('<group targetFramework="net6.0-ios15.4">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
xml_text.append("</group>")
# Support net6.0-macos
xml_text.append('<group targetFramework="net6.0-macos12.3">')
xml_text.append('<dependency id="Microsoft.ML.OnnxRuntime.Managed"' + ' version="' + version + '"/>')
xml_text.append("</group>")
# Support Native C++
if include_dml:
xml_text.append('<group targetFramework="native">')
xml_text.append(dml_dependency)
xml_text.append("</group>")
xml_text.append("</dependencies>")
def get_env_var(key):
return os.environ.get(key)
def generate_release_notes(line_list, dependency_sdk_info):
line_list.append("<releaseNotes>")
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 ""))
build_id = get_env_var("BUILD_BUILDID")
line_list.append(
"\t"
+ "Build: https://aiinfra.visualstudio.com/Lotus/_build/results?buildId="
+ (build_id if build_id is not None else "")
)
if dependency_sdk_info:
line_list.append("Dependency SDK: " + dependency_sdk_info)
line_list.append("</releaseNotes>")
def generate_metadata(line_list, args):
metadata_list = ["<metadata>"]
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_copyright(metadata_list, "\xc2\xa9 " + "Microsoft Corporation. All rights reserved.")
generate_tags(metadata_list, "ONNX ONNX Runtime Machine Learning")
generate_icon(metadata_list, "ORT_icon_for_light_bg.png")
generate_license(metadata_list)
generate_project_url(metadata_list, "https://github.com/Microsoft/onnxruntime")
generate_repo_url(metadata_list, "https://github.com/Microsoft/onnxruntime.git", args.commit_id)
generate_dependencies(metadata_list, args.package_name, args.package_version)
generate_release_notes(metadata_list, args.sdk_info)
metadata_list.append("</metadata>")
line_list += metadata_list
def generate_files(line_list, args):
files_list = ["<files>"]
is_cpu_package = args.package_name in ["Microsoft.ML.OnnxRuntime", "Microsoft.ML.OnnxRuntime.OpenMP"]
is_mklml_package = args.package_name == "Microsoft.ML.OnnxRuntime.MKLML"
is_cuda_gpu_package = args.package_name == "Microsoft.ML.OnnxRuntime.Gpu"
is_dml_package = args.package_name == "Microsoft.ML.OnnxRuntime.DirectML"
is_windowsai_package = args.package_name == "Microsoft.AI.MachineLearning"
is_snpe_package = args.package_name == "Microsoft.ML.OnnxRuntime.Snpe"
is_training_package = args.package_name in [
"Microsoft.ML.OnnxRuntime.Training",
"Microsoft.ML.OnnxRuntime.Training.Gpu",
]
includes_winml = is_windowsai_package
includes_directml = (is_dml_package or is_windowsai_package) and (
args.target_architecture == "x64" or args.target_architecture == "x86"
)
is_windows_build = is_windows()
nuget_dependencies = {}
if is_windows_build:
nuget_dependencies = {
"mklml": "mklml.dll",
"openmp": "libiomp5md.dll",
"dnnl": "dnnl.dll",
"tvm": "tvm.dll",
"providers_shared_lib": "onnxruntime_providers_shared.dll",
"dnnl_ep_shared_lib": "onnxruntime_providers_dnnl.dll",
"tensorrt_ep_shared_lib": "onnxruntime_providers_tensorrt.dll",
"openvino_ep_shared_lib": "onnxruntime_providers_openvino.dll",
"cuda_ep_shared_lib": "onnxruntime_providers_cuda.dll",
"tvm_ep_shared_lib": "onnxruntime_providers_tvm.lib",
"onnxruntime_perf_test": "onnxruntime_perf_test.exe",
"onnx_test_runner": "onnx_test_runner.exe",
}
copy_command = "copy"
runtimes_target = '" target="runtimes\\win-'
else:
nuget_dependencies = {
"mklml": "libmklml_intel.so",
"mklml_1": "libmklml_gnu.so",
"openmp": "libiomp5.so",
"dnnl": "libdnnl.so.1",
"tvm": "libtvm.so.0.5.1",
"providers_shared_lib": "libonnxruntime_providers_shared.so",
"dnnl_ep_shared_lib": "libonnxruntime_providers_dnnl.so",
"tensorrt_ep_shared_lib": "libonnxruntime_providers_tensorrt.so",
"openvino_ep_shared_lib": "libonnxruntime_providers_openvino.so",
"cuda_ep_shared_lib": "libonnxruntime_providers_cuda.so",
"onnxruntime_perf_test": "onnxruntime_perf_test",
"onnx_test_runner": "onnx_test_runner",
}
copy_command = "cp"
runtimes_target = '" target="runtimes\\linux-'
if is_windowsai_package:
runtimes_native_folder = "_native"
else:
runtimes_native_folder = "native"
runtimes = '{}{}\\{}"'.format(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" />'
)
if is_training_package:
files_list.append(
"<file src="
+ '"'
+ os.path.join(
args.sources_path, "orttraining\\orttraining\\training_api\\include\\onnxruntime_training_c_api.h"
)
+ '" target="build\\native\\include" />'
)
if args.execution_provider == "tvm":
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\providers\\tvm\\tvm_provider_factory.h")
+ '" target="build\\native\\include" />'
)
if args.execution_provider == "openvino":
files_list.append(
"<file src="
+ '"'
+ os.path.join(
args.sources_path, "include\\onnxruntime\\core\\providers\\openvino\\openvino_provider_factory.h"
)
+ '" target="build\\native\\include" />'
)
if args.execution_provider == "tensorrt":
files_list.append(
"<file src="
+ '"'
+ os.path.join(
args.sources_path, "include\\onnxruntime\\core\\providers\\tensorrt\\tensorrt_provider_factory.h"
)
+ '" target="build\\native\\include" />'
)
if args.execution_provider == "dnnl":
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\providers\\dnnl\\dnnl_provider_factory.h")
+ '" target="build\\native\\include" />'
)
if includes_directml:
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "include\\onnxruntime\\core\\providers\\dml\\dml_provider_factory.h")
+ '" target="build\\native\\include" />'
)
if includes_winml:
# Add microsoft.ai.machinelearning headers
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.ort_build_path, args.build_config, "microsoft.ai.machinelearning.h")
+ '" target="build\\native\\include\\abi\\Microsoft.AI.MachineLearning.h" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "winml\\api\\dualapipartitionattribute.h")
+ '" target="build\\native\\include\\abi\\dualapipartitionattribute.h" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.ort_build_path, args.build_config, "microsoft.ai.machinelearning.native.h")
+ '" target="build\\native\\include\\Microsoft.AI.MachineLearning.Native.h" />'
)
# Add custom operator headers
mlop_path = "onnxruntime\\core\\providers\\dml\\dmlexecutionprovider\\inc\\mloperatorauthor.h"
files_list.append(
"<file src=" + '"' + os.path.join(args.sources_path, mlop_path) + '" target="build\\native\\include" />'
)
# Process microsoft.ai.machinelearning.winmd
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.ort_build_path, args.build_config, "microsoft.ai.machinelearning.winmd")
+ '" target="winmds\\Microsoft.AI.MachineLearning.winmd" />'
)
# Process microsoft.ai.machinelearning.experimental.winmd
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.ort_build_path, args.build_config, "microsoft.ai.machinelearning.experimental.winmd")
+ '" target="winmds\\Microsoft.AI.MachineLearning.Experimental.winmd" />'
)
if args.target_architecture == "x64":
interop_dll_path = "Microsoft.AI.MachineLearning.Interop\\net5.0-windows10.0.17763.0"
interop_dll = interop_dll_path + "\\Microsoft.AI.MachineLearning.Interop.dll"
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, interop_dll)
+ '" target="lib\\net5.0\\Microsoft.AI.MachineLearning.Interop.dll" />'
)
interop_pdb_path = "Microsoft.AI.MachineLearning.Interop\\net5.0-windows10.0.17763.0"
interop_pdb = interop_pdb_path + "\\Microsoft.AI.MachineLearning.Interop.pdb"
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, interop_pdb)
+ '" target="lib\\net5.0\\Microsoft.AI.MachineLearning.Interop.pdb" />'
)
if args.package_name == "Microsoft.ML.OnnxRuntime.Snpe":
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnx_test_runner.exe") + runtimes + " />"
)
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, "onnxruntime_perf_test.exe") + runtimes + " />"
)
is_ado_packaging_build = False
# Process runtimes
# Process onnxruntime import lib, dll, and pdb
# for Snpe android build
if is_windows_build:
nuget_artifacts_dir = Path(args.native_build_path) / "nuget-artifacts"
# the winml package includes pdbs. for other packages exclude them.
include_pdbs = includes_winml
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:
ep_list = ["tensorrt", "cuda", None]
else:
ep_list = [None]
for ep in ep_list:
generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs)
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")):
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, "nuget-staging/usr/local/lib", "libonnxruntime.so")
+ '" target="runtimes\\linux-'
+ args.target_architecture
+ '\\native" />'
)
if includes_winml:
# Process microsoft.ai.machinelearning import lib, dll, and pdb
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, "microsoft.ai.machinelearning.lib")
+ runtimes_target
+ args.target_architecture
+ "\\_native"
+ '\\Microsoft.AI.MachineLearning.lib" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, "microsoft.ai.machinelearning.dll")
+ runtimes_target
+ args.target_architecture
+ "\\_native"
+ '\\Microsoft.AI.MachineLearning.dll" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, "microsoft.ai.machinelearning.pdb")
+ runtimes_target
+ args.target_architecture
+ "\\_native"
+ '\\Microsoft.AI.MachineLearning.pdb" />'
)
# Process execution providers which are built as shared libs
if args.execution_provider == "tensorrt" and not is_ado_packaging_build:
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["providers_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["cuda_ep_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["tensorrt_ep_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
if args.execution_provider == "dnnl":
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["providers_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["dnnl_ep_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
if args.execution_provider == "tvm":
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["providers_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["tvm_ep_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
tvm_build_path = os.path.join(args.ort_build_path, args.build_config, "_deps", "tvm-build")
if is_windows():
files_list.append(
"<file src="
+ '"'
+ os.path.join(tvm_build_path, args.build_config, nuget_dependencies["tvm"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
else:
# TODO(agladyshev): Add support for Linux.
raise RuntimeError("Now only Windows is supported for TVM EP.")
if args.execution_provider == "openvino":
openvino_path = get_env_var("INTEL_OPENVINO_DIR")
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["providers_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["openvino_ep_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
if is_windows():
if "2022" in openvino_path:
dll_list_path = os.path.join(openvino_path, "runtime\\bin\\intel64\\Release\\")
tbb_list_path = os.path.join(openvino_path, "runtime\\3rdparty\\tbb\\bin\\")
else:
dll_list_path = os.path.join(
openvino_path, "deployment_tools\\inference_engine\\bin\\intel64\\Release\\"
)
tbb_list_path = os.path.join(openvino_path, "deployment_tools\\inference_engine\\external\\tbb\\bin\\")
ngraph_list_path = os.path.join(openvino_path, "deployment_tools\\ngraph\\lib\\")
for ngraph_element in os.listdir(ngraph_list_path):
if ngraph_element.endswith("dll"):
files_list.append(
"<file src="
+ '"'
+ os.path.join(ngraph_list_path, ngraph_element)
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
for dll_element in os.listdir(dll_list_path):
if dll_element.endswith("dll"):
files_list.append(
"<file src="
+ '"'
+ os.path.join(dll_list_path, dll_element)
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
# plugins.xml
files_list.append(
"<file src="
+ '"'
+ os.path.join(dll_list_path, "plugins.xml")
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
# usb-ma2x8x.mvcmd
files_list.append(
"<file src="
+ '"'
+ os.path.join(dll_list_path, "usb-ma2x8x.mvcmd")
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
for tbb_element in os.listdir(tbb_list_path):
if tbb_element.endswith("dll"):
files_list.append(
"<file src="
+ '"'
+ os.path.join(tbb_list_path, tbb_element)
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
if args.execution_provider == "cuda" or is_cuda_gpu_package and not is_ado_packaging_build:
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["providers_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["cuda_ep_shared_lib"])
+ runtimes_target
+ args.target_architecture
+ '\\native" />'
)
# process all other library dependencies
if is_cpu_package or is_cuda_gpu_package or is_dml_package or is_mklml_package:
# Process dnnl dependency
if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["dnnl"])):
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, nuget_dependencies["dnnl"]) + runtimes + " />"
)
# Process mklml dependency
if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["mklml"])):
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["mklml"])
+ runtimes
+ " />"
)
if is_linux() and os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["mklml_1"])):
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["mklml_1"])
+ runtimes
+ " />"
)
# Process libiomp5md dependency
if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["openmp"])):
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["openmp"])
+ runtimes
+ " />"
)
# Process tvm dependency
if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["tvm"])):
files_list.append(
"<file src=" + '"' + os.path.join(args.native_build_path, nuget_dependencies["tvm"]) + runtimes + " />"
)
# Some tools to be packaged in nightly build only, should not be released
# These are copied to the runtimes folder for convenience of loading with the dlls
if (
args.is_release_build.lower() != "true"
and args.target_architecture == "x64"
and os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["onnxruntime_perf_test"]))
):
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["onnxruntime_perf_test"])
+ runtimes
+ " />"
)
if (
args.is_release_build.lower() != "true"
and args.target_architecture == "x64"
and os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["onnx_test_runner"]))
):
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.native_build_path, nuget_dependencies["onnx_test_runner"])
+ runtimes
+ " />"
)
# Process props and targets files
if is_windowsai_package:
windowsai_src = "Microsoft.AI.MachineLearning"
windowsai_props = "Microsoft.AI.MachineLearning.props"
windowsai_targets = "Microsoft.AI.MachineLearning.targets"
windowsai_native_props = os.path.join(args.sources_path, "csharp", "src", windowsai_src, windowsai_props)
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"
files_list.append("<file src=" + '"' + windowsai_native_props + '" target="' + build + '" />')
# Process native targets
files_list.append("<file src=" + '"' + windowsai_native_targets + '" target="' + build + '" />')
# Process rules
files_list.append("<file src=" + '"' + windowsai_native_rules + '" target="' + build + '" />')
# Process .net5.0 targets
if args.target_architecture == "x64":
interop_src = "Microsoft.AI.MachineLearning.Interop"
interop_props = "Microsoft.AI.MachineLearning.props"
interop_targets = "Microsoft.AI.MachineLearning.targets"
windowsai_net50_props = os.path.join(args.sources_path, "csharp", "src", interop_src, interop_props)
windowsai_net50_targets = os.path.join(args.sources_path, "csharp", "src", interop_src, interop_targets)
files_list.append("<file src=" + '"' + windowsai_net50_props + '" target="build\\net5.0" />')
files_list.append("<file src=" + '"' + windowsai_net50_targets + '" target="build\\net5.0" />')
if is_cpu_package or is_cuda_gpu_package or is_dml_package or is_mklml_package or is_snpe_package:
# Process props file
source_props = os.path.join(
args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "netstandard", "props.xml"
)
target_props = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"netstandard",
args.package_name + ".props",
)
os.system(copy_command + " " + source_props + " " + target_props)
files_list.append("<file src=" + '"' + target_props + '" target="build\\native" />')
if not is_snpe_package:
files_list.append("<file src=" + '"' + target_props + '" target="build\\netstandard1.1" />')
files_list.append("<file src=" + '"' + target_props + '" target="build\\netstandard2.0" />')
# Process targets file
source_targets = os.path.join(
args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "netstandard", "targets.xml"
)
target_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"netstandard",
args.package_name + ".targets",
)
os.system(copy_command + " " + source_targets + " " + target_targets)
files_list.append("<file src=" + '"' + target_targets + '" target="build\\native" />')
if not is_snpe_package:
files_list.append("<file src=" + '"' + target_targets + '" target="build\\netstandard1.1" />')
files_list.append("<file src=" + '"' + target_targets + '" target="build\\netstandard2.0" />')
# Process xamarin targets files
if args.package_name == "Microsoft.ML.OnnxRuntime":
monoandroid_source_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"monoandroid11.0",
"targets.xml",
)
monoandroid_target_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"monoandroid11.0",
args.package_name + ".targets",
)
xamarinios_source_targets = os.path.join(
args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "xamarinios10", "targets.xml"
)
xamarinios_target_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"xamarinios10",
args.package_name + ".targets",
)
net6_android_source_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"net6.0-android",
"targets.xml",
)
net6_android_target_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"net6.0-android",
args.package_name + ".targets",
)
net6_ios_source_targets = os.path.join(
args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net6.0-ios", "targets.xml"
)
net6_ios_target_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"net6.0-ios",
args.package_name + ".targets",
)
net6_macos_source_targets = os.path.join(
args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net6.0-macos", "targets.xml"
)
net6_macos_target_targets = os.path.join(
args.sources_path,
"csharp",
"src",
"Microsoft.ML.OnnxRuntime",
"targets",
"net6.0-macos",
args.package_name + ".targets",
)
os.system(copy_command + " " + monoandroid_source_targets + " " + monoandroid_target_targets)
os.system(copy_command + " " + xamarinios_source_targets + " " + xamarinios_target_targets)
os.system(copy_command + " " + net6_android_source_targets + " " + net6_android_target_targets)
os.system(copy_command + " " + net6_ios_source_targets + " " + net6_ios_target_targets)
os.system(copy_command + " " + net6_macos_source_targets + " " + net6_macos_target_targets)
files_list.append("<file src=" + '"' + monoandroid_target_targets + '" target="build\\monoandroid11.0" />')
files_list.append(
"<file src=" + '"' + monoandroid_target_targets + '" target="buildTransitive\\monoandroid11.0" />'
)
files_list.append("<file src=" + '"' + xamarinios_target_targets + '" target="build\\xamarinios10" />')
files_list.append(
"<file src=" + '"' + xamarinios_target_targets + '" target="buildTransitive\\xamarinios10" />'
)
files_list.append(
"<file src=" + '"' + net6_android_target_targets + '" target="build\\net6.0-android31.0" />'
)
files_list.append(
"<file src=" + '"' + net6_android_target_targets + '" target="buildTransitive\\net6.0-android31.0" />'
)
files_list.append("<file src=" + '"' + net6_ios_target_targets + '" target="build\\net6.0-ios15.4" />')
files_list.append(
"<file src=" + '"' + net6_ios_target_targets + '" target="buildTransitive\\net6.0-ios15.4" />'
)
files_list.append("<file src=" + '"' + net6_macos_target_targets + '" target="build\\net6.0-macos12.3" />')
files_list.append(
"<file src=" + '"' + net6_macos_target_targets + '" target="buildTransitive\\net6.0-macos12.3" />'
)
# Process License, ThirdPartyNotices, Privacy
files_list.append("<file src=" + '"' + os.path.join(args.sources_path, "LICENSE.txt") + '" target="LICENSE.txt" />')
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "ThirdPartyNotices.txt")
+ '" target="ThirdPartyNotices.txt" />'
)
files_list.append(
"<file src=" + '"' + os.path.join(args.sources_path, "docs", "Privacy.md") + '" target="Privacy.md" />'
)
files_list.append(
"<file src="
+ '"'
+ os.path.join(args.sources_path, "ORT_icon_for_light_bg.png")
+ '" target="ORT_icon_for_light_bg.png" />'
)
files_list.append("</files>")
line_list += files_list
def generate_nuspec(args):
lines = ['<?xml version="1.0"?>']
lines.append("<package>")
generate_metadata(lines, args)
generate_files(lines, args)
lines.append("</package>")
return lines
def is_windows():
return sys.platform.startswith("win")
def is_linux():
return sys.platform.startswith("linux")
def is_macos():
return sys.platform.startswith("darwin")
def validate_platform():
if not (is_windows() or is_linux() or is_macos()):
raise Exception("Native Nuget generation is currently supported only on Windows, Linux, and MacOS")
def validate_execution_provider(execution_provider):
if is_linux():
if not (
execution_provider == "None"
or execution_provider == "dnnl"
or execution_provider == "cuda"
or execution_provider == "tensorrt"
or execution_provider == "openvino"
):
raise Exception(
"On Linux platform nuget generation is supported only "
"for cpu|cuda|dnnl|tensorrt|openvino execution providers."
)
def main():
# Parse arguments
args = parse_arguments()
validate_platform()
validate_execution_provider(args.execution_provider)
if args.is_release_build.lower() != "true" and args.is_release_build.lower() != "false":
raise Exception("Only valid options for IsReleaseBuild are: true and false")
# Generate nuspec
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:
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__":
sys.exit(main())