# 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, is_training_package): pkg_name = "onnxruntime-training" if is_training_package else "onnxruntime" if os == "win": pkg_name += "-win-" pkg_name += cpu_arch if ep == "cuda": pkg_name += "-cuda" elif ep == "tensorrt": pkg_name += "-tensorrt" elif ep == "rocm": pkg_name += "-rocm" elif os == "linux": pkg_name += "-linux-" pkg_name += cpu_arch if ep == "cuda": pkg_name += "-cuda" elif ep == "tensorrt": pkg_name += "-tensorrt" elif ep == "rocm": pkg_name += "-rocm" 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 # 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) # 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, is_training_package, package_name): 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, is_training_package): 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, package_name) and package_name != "Microsoft.ML.OnnxRuntime.Gpu.Linux" ): files_list.append( '' ) for cpu_arch in ["x86_64", "arm64"]: if child.name == get_package_name("osx", cpu_arch, ep, is_training_package): child = child / "lib" # noqa: PLW2901 if cpu_arch == "x86_64": cpu_arch = "x64" # noqa: PLW2901 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( '' ) for cpu_arch in ["x64", "aarch64"]: if child.name == get_package_name("linux", cpu_arch, ep, is_training_package): child = child / "lib" # noqa: PLW2901 if cpu_arch == "x86_64": cpu_arch = "x64" # noqa: PLW2901 elif cpu_arch == "aarch64": cpu_arch = "arm64" # noqa: PLW2901 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, package_name) and package_name != "Microsoft.ML.OnnxRuntime.Gpu.Windows" ): files_list.append( '' ) if child.name == "onnxruntime-android" or child.name == "onnxruntime-training-android": for child_file in child.iterdir(): if child_file.suffix in [".aar"]: files_list.append('') if child.name == "onnxruntime-ios": for child_file in child.iterdir(): if child_file.suffix in [".zip"]: files_list.append('') 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", "qnn", "None"], 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() def generate_id(line_list, package_name): line_list.append("" + package_name + "") def generate_version(line_list, package_version): line_list.append("" + package_version + "") def generate_authors(line_list, authors): line_list.append("" + authors + "") def generate_owners(line_list, owners): line_list.append("" + owners + "") def generate_description(line_list, package_name): description = "" if package_name == "Microsoft.AI.MachineLearning": description = "This package contains Windows ML binaries." elif "Microsoft.ML.OnnxRuntime.Training" in package_name: # This is a Microsoft.ML.OnnxRuntime.Training.* package description = ( "The onnxruntime-training native shared library artifacts are designed to efficiently train and infer " + "a wide range of ONNX models on edge devices, such as client machines, gaming consoles, and other " + "portable devices with a focus on minimizing resource usage and maximizing accuracy." + "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 + "") def generate_copyright(line_list, copyright): line_list.append("" + copyright + "") def generate_tags(line_list, tags): line_list.append("" + tags + "") def generate_icon(line_list, icon_file): line_list.append("" + icon_file + "") def generate_license(line_list): line_list.append('LICENSE') def generate_project_url(line_list, project_url): line_list.append("" + project_url + "") def generate_repo_url(line_list, repo_url, commit_id): line_list.append('') def generate_readme(line_list): line_list.append("README.md") def add_common_dependencies(xml_text, package_name, version): xml_text.append('') if package_name == "Microsoft.ML.OnnxRuntime.Gpu": xml_text.append('') xml_text.append('') def generate_dependencies(xml_text, package_name, version): dml_dependency = '' if package_name == "Microsoft.AI.MachineLearning": xml_text.append("") # Support .Net Core xml_text.append('') xml_text.append(dml_dependency) xml_text.append("") # UAP10.0.16299, This is the earliest release of the OS that supports .NET Standard apps xml_text.append('') xml_text.append(dml_dependency) xml_text.append("") # Support Native C++ xml_text.append('') xml_text.append(dml_dependency) xml_text.append("") xml_text.append("") else: include_dml = package_name == "Microsoft.ML.OnnxRuntime.DirectML" xml_text.append("") # Support .Net Core xml_text.append('') add_common_dependencies(xml_text, package_name, version) if include_dml: xml_text.append(dml_dependency) xml_text.append("") # Support .Net Standard xml_text.append('') add_common_dependencies(xml_text, package_name, version) if include_dml: xml_text.append(dml_dependency) xml_text.append("") # Support .Net Framework xml_text.append('') add_common_dependencies(xml_text, package_name, version) if include_dml: xml_text.append(dml_dependency) xml_text.append("") if package_name == "Microsoft.ML.OnnxRuntime": # Support net8.0-android xml_text.append('') xml_text.append('') xml_text.append("") # Support net8.0-ios xml_text.append('') xml_text.append('') xml_text.append("") # Support net8.0-maccatalyst xml_text.append('') xml_text.append('') xml_text.append("") # Support Native C++ if include_dml: xml_text.append('') xml_text.append(dml_dependency) xml_text.append("") xml_text.append("") def get_env_var(key): return os.environ.get(key) def generate_release_notes(line_list, dependency_sdk_info): line_list.append("") line_list.append("Release Def:") branch = get_env_var("BUILD_SOURCEBRANCH") line_list.append("\t" + "Branch: " + (branch if branch is not None else "")) version = get_env_var("BUILD_SOURCEVERSION") line_list.append("\t" + "Commit: " + (version if version is not None else "")) 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("") def generate_metadata(line_list, args): tags = "native ONNX Runtime ONNXRuntime Machine Learning MachineLearning" if "Microsoft.ML.OnnxRuntime.Training." in args.package_name: tags.append(" ONNXRuntime-Training Learning-on-The-Edge On-Device-Training On-Device Training") metadata_list = [""] generate_id(metadata_list, args.package_name) generate_version(metadata_list, args.package_version) generate_authors(metadata_list, "Microsoft") generate_owners(metadata_list, "Microsoft") generate_description(metadata_list, args.package_name) generate_copyright(metadata_list, "\xc2\xa9 " + "Microsoft Corporation. All rights reserved.") generate_tags(metadata_list, tags) 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_readme(metadata_list) generate_dependencies(metadata_list, args.package_name, args.package_version) generate_release_notes(metadata_list, args.sdk_info) metadata_list.append("") line_list += metadata_list def generate_files(line_list, args): files_list = [""] is_cpu_package = args.package_name in [ "Microsoft.ML.OnnxRuntime", "Microsoft.ML.OnnxRuntime.OpenMP", "Microsoft.ML.OnnxRuntime.Training", ] 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" is_snpe_package = args.package_name == "Microsoft.ML.OnnxRuntime.Snpe" is_qnn_package = args.package_name == "Microsoft.ML.OnnxRuntime.QNN" 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", "rocm_ep_shared_lib": "libonnxruntime_providers_rocm.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 = f'{runtimes_target}{args.target_architecture}\\{runtimes_native_folder}"' # Process headers 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( "' ) files_list.append( "' ) files_list.append( "' ) if is_training_package: files_list.append( "' ) if args.execution_provider == "tvm": files_list.append( "' ) if args.execution_provider == "openvino": files_list.append( "' ) if args.execution_provider == "tensorrt": files_list.append("') if args.execution_provider == "dnnl": files_list.append( "' ) if includes_directml: files_list.append( "' ) if includes_winml: # Add microsoft.ai.machinelearning headers files_list.append( "' ) files_list.append( "' ) files_list.append( "' ) # Add custom operator headers mlop_path = "onnxruntime\\core\\providers\\dml\\dmlexecutionprovider\\inc\\mloperatorauthor.h" files_list.append( "' ) # Process microsoft.ai.machinelearning.winmd files_list.append( "' ) # Process microsoft.ai.machinelearning.experimental.winmd files_list.append( "' ) 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( "' ) 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( "' ) if args.package_name == "Microsoft.ML.OnnxRuntime.Snpe" or args.package_name == "Microsoft.ML.OnnxRuntime.QNN": files_list.append( "" ) files_list.append( "" ) if is_qnn_package: files_list.append("") files_list.append("") files_list.append("") if args.target_architecture != "x64": files_list.append( "" ) files_list.append( "" ) files_list.append( "" ) files_list.append( "" ) files_list.append( "" ) files_list.append( "" ) files_list.append( "" ) 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 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, args.package_name ) is_ado_packaging_build = True else: # Code path for local dev build # 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( "" ) files_list.append( "" ) if include_pdbs and os.path.exists(os.path.join(args.native_build_path, "onnxruntime.pdb")): files_list.append( "" ) else: ort_so = os.path.join(args.native_build_path, "libonnxruntime.so") if os.path.exists(ort_so): files_list.append( "' ) if includes_winml: # Process microsoft.ai.machinelearning import lib, dll, and pdb files_list.append( "' ) files_list.append( "' ) files_list.append( "' ) # Process execution providers which are built as shared libs if args.execution_provider == "tensorrt" and not is_ado_packaging_build: files_list.append( "' ) files_list.append( "' ) files_list.append( "' ) if args.execution_provider == "dnnl": files_list.append( "' ) files_list.append( "' ) if args.execution_provider == "tvm": files_list.append( "' ) files_list.append( "' ) tvm_build_path = os.path.join(args.ort_build_path, args.build_config, "_deps", "tvm-build") if is_windows(): files_list.append( "' ) else: # TODO(agladyshev): Add support for Linux. raise RuntimeError("Now only Windows is supported for TVM EP.") if args.execution_provider == "rocm" or is_rocm_gpu_package and not is_ado_packaging_build: files_list.append( "' ) files_list.append( "' ) if args.execution_provider == "openvino": get_env_var("INTEL_OPENVINO_DIR") files_list.append( "' ) files_list.append( "' ) if args.execution_provider == "cuda" or is_cuda_gpu_win_sub_package and not is_ado_packaging_build: files_list.append( "' ) files_list.append( "' ) # 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( "" ) # Process mklml dependency if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["mklml"])): files_list.append( "" ) if is_linux() and os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["mklml_1"])): files_list.append( "" ) # Process libiomp5md dependency if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["openmp"])): files_list.append( "" ) # Process tvm dependency if os.path.exists(os.path.join(args.native_build_path, nuget_dependencies["tvm"])): files_list.append( "" ) # Some tools to be packaged in nightly debug build only, should not be released # These are copied to the runtimes folder for convenience of loading with the dlls # NOTE: nuget gives a spurious error on linux if these aren't in a separate directory to the library so # we add them to a tools folder for that reason. 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( "" ) 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( "" ) # 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 = f"{build_dir}\\native" files_list.append("') # Process native targets files_list.append("') # Process rules files_list.append("') # 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("') files_list.append("') 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 or is_snpe_package or is_qnn_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("') if not is_snpe_package and not is_qnn_package: files_list.append("') files_list.append("') # 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("') if not is_snpe_package and not is_qnn_package: files_list.append("') files_list.append("') # Process xamarin targets files if args.package_name == "Microsoft.ML.OnnxRuntime": net8_android_source_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-android", "targets.xml", ) net8_android_target_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-android", args.package_name + ".targets", ) net8_ios_source_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-ios", "targets.xml" ) net8_ios_target_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-ios", args.package_name + ".targets", ) net8_maccatalyst_source_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-maccatalyst", "_._", ) net8_maccatalyst_target_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-maccatalyst", "_._" ) os.system(copy_command + " " + net8_android_source_targets + " " + net8_android_target_targets) os.system(copy_command + " " + net8_ios_source_targets + " " + net8_ios_target_targets) os.system(copy_command + " " + net8_maccatalyst_source_targets + " " + net8_maccatalyst_target_targets) files_list.append( "' ) files_list.append( "' ) files_list.append("') files_list.append( "' ) files_list.append( "' ) files_list.append( "' ) # Process Training specific targets and props if args.package_name == "Microsoft.ML.OnnxRuntime.Training": net8_android_source_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-android", "targets.xml", ) net8_android_target_targets = os.path.join( args.sources_path, "csharp", "src", "Microsoft.ML.OnnxRuntime", "targets", "net8.0-android", args.package_name + ".targets", ) os.system(copy_command + " " + net8_android_source_targets + " " + net8_android_target_targets) files_list.append( "' ) files_list.append( "' ) # README files_list.append( "' ) # Process License, ThirdPartyNotices, Privacy files_list.append("') files_list.append( "' ) files_list.append( "' ) files_list.append( "' ) if is_qnn_package: files_list.append( "' ) files_list.append("") line_list += files_list def generate_nuspec(args): lines = [''] lines.append("") generate_metadata(lines, args) generate_files(lines, args) lines.append("") 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" or execution_provider == "rocm" ): raise Exception( "On Linux platform nuget generation is supported only " "for cpu|cuda|dnnl|tensorrt|openvino|rocm 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 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) f.write(line) f.write("\n") if __name__ == "__main__": sys.exit(main())