onnx-simplifier
/
setup.py
315 строк · 10.8 Кб
1from distutils.spawn import find_executable2from distutils import sysconfig, log3import setuptools4import setuptools.command.build_py5import setuptools.command.develop6import setuptools.command.build_ext7
8from collections import namedtuple9from contextlib import contextmanager10import glob11import os12import shlex13import subprocess14import sys15import platform16from textwrap import dedent17import multiprocessing18import re19
20
21TOP_DIR = os.path.realpath(os.path.dirname(__file__))22SRC_DIR = os.path.join(TOP_DIR, 'onnxsim')23CMAKE_BUILD_DIR = os.path.join(TOP_DIR, '.setuptools-cmake-build')24
25WINDOWS = (os.name == 'nt')26MACOS = sys.platform.startswith("darwin")27
28CMAKE = find_executable('cmake')29
30install_requires = []31setup_requires = []32
33USE_MSVC_STATIC_RUNTIME = bool(os.getenv('USE_MSVC_STATIC_RUNTIME', '0') == '1')34ONNX_ML = not bool(os.getenv('ONNX_ML') == '0')35ONNX_VERIFY_PROTO3 = bool(os.getenv('ONNX_VERIFY_PROTO3') == '1')36ONNX_NAMESPACE = os.getenv('ONNX_NAMESPACE', 'onnx')37ONNX_BUILD_TESTS = bool(os.getenv('ONNX_BUILD_TESTS') == '1')38ONNX_OPT_USE_SYSTEM_PROTOBUF = bool(os.getenv('ONNX_OPT_USE_SYSTEM_PROTOBUF', '0') == '1')39
40DEBUG = bool(os.getenv('DEBUG'))41COVERAGE = bool(os.getenv('COVERAGE'))42
43try:44version = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0'],45cwd=TOP_DIR).decode('ascii').strip()46if version[0] == 'v':47version = version[1:]48except (OSError, subprocess.CalledProcessError):49with open(os.path.join(TOP_DIR, 'VERSION')) as ver_file:50version = ver_file.read().strip()51
52try:53git_version = subprocess.check_output(['git', 'rev-parse', 'HEAD'],54cwd=TOP_DIR).decode('ascii').strip()55except (OSError, subprocess.CalledProcessError):56git_version = None57
58if os.getenv('ONNXSIM_SDIST') is not None:59version = '0.0.0'60git_version = None61
62VersionInfo = namedtuple('VersionInfo', ['version', 'git_version'])(63version=version,64git_version=git_version65)
66
67assert CMAKE, 'Could not find "cmake" executable!'68
69@contextmanager
70def cd(path):71if not os.path.isabs(path):72raise RuntimeError('Can only cd to absolute path, got: {}'.format(path))73orig_path = os.getcwd()74os.chdir(path)75try:76yield77finally:78os.chdir(orig_path)79
80
81class ONNXCommand(setuptools.Command):82user_options = []83
84def initialize_options(self):85pass86
87def finalize_options(self):88pass89
90
91class create_version(ONNXCommand):92def run(self):93with open(os.path.join(SRC_DIR, 'version.py'), 'w') as f:94f.write(dedent('''\95# This file is generated by setup.py. DO NOT EDIT!
96
97version = '{version}'
98git_version = '{git_version}'
99'''.format(**dict(VersionInfo._asdict()))))100
101
102class cmake_build(setuptools.Command):103"""104Compiles everything when `python setupmnm.py build` is run using cmake.
105
106Custom args can be passed to cmake by specifying the `CMAKE_ARGS`
107environment variable.
108
109The number of CPUs used by `make` can be specified by passing `-j<ncpus>`
110to `setup.py build`. By default all CPUs are used.
111"""
112user_options = [113(str('jobs='), str('j'), str('Specifies the number of jobs to use with make'))114]115
116built = False117
118def initialize_options(self):119self.jobs = None120
121def finalize_options(self):122self.set_undefined_options('build', ('parallel', 'jobs'))123if self.jobs is None and os.getenv("MAX_JOBS") is not None:124self.jobs = os.getenv("MAX_JOBS")125self.jobs = multiprocessing.cpu_count() if self.jobs is None else int(self.jobs)126
127def run(self):128if cmake_build.built:129return130cmake_build.built = True131if not os.path.exists(CMAKE_BUILD_DIR):132os.makedirs(CMAKE_BUILD_DIR)133
134with cd(CMAKE_BUILD_DIR):135build_type = 'Release'136# configure137cmake_args = [138CMAKE,139'-DPython_INCLUDE_DIR={}'.format(sysconfig.get_python_inc()),140'-DPython_EXECUTABLE={}'.format(sys.executable),141# For pybind11142'-DPYTHON_EXECUTABLE={}'.format(sys.executable),143'-DBUILD_ONNX_PYTHON=OFF',144'-DONNXSIM_PYTHON=ON',145'-DONNXSIM_BUILTIN_ORT=OFF',146'-DONNX_USE_LITE_PROTO=OFF',147'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',148'-DONNX_NAMESPACE={}'.format(ONNX_NAMESPACE),149'-DPY_EXT_SUFFIX={}'.format(150sysconfig.get_config_var('EXT_SUFFIX') or ''),151'-DONNX_OPT_USE_SYSTEM_PROTOBUF={}'.format(152'ON' if ONNX_OPT_USE_SYSTEM_PROTOBUF else 'OFF'),153]154if COVERAGE:155cmake_args.append('-DONNX_COVERAGE=ON')156if COVERAGE or DEBUG:157# in order to get accurate coverage information, the158# build needs to turn off optimizations159build_type = 'Debug'160cmake_args.append('-DCMAKE_BUILD_TYPE=%s' % build_type)161if WINDOWS:162cmake_args.extend([163# we need to link with libpython on windows, so164# passing python version to window in order to165# find python in cmake166'-DPY_VERSION={}'.format('{0}.{1}'.format(* \167sys.version_info[:2])),168])169if USE_MSVC_STATIC_RUNTIME:170cmake_args.append('-DONNX_USE_MSVC_STATIC_RUNTIME=ON')171if platform.architecture()[0] == '64bit':172cmake_args.extend(['-A', 'x64', '-T', 'host=x64'])173else:174cmake_args.extend(['-A', 'Win32', '-T', 'host=x86'])175if MACOS:176# Cross-compile support for macOS - respect ARCHFLAGS if set177archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", ""))178if archs:179cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))]180if ONNX_ML:181cmake_args.append('-DONNX_ML=1')182if ONNX_VERIFY_PROTO3:183cmake_args.append('-DONNX_VERIFY_PROTO3=1')184if ONNX_BUILD_TESTS:185cmake_args.append('-DONNX_BUILD_TESTS=ON')186if 'CMAKE_ARGS' in os.environ:187extra_cmake_args = shlex.split(os.environ['CMAKE_ARGS'])188# prevent crossfire with downstream scripts189del os.environ['CMAKE_ARGS']190log.info('Extra cmake args: {}'.format(extra_cmake_args))191cmake_args.extend(extra_cmake_args)192cmake_args.append(TOP_DIR)193print(f"Run command {cmake_args}")194subprocess.check_call(cmake_args)195
196build_args = [CMAKE, '--build', os.curdir, '--target onnxsim_cpp2py_export']197if WINDOWS:198build_args.extend(['--config', build_type])199build_args.extend(['--', '/maxcpucount:{}'.format(self.jobs)])200else:201build_args.extend(['--', '-j', str(self.jobs)])202print(f"Run command {build_args}")203subprocess.check_call(build_args)204
205
206class build_py(setuptools.command.build_py.build_py):207def run(self):208self.run_command('create_version')209return setuptools.command.build_py.build_py.run(self)210
211
212class develop(setuptools.command.develop.develop):213def run(self):214self.run_command('build_py')215setuptools.command.develop.develop.run(self)216
217
218class build_ext(setuptools.command.build_ext.build_ext):219def run(self):220self.run_command('cmake_build')221setuptools.command.build_ext.build_ext.run(self)222
223def build_extensions(self):224for ext in self.extensions:225fullname = self.get_ext_fullname(ext.name)226filename = os.path.basename(self.get_ext_filename(fullname))227
228lib_path = CMAKE_BUILD_DIR229if os.name == 'nt':230debug_lib_dir = os.path.join(lib_path, "Debug")231release_lib_dir = os.path.join(lib_path, "Release")232if os.path.exists(debug_lib_dir):233lib_path = debug_lib_dir234elif os.path.exists(release_lib_dir):235lib_path = release_lib_dir236src = os.path.join(lib_path, filename)237dst_dir = os.path.join(os.path.realpath(238self.build_lib), "onnxsim")239dst = os.path.join(dst_dir, filename)240os.makedirs(dst_dir, exist_ok=True)241self.copy_file(src, dst)242
243
244cmdclass = {245'create_version': create_version,246'cmake_build': cmake_build,247'build_ext': build_ext,248'build_py': build_py,249'develop': develop,250}
251
252ext_modules = [253setuptools.Extension(254name=str('onnxsim.onnxsim_cpp2py_export'),255sources=[])256]
257
258# no need to do fancy stuff so far
259packages = setuptools.find_packages()260
261# Though we depend on onnxruntime, it has three different packages:
262# onnxruntime, onnxruntime-gpu and onnxruntime-noopenmp.
263# The solution is, we publish two packages, a wheel named onnxsim-no-ort
264# and a sdist package named onnxsim, onnxsim depends on onnxsim-no-ort,
265# and also check if one of onnxruntime packages is installed, and depends
266# on onnxruntime when no existing installed packages.
267install_requires.extend([268'onnx',269'rich',270])271
272setup_requires.append('pytest-runner')273
274# read the contents of your README file
275from pathlib import Path276this_directory = Path(__file__).parent277long_description = (this_directory / "README.md").read_text()278
279setuptools.setup(280name=os.getenv("ONNXSIM_PKG_NAME", "onnxsim"),281version=VersionInfo.version,282description='Simplify your ONNX model',283ext_modules=ext_modules,284cmdclass=cmdclass,285packages=packages,286license='Apache License v2.0',287include_package_data=True,288install_requires=install_requires,289setup_requires=setup_requires,290author='ONNX Simplifier Authors',291author_email='daquexian566@gmail.com',292url='https://github.com/daquexian/onnx-simplifier',293keywords='deep-learning ONNX',294long_description=long_description,295long_description_content_type='text/markdown',296classifiers=[297'Development Status :: 4 - Beta',298'Intended Audience :: Developers',299'License :: OSI Approved :: Apache Software License',300'Programming Language :: Python :: 3 :: Only',301'Programming Language :: Python :: 3.7',302'Programming Language :: Python :: 3.8',303'Programming Language :: Python :: 3.9',304'Programming Language :: Python :: 3.10',305'Programming Language :: Python :: 3.11',306'Topic :: Scientific/Engineering',307'Topic :: Software Development'308],309python_requires='>=3.7',310entry_points={311'console_scripts': [312'onnxsim=onnxsim:main',313],314},315)
316