onnxruntime/setup.py

365 строки
14 KiB
Python

#-------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#--------------------------------------------------------------------------
from setuptools import setup, find_packages, Extension
from distutils import log as logger
from distutils.command.build_ext import build_ext as _build_ext
from glob import glob
from os import path, getcwd, environ, remove, walk, makedirs, listdir
from shutil import copyfile, copytree, rmtree
import platform
import subprocess
import sys
import datetime
nightly_build = False
featurizers_build = False
package_name = 'onnxruntime'
wheel_name_suffix = None
# Any combination of the following arguments can be applied
if '--use_featurizers' in sys.argv:
featurizers_build = True
sys.argv.remove('--use_featurizers')
if '--nightly_build' in sys.argv:
package_name = 'ort-nightly'
nightly_build = True
sys.argv.remove('--nightly_build')
for arg in sys.argv[1:]:
if arg.startswith("--wheel_name_suffix="):
wheel_name_suffix = arg[len("--wheel_name_suffix="):]
sys.argv.remove(arg)
break
# The following arguments are mutually exclusive
if '--use_tensorrt' in sys.argv:
package_name = 'onnxruntime-gpu-tensorrt' if not nightly_build else 'ort-trt-nightly'
sys.argv.remove('--use_tensorrt')
elif '--use_cuda' in sys.argv:
package_name = 'onnxruntime-gpu' if not nightly_build else 'ort-gpu-nightly'
sys.argv.remove('--use_cuda')
elif '--use_openvino' in sys.argv:
package_name = 'onnxruntime-openvino'
sys.argv.remove('--use_openvino')
elif '--use_dnnl' in sys.argv:
package_name = 'onnxruntime-dnnl'
sys.argv.remove('--use_dnnl')
elif '--use_nuphar' in sys.argv:
package_name = 'onnxruntime-nuphar'
sys.argv.remove('--use_nuphar')
elif '--use_vitisai' in sys.argv:
package_name = 'onnxruntime-vitisai'
sys.argv.remove('--use_vitisai')
elif '--use_acl' in sys.argv:
package_name = 'onnxruntime-acl'
sys.argv.remove('--use_acl')
elif '--use_armnn' in sys.argv:
package_name = 'onnxruntime-armnn'
sys.argv.remove('--use_armnn')
elif '--use_dml' in sys.argv:
package_name = 'onnxruntime-dml'
sys.argv.remove('--use_dml')
# PEP 513 defined manylinux1_x86_64 and manylinux1_i686
# PEP 571 defined manylinux2010_x86_64 and manylinux2010_i686
# PEP 599 defines the following platform tags:
# manylinux2014_x86_64
# manylinux2014_i686
# manylinux2014_aarch64
# manylinux2014_armv7l
# manylinux2014_ppc64
# manylinux2014_ppc64le
# manylinux2014_s390x
manylinux_tags = [
'manylinux1_x86_64',
'manylinux1_i686',
'manylinux2010_x86_64',
'manylinux2010_i686',
'manylinux2014_x86_64',
'manylinux2014_i686',
'manylinux2014_aarch64',
'manylinux2014_armv7l',
'manylinux2014_ppc64',
'manylinux2014_ppc64le',
'manylinux2014_s390x',
]
is_manylinux = environ.get('AUDITWHEEL_PLAT', None) in manylinux_tags
class build_ext(_build_ext):
def build_extension(self, ext):
dest_file = self.get_ext_fullpath(ext.name)
logger.info('copying %s -> %s', ext.sources[0], dest_file)
copyfile(ext.sources[0], dest_file)
try:
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
class bdist_wheel(_bdist_wheel):
def finalize_options(self):
_bdist_wheel.finalize_options(self)
if not is_manylinux:
self.root_is_pure = False
def _rewrite_ld_preload(self, to_preload):
with open('onnxruntime/capi/_ld_preload.py', 'rt') as f:
ld_preload = f.read().splitlines()
with open('onnxruntime/capi/_ld_preload.py', 'wt') as f:
for line in ld_preload:
f.write(line)
f.write('\n')
if 'LD_PRELOAD_BEGIN_MARK' in line:
break
if len(to_preload) > 0:
f.write('from ctypes import CDLL, RTLD_GLOBAL\n')
for library in to_preload:
f.write('_{} = CDLL("{}", mode=RTLD_GLOBAL)\n'.format(library.split('.')[0], library))
def run(self):
if is_manylinux:
source = 'onnxruntime/capi/onnxruntime_pybind11_state.so'
dest = 'onnxruntime/capi/onnxruntime_pybind11_state_manylinux1.so'
logger.info('copying %s -> %s', source, dest)
copyfile(source, dest)
result = subprocess.run(['patchelf', '--print-needed', dest], check=True, stdout=subprocess.PIPE, universal_newlines=True)
cuda_dependencies = ['libcublas.so', 'libcudnn.so', 'libcudart.so', 'libcurand.so', 'libcufft.so', 'libnvToolsExt.so']
to_preload = []
args = ['patchelf', '--debug']
for line in result.stdout.split('\n'):
for dependency in cuda_dependencies:
if dependency in line:
to_preload.append(line)
args.extend(['--remove-needed', line])
args.append(dest)
if len(to_preload) > 0:
subprocess.run(args, check=True, stdout=subprocess.PIPE)
self._rewrite_ld_preload(to_preload)
_bdist_wheel.run(self)
if is_manylinux:
file = glob(path.join(self.dist_dir, '*linux*.whl'))[0]
logger.info('repairing %s for manylinux1', file)
try:
subprocess.run(['auditwheel', 'repair', '-w', self.dist_dir, file], check=True, stdout=subprocess.PIPE)
finally:
logger.info('removing %s', file)
remove(file)
except ImportError as error:
print("Error importing dependencies:")
print(error)
bdist_wheel = None
# Additional binaries
if platform.system() == 'Linux':
libs = ['onnxruntime_pybind11_state.so', 'libdnnl.so.1', 'libmklml_intel.so', 'libmklml_gnu.so', 'libiomp5.so', 'mimalloc.so']
# DNNL, TensorRT & OpenVINO EPs are built as shared libs
libs.extend(['libonnxruntime_providers_shared.so'])
libs.extend(['libonnxruntime_providers_dnnl.so'])
libs.extend(['libonnxruntime_providers_tensorrt.so'])
libs.extend(['libonnxruntime_providers_openvino.so'])
# Nuphar Libs
libs.extend(['libtvm.so.0.5.1'])
if nightly_build:
libs.extend(['libonnxruntime_pywrapper.so'])
elif platform.system() == "Darwin":
libs = ['onnxruntime_pybind11_state.so', 'libdnnl.1.dylib', 'mimalloc.so'] # TODO add libmklml and libiomp5 later.
# DNNL & TensorRT EPs are built as shared libs
libs.extend(['libonnxruntime_providers_shared.dylib'])
libs.extend(['libonnxruntime_providers_dnnl.dylib'])
libs.extend(['libonnxruntime_providers_tensorrt.dylib'])
if nightly_build:
libs.extend(['libonnxruntime_pywrapper.dylib'])
else:
libs = ['onnxruntime_pybind11_state.pyd', 'dnnl.dll', 'mklml.dll', 'libiomp5md.dll']
# DNNL, TensorRT & OpenVINO EPs are built as shared libs
libs.extend(['onnxruntime_providers_shared.dll'])
libs.extend(['onnxruntime_providers_dnnl.dll'])
libs.extend(['onnxruntime_providers_tensorrt.dll'])
libs.extend(['onnxruntime_providers_openvino.dll'])
# DirectML Libs
libs.extend(['directml.dll'])
# Nuphar Libs
libs.extend(['tvm.dll'])
if nightly_build:
libs.extend(['onnxruntime_pywrapper.dll'])
if is_manylinux:
data = ['capi/libonnxruntime_pywrapper.so'] if nightly_build else []
ext_modules = [
Extension(
'onnxruntime.capi.onnxruntime_pybind11_state',
['onnxruntime/capi/onnxruntime_pybind11_state_manylinux1.so'],
),
]
else:
data = [path.join('capi', x) for x in libs if path.isfile(path.join('onnxruntime', 'capi', x))]
ext_modules = []
# Additional examples
examples_names = ["mul_1.onnx", "logreg_iris.onnx", "sigmoid.onnx"]
examples = [path.join('datasets', x) for x in examples_names]
# Extra files such as EULA and ThirdPartyNotices
extra = ["LICENSE", "ThirdPartyNotices.txt", "Privacy.md"]
# Description
README = path.join(getcwd(), "docs/python/README.rst")
if not path.exists(README):
this = path.dirname(__file__)
README = path.join(this, "docs/python/README.rst")
if not path.exists(README):
raise FileNotFoundError("Unable to find 'README.rst'")
with open(README) as f:
long_description = f.read()
packages = [
'onnxruntime',
'onnxruntime.backend',
'onnxruntime.capi',
'onnxruntime.capi.training',
'onnxruntime.datasets',
'onnxruntime.tools',
'onnxruntime.quantization',
'onnxruntime.quantization.operators',
'onnxruntime.quantization.CalTableFlatBuffers',
'onnxruntime.transformers',
'onnxruntime.transformers.longformer',
]
if '--enable_training' in sys.argv:
packages.extend(['onnxruntime.training',
'onnxruntime.training.amp',
'onnxruntime.training.optim'])
sys.argv.remove('--enable_training')
package_data = {}
data_files = []
if package_name == 'onnxruntime-nuphar':
packages += ["onnxruntime.nuphar"]
extra += [path.join('nuphar', 'NUPHAR_CACHE_VERSION')]
if featurizers_build:
# Copy the featurizer data from its current directory into the onnx runtime directory so that the
# content can be included as module data.
# Apparently, the root_dir is different based on how the script is invoked
source_root_dir = None
dest_root_dir = None
for potential_source_prefix, potential_dest_prefix in [
(getcwd(), getcwd()),
(path.dirname(__file__), path.dirname(__file__)),
(path.join(getcwd(), ".."), getcwd()),
]:
potential_dir = path.join(potential_source_prefix, "external", "FeaturizersLibrary", "Data")
if path.isdir(potential_dir):
source_root_dir = potential_source_prefix
dest_root_dir = potential_dest_prefix
break
if source_root_dir is None:
raise Exception("Unable to find the build root dir")
assert dest_root_dir is not None
featurizer_source_dir = path.join(source_root_dir, "external", "FeaturizersLibrary", "Data")
assert path.isdir(featurizer_source_dir), featurizer_source_dir
featurizer_dest_dir = path.join(dest_root_dir, "onnxruntime", "FeaturizersLibrary", "Data")
if path.isdir(featurizer_dest_dir):
rmtree(featurizer_dest_dir)
for item in listdir(featurizer_source_dir):
this_featurizer_source_fullpath = path.join(featurizer_source_dir)
assert path.isdir(this_featurizer_source_fullpath), this_featurizer_source_fullpath
copytree(this_featurizer_source_fullpath, featurizer_dest_dir)
packages.append("onnxruntime.FeaturizersLibrary.Data.{}".format(item))
package_data[packages[-1]] = listdir(path.join(featurizer_dest_dir, item))
package_data["onnxruntime"] = data + examples + extra
version_number = ''
with open('VERSION_NUMBER') as f:
version_number = f.readline().strip()
if nightly_build:
#https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables
build_suffix = environ.get('BUILD_BUILDNUMBER')
if build_suffix is None:
#The following line is only for local testing
build_suffix = str(datetime.datetime.now().date().strftime("%Y%m%d"))
else:
build_suffix = build_suffix.replace('.','')
version_number = version_number + ".dev" + build_suffix
if wheel_name_suffix:
package_name = "{}_{}".format(package_name, wheel_name_suffix)
cmd_classes = {}
if bdist_wheel is not None :
cmd_classes['bdist_wheel'] = bdist_wheel
cmd_classes['build_ext'] = build_ext
requirements_path = path.join(getcwd(), "requirements.txt")
if not path.exists(requirements_path):
this = path.dirname(__file__)
requirements_path = path.join(this, "requirements.txt")
if not path.exists(requirements_path):
raise FileNotFoundError("Unable to find 'requirements.txt'")
with open(requirements_path) as f:
install_requires = f.read().splitlines()
# Setup
setup(
name=package_name,
version=version_number,
description='ONNX Runtime is a runtime accelerator for Machine Learning models',
long_description=long_description,
author='Microsoft Corporation',
author_email='onnxruntime@microsoft.com',
cmdclass=cmd_classes,
license="MIT License",
packages=packages,
ext_modules=ext_modules,
package_data=package_data,
url="https://onnxruntime.ai",
download_url='https://github.com/microsoft/onnxruntime/tags',
data_files=data_files,
install_requires=install_requires,
keywords='onnx machine learning',
entry_points= {
'console_scripts': [
'onnxruntime_test = onnxruntime.tools.onnxruntime_test:main',
]
},
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS',
'Topic :: Scientific/Engineering',
'Topic :: Scientific/Engineering :: Mathematics',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
'Topic :: Software Development',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
'Programming Language :: Python',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9'],
)