microsoft/onnxruntime-extensions

Public

mirrored from https://github.com/microsoft/onnxruntime-extensionsAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
b603c0283aa82e3e6afc10d42e36b4a0f73640d3

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

setup.py

273lines · modecode

1# -*- coding: utf-8 -*-
2# Copyright (c) Microsoft Corporation. All rights reserved.
3# Licensed under the MIT License. See License.txt in the project root for
4# license information.
5###########################################################################
6
7from setuptools import setup, find_packages
8from setuptools.command.build import build as _build
9from setuptools.command.build_ext import build_ext as _build_ext
10
11import re
12import os
13import sys
14import setuptools
15import pathlib
16import subprocess
17
18from textwrap import dedent
19
20TOP_DIR = os.path.dirname(__file__) or os.getcwd()
21PACKAGE_NAME = 'onnxruntime_extensions'
22VSINSTALLDIR_NAME = 'VSINSTALLDIR'
23
24
25def load_vsdevcmd():
26 if os.environ.get(VSINSTALLDIR_NAME) is None:
27 stdout, _ = subprocess.Popen([
28 'powershell', ' -noprofile', '-executionpolicy',
29 'bypass', '-f', TOP_DIR + '/tools/get_vsdevcmd.ps1', '-outputEnv', '1'],
30 stdout=subprocess.PIPE, shell=False, universal_newlines=True).communicate()
31 for line in stdout.splitlines():
32 kv_pair = line.split('=')
33 if len(kv_pair) == 2:
34 os.environ[kv_pair[0]] = kv_pair[1]
35 else:
36 import shutil
37 if shutil.which('cmake') is None:
38 raise SystemExit(
39 "Cannot find cmake in the executable path, "
40 "please run this script under Developer Command Prompt for VS.")
41
42
43def read_git_refs():
44 release_branch = False
45 stdout, _ = subprocess.Popen(
46 ['git'] + ['log', '-1', '--format=%H'],
47 cwd=TOP_DIR,
48 stdout=subprocess.PIPE, universal_newlines=True).communicate()
49 HEAD = dedent(stdout.splitlines()[0]).strip('\n\r')
50 stdout, _ = subprocess.Popen(
51 ['git'] + ['show-ref', '--head'],
52 cwd=TOP_DIR,
53 stdout=subprocess.PIPE, universal_newlines=True).communicate()
54 for _ln in stdout.splitlines():
55 _ln = dedent(_ln).strip('\n\r')
56 if _ln.startswith(HEAD):
57 _, _2 = _ln.split(' ')
58 if _2.startswith('refs/remotes/origin/rel-'):
59 release_branch = True
60 return release_branch, HEAD
61
62
63class BuildCMakeExt(_build_ext):
64
65 def run(self):
66 """
67 Perform build_cmake before doing the 'normal' stuff
68 """
69 for extension in self.extensions:
70 if extension.name == 'onnxruntime_extensions._extensions_pydll':
71 self.build_cmake(extension)
72
73 def build_cmake(self, extension):
74 project_dir = pathlib.Path().absolute()
75 build_temp = pathlib.Path(self.build_temp)
76 build_temp.mkdir(parents=True, exist_ok=True)
77 ext_fullpath = pathlib.Path(self.get_ext_fullpath(extension.name))
78
79 config = 'RelWithDebInfo' if self.debug else 'Release'
80 cmake_args = [
81 '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + str(ext_fullpath.parent.absolute()),
82 '-DOCOS_BUILD_PYTHON=ON',
83 '-DOCOS_EXTENTION_NAME=' + ext_fullpath.name,
84 '-DCMAKE_BUILD_TYPE=' + config
85 ]
86
87 if os.environ.get('OCOS_NO_OPENCV') == '1':
88 # Disabling openCV can drastically reduce the build time.
89 cmake_args += [
90 '-DOCOS_ENABLE_CTEST=OFF',
91 '-DOCOS_ENABLE_OPENCV_CODECS=OFF',
92 '-DOCOS_ENABLE_CV2=OFF',
93 '-DOCOS_ENABLE_VISION=OFF']
94
95 # CMake lets you override the generator - we need to check this.
96 # Can be set with Conda-Build, for example.
97 cmake_generator = os.environ.get("CMAKE_GENERATOR", "")
98 # Adding CMake arguments set as environment variable
99 # (needed e.g. to build for ARM OSx on conda-forge)
100 if "CMAKE_ARGS" in os.environ:
101 cmake_args += [item for item in os.environ["CMAKE_ARGS"].split(" ") if item]
102
103 if sys.platform != "win32":
104 # Using Ninja-build since it a) is available as a wheel and b)
105 # multithreads automatically. MSVC would require all variables be
106 # exported for Ninja to pick it up, which is a little tricky to do.
107 # Users can override the generator with CMAKE_GENERATOR in CMake
108 # 3.15+.
109 if not cmake_generator or cmake_generator == "Ninja":
110 try:
111 import ninja # noqa: F401
112
113 ninja_executable_path = os.path.join(ninja.BIN_DIR, "ninja")
114 cmake_args += [
115 "-GNinja",
116 f"-DCMAKE_MAKE_PROGRAM:FILEPATH={ninja_executable_path}",
117 ]
118 except ImportError:
119 pass
120
121 if sys.platform.startswith("darwin"):
122 # Cross-compile support for macOS - respect ARCHFLAGS if set
123 archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", ""))
124 if archs:
125 cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))]
126
127 # overwrite the Python module info if the auto-detection doesn't work.
128 # export Python3_INCLUDE_DIRS=/opt/python/cp38-cp38
129 # export Python3_LIBRARIES=/opt/python/cp38-cp38
130 for env in ['Python3_INCLUDE_DIRS', 'Python3_LIBRARIES']:
131 if env in os.environ:
132 cmake_args.append("-D%s=%s" % (env, os.environ[env]))
133
134 if self.debug:
135 cmake_args += ['-DCC_OPTIMIZE=OFF']
136
137 # the parallel build has to be limited on some Linux VM machine.
138 cpu_number = os.environ.get('CPU_NUMBER')
139 build_args = [
140 '--config', config,
141 '--parallel' + ('' if cpu_number is None else ' ' + cpu_number)
142 ]
143 cmake_exe = 'cmake'
144 # unlike Linux/macOS, cmake pip package on Windows fails to build some 3rd party dependencies.
145 # so we have to use the cmake installed from Visual Studio.
146 if os.environ.get(VSINSTALLDIR_NAME):
147 cmake_exe = os.environ[VSINSTALLDIR_NAME] + \
148 'Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\bin\\cmake.exe'
149
150 self.spawn([cmake_exe, '-S', str(project_dir), '-B', str(build_temp)] + cmake_args)
151 if not self.dry_run:
152 self.spawn([cmake_exe, '--build', str(build_temp)] + build_args)
153
154 if sys.platform == "win32":
155 config_dir = '.'
156 if not (build_temp / 'build.ninja').exists():
157 config_dir = config
158 self.copy_file(build_temp / 'bin' / config_dir / 'extensions_pydll.dll', ext_fullpath,
159 link='hard' if self.debug else None)
160 else:
161 self.copy_file(build_temp / 'lib' / ext_fullpath.name, ext_fullpath,
162 link='sym' if self.debug else None)
163
164
165class Build(_build):
166 def initialize_options(self) -> None:
167 super().initialize_options()
168 if os.environ.get('OCOS_SCB_DEBUG', None) == '1':
169 self.debug = True
170
171 def finalize_options(self) -> None:
172 # There is a bug in setuptools that prevents the build get the right platform name from arguments.
173 # So, it cannot generate the correct wheel with the right arch in Official release pipeline.
174 # Force plat_name to be 'win-amd64' in Windows to fix that.
175 # Since extensions cmake is only available on x64 for Windows now, it is not a problem to hardcode it.
176 if sys.platform == "win32" and "arm" not in sys.version.lower():
177 self.plat_name = "win-amd64"
178 super().finalize_options()
179
180
181def read_requirements():
182 with open(os.path.join(TOP_DIR, "requirements.txt"), "r", encoding="utf-8") as f:
183 requirements = [_ for _ in [dedent(_) for _ in f.readlines()] if _ is not None]
184 return requirements
185
186
187# read version from the package file.
188def read_version():
189 version_str = '1.0.0'
190 with (open(os.path.join(TOP_DIR, 'version.txt'), "r")) as f:
191 version_str = f.readline().strip()
192
193 # special handling for Onebranch building
194 if os.getenv('BUILD_SOURCEBRANCHNAME', "").startswith('rel-'):
195 return version_str
196
197 # is it a dev build or release?
198 rel_br, cid = read_git_refs() if os.path.isdir(
199 os.path.join(TOP_DIR, '.git')) else (True, None)
200
201 if rel_br:
202 return version_str
203
204 build_id = os.getenv('BUILD_BUILDID', None)
205 if build_id is not None:
206 version_str += '.{}'.format(build_id)
207 else:
208 version_str += '+' + cid[:7]
209 return version_str
210
211
212def write_py_version(ortx_version):
213 text = ["# Generated by setup.py, DON'T MANUALLY UPDATE IT!\n",
214 "__version__ = \"{}\"\n".format(ortx_version)]
215 with (open(os.path.join(TOP_DIR, 'onnxruntime_extensions/_version.py'), "w")) as _f:
216 _f.writelines(text)
217
218
219if sys.platform == "win32":
220 load_vsdevcmd()
221
222ext_modules = [
223 setuptools.extension.Extension(
224 name=str('onnxruntime_extensions._extensions_pydll'),
225 sources=[])
226]
227
228packages = find_packages()
229package_dir = {k: os.path.join('.', k.replace(".", "/")) for k in packages}
230package_data = {
231 "onnxruntime_extensions": ["*.so", "*.pyd"],
232}
233
234long_description = ''
235with open(os.path.join(TOP_DIR, "README.md"), 'r', encoding="utf-8") as _f:
236 long_description += _f.read()
237 start_pos = long_description.find('# Introduction')
238 start_pos = 0 if start_pos < 0 else start_pos
239 end_pos = long_description.find('# Contributing')
240 long_description = long_description[start_pos:end_pos]
241ortx_version = read_version()
242write_py_version(ortx_version)
243
244setup(
245 name=PACKAGE_NAME,
246 version=ortx_version,
247 packages=packages,
248 package_dir=package_dir,
249 package_data=package_data,
250 description="ONNXRuntime Extensions",
251 long_description=long_description,
252 long_description_content_type='text/markdown',
253 license='MIT License',
254 author='Microsoft Corporation',
255 author_email='onnxruntime@microsoft.com',
256 url='https://github.com/microsoft/onnxruntime-extensions',
257 ext_modules=ext_modules,
258 cmdclass=dict(build_ext=BuildCMakeExt, build=Build),
259 include_package_data=True,
260 install_requires=read_requirements(),
261 classifiers=[
262 'Development Status :: 4 - Beta',
263 'Environment :: Console',
264 'Intended Audience :: Developers',
265 'Operating System :: MacOS :: MacOS X',
266 'Operating System :: Microsoft :: Windows',
267 'Operating System :: POSIX :: Linux',
268 "Programming Language :: C++",
269 'Programming Language :: Python',
270 "Programming Language :: Python :: Implementation :: CPython",
271 'License :: OSI Approved :: MIT License'
272 ]
273)