setup.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. # Copyright 2015 gRPC authors.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """A setup module for the GRPC Python package."""
  15. # setuptools need to be imported before distutils. Otherwise it might lead to
  16. # undesirable behaviors or errors.
  17. import setuptools
  18. # Monkey Patch the unix compiler to accept ASM
  19. # files used by boring SSL.
  20. from distutils.unixccompiler import UnixCCompiler
  21. UnixCCompiler.src_extensions.append('.S')
  22. del UnixCCompiler
  23. from distutils import cygwinccompiler
  24. from distutils import extension as _extension
  25. from distutils import util
  26. import os
  27. import os.path
  28. import pkg_resources
  29. import platform
  30. import re
  31. import shlex
  32. import shutil
  33. import sys
  34. import sysconfig
  35. from setuptools.command import egg_info
  36. import subprocess
  37. from subprocess import PIPE
  38. # Redirect the manifest template from MANIFEST.in to PYTHON-MANIFEST.in.
  39. egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
  40. PY3 = sys.version_info.major == 3
  41. PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
  42. CORE_INCLUDE = (
  43. 'include',
  44. '.',
  45. )
  46. ABSL_INCLUDE = (os.path.join('third_party', 'abseil-cpp'),)
  47. ADDRESS_SORTING_INCLUDE = (os.path.join('third_party', 'address_sorting',
  48. 'include'),)
  49. CARES_INCLUDE = (
  50. os.path.join('third_party', 'cares'),
  51. os.path.join('third_party', 'cares', 'cares'),
  52. )
  53. if 'darwin' in sys.platform:
  54. CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
  55. if 'freebsd' in sys.platform:
  56. CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_freebsd'),)
  57. if 'linux' in sys.platform:
  58. CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
  59. if 'openbsd' in sys.platform:
  60. CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_openbsd'),)
  61. RE2_INCLUDE = (os.path.join('third_party', 're2'),)
  62. SSL_INCLUDE = (os.path.join('third_party', 'boringssl-with-bazel', 'src',
  63. 'include'),)
  64. UPB_INCLUDE = (os.path.join('third_party', 'upb'),)
  65. UPB_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext',
  66. 'upb-generated'),)
  67. UPBDEFS_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext',
  68. 'upbdefs-generated'),)
  69. ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
  70. README = os.path.join(PYTHON_STEM, 'README.rst')
  71. # Ensure we're in the proper directory whether or not we're being used by pip.
  72. os.chdir(os.path.dirname(os.path.abspath(__file__)))
  73. sys.path.insert(0, os.path.abspath(PYTHON_STEM))
  74. # Break import-style to ensure we can actually find our in-repo dependencies.
  75. import _parallel_compile_patch
  76. import _spawn_patch
  77. import commands
  78. import grpc_core_dependencies
  79. import grpc_version
  80. _parallel_compile_patch.monkeypatch_compile_maybe()
  81. _spawn_patch.monkeypatch_spawn()
  82. LICENSE = 'Apache License 2.0'
  83. CLASSIFIERS = [
  84. 'Development Status :: 5 - Production/Stable',
  85. 'Programming Language :: Python',
  86. 'Programming Language :: Python :: 2',
  87. 'Programming Language :: Python :: 2.7',
  88. 'Programming Language :: Python :: 3',
  89. 'Programming Language :: Python :: 3.5',
  90. 'Programming Language :: Python :: 3.6',
  91. 'Programming Language :: Python :: 3.7',
  92. 'Programming Language :: Python :: 3.8',
  93. 'Programming Language :: Python :: 3.9',
  94. 'License :: OSI Approved :: Apache Software License',
  95. ]
  96. def _env_bool_value(env_name, default):
  97. """Parses a bool option from an environment variable"""
  98. return os.environ.get(env_name, default).upper() not in ['FALSE', '0', '']
  99. BUILD_WITH_BORING_SSL_ASM = _env_bool_value('GRPC_BUILD_WITH_BORING_SSL_ASM',
  100. 'True')
  101. # Export this environment variable to override the platform variant that will
  102. # be chosen for boringssl assembly optimizations. This option is useful when
  103. # crosscompiling and the host platform as obtained by distutils.utils.get_platform()
  104. # doesn't match the platform we are targetting.
  105. # Example value: "linux-aarch64"
  106. BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM = os.environ.get(
  107. 'GRPC_BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM', '')
  108. # Environment variable to determine whether or not the Cython extension should
  109. # *use* Cython or use the generated C files. Note that this requires the C files
  110. # to have been generated by building first *with* Cython support. Even if this
  111. # is set to false, if the script detects that the generated `.c` file isn't
  112. # present, then it will still attempt to use Cython.
  113. BUILD_WITH_CYTHON = _env_bool_value('GRPC_PYTHON_BUILD_WITH_CYTHON', 'False')
  114. # Export this variable to use the system installation of openssl. You need to
  115. # have the header files installed (in /usr/include/openssl) and during
  116. # runtime, the shared library must be installed
  117. BUILD_WITH_SYSTEM_OPENSSL = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_OPENSSL',
  118. 'False')
  119. # Export this variable to use the system installation of zlib. You need to
  120. # have the header files installed (in /usr/include/) and during
  121. # runtime, the shared library must be installed
  122. BUILD_WITH_SYSTEM_ZLIB = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_ZLIB',
  123. 'False')
  124. # Export this variable to use the system installation of cares. You need to
  125. # have the header files installed (in /usr/include/) and during
  126. # runtime, the shared library must be installed
  127. BUILD_WITH_SYSTEM_CARES = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_CARES',
  128. 'False')
  129. # Export this variable to use the system installation of re2. You need to
  130. # have the header files installed (in /usr/include/re2) and during
  131. # runtime, the shared library must be installed
  132. BUILD_WITH_SYSTEM_RE2 = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_RE2', 'False')
  133. # Export this variable to force building the python extension with a statically linked libstdc++.
  134. # At least on linux, this is normally not needed as we can build manylinux-compatible wheels on linux just fine
  135. # without statically linking libstdc++ (which leads to a slight increase in the wheel size).
  136. # This option is useful when crosscompiling wheels for aarch64 where
  137. # it's difficult to ensure that the crosscompilation toolchain has a high-enough version
  138. # of GCC (we require >4.9) but still uses old-enough libstdc++ symbols.
  139. # TODO(jtattermusch): remove this workaround once issues with crosscompiler version are resolved.
  140. BUILD_WITH_STATIC_LIBSTDCXX = _env_bool_value(
  141. 'GRPC_PYTHON_BUILD_WITH_STATIC_LIBSTDCXX', 'False')
  142. # For local development use only: This skips building gRPC Core and its
  143. # dependencies, including protobuf and boringssl. This allows "incremental"
  144. # compilation by first building gRPC Core using make, then building only the
  145. # Python/Cython layers here.
  146. #
  147. # Note that this requires libboringssl.a in the libs/{dbg,opt}/ directory, which
  148. # may require configuring make to not use the system openssl implementation:
  149. #
  150. # make HAS_SYSTEM_OPENSSL_ALPN=0
  151. #
  152. # TODO(ericgribkoff) Respect the BUILD_WITH_SYSTEM_* flags alongside this option
  153. USE_PREBUILT_GRPC_CORE = _env_bool_value('GRPC_PYTHON_USE_PREBUILT_GRPC_CORE',
  154. 'False')
  155. # If this environmental variable is set, GRPC will not try to be compatible with
  156. # libc versions old than the one it was compiled against.
  157. DISABLE_LIBC_COMPATIBILITY = _env_bool_value(
  158. 'GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', 'False')
  159. # Environment variable to determine whether or not to enable coverage analysis
  160. # in Cython modules.
  161. ENABLE_CYTHON_TRACING = _env_bool_value('GRPC_PYTHON_ENABLE_CYTHON_TRACING',
  162. 'False')
  163. # Environment variable specifying whether or not there's interest in setting up
  164. # documentation building.
  165. ENABLE_DOCUMENTATION_BUILD = _env_bool_value(
  166. 'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', 'False')
  167. def check_linker_need_libatomic():
  168. """Test if linker on system needs libatomic."""
  169. code_test = (b'#include <atomic>\n' +
  170. b'int main() { return std::atomic<int64_t>{}; }')
  171. cxx = os.environ.get('CXX', 'c++')
  172. cpp_test = subprocess.Popen([cxx, '-x', 'c++', '-std=c++11', '-'],
  173. stdin=PIPE,
  174. stdout=PIPE,
  175. stderr=PIPE)
  176. cpp_test.communicate(input=code_test)
  177. if cpp_test.returncode == 0:
  178. return False
  179. # Double-check to see if -latomic actually can solve the problem.
  180. # https://github.com/grpc/grpc/issues/22491
  181. cpp_test = subprocess.Popen(
  182. [cxx, '-x', 'c++', '-std=c++11', '-latomic', '-'],
  183. stdin=PIPE,
  184. stdout=PIPE,
  185. stderr=PIPE)
  186. cpp_test.communicate(input=code_test)
  187. return cpp_test.returncode == 0
  188. # There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are
  189. # entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
  190. # We use these environment variables to thus get around that without locking
  191. # ourselves in w.r.t. the multitude of operating systems this ought to build on.
  192. # We can also use these variables as a way to inject environment-specific
  193. # compiler/linker flags. We assume GCC-like compilers and/or MinGW as a
  194. # reasonable default.
  195. EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
  196. EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
  197. if EXTRA_ENV_COMPILE_ARGS is None:
  198. EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
  199. if 'win32' in sys.platform:
  200. if sys.version_info < (3, 5):
  201. EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
  202. # We use define flags here and don't directly add to DEFINE_MACROS below to
  203. # ensure that the expert user/builder has a way of turning it off (via the
  204. # envvars) without adding yet more GRPC-specific envvars.
  205. # See https://sourceforge.net/p/mingw-w64/bugs/363/
  206. if '32' in platform.architecture()[0]:
  207. EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
  208. else:
  209. EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
  210. else:
  211. # We need to statically link the C++ Runtime, only the C runtime is
  212. # available dynamically
  213. EXTRA_ENV_COMPILE_ARGS += ' /MT'
  214. elif "linux" in sys.platform:
  215. EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
  216. elif "darwin" in sys.platform:
  217. EXTRA_ENV_COMPILE_ARGS += ' -stdlib=libc++ -fvisibility=hidden -fno-wrapv -fno-exceptions'
  218. if EXTRA_ENV_LINK_ARGS is None:
  219. EXTRA_ENV_LINK_ARGS = ''
  220. if "linux" in sys.platform or "darwin" in sys.platform:
  221. EXTRA_ENV_LINK_ARGS += ' -lpthread'
  222. if check_linker_need_libatomic():
  223. EXTRA_ENV_LINK_ARGS += ' -latomic'
  224. elif "win32" in sys.platform and sys.version_info < (3, 5):
  225. msvcr = cygwinccompiler.get_msvcr()[0]
  226. EXTRA_ENV_LINK_ARGS += (
  227. ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr}'
  228. ' -static -lshlwapi'.format(msvcr=msvcr))
  229. if "linux" in sys.platform:
  230. EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy -static-libgcc'
  231. EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
  232. EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)
  233. if BUILD_WITH_STATIC_LIBSTDCXX:
  234. EXTRA_LINK_ARGS.append('-static-libstdc++')
  235. CYTHON_EXTENSION_PACKAGE_NAMES = ()
  236. CYTHON_EXTENSION_MODULE_NAMES = ('grpc._cython.cygrpc',)
  237. CYTHON_HELPER_C_FILES = ()
  238. CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
  239. if "win32" in sys.platform:
  240. CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
  241. if BUILD_WITH_SYSTEM_OPENSSL:
  242. CORE_C_FILES = filter(lambda x: 'third_party/boringssl' not in x,
  243. CORE_C_FILES)
  244. CORE_C_FILES = filter(lambda x: 'src/boringssl' not in x, CORE_C_FILES)
  245. SSL_INCLUDE = (os.path.join('/usr', 'include', 'openssl'),)
  246. if BUILD_WITH_SYSTEM_ZLIB:
  247. CORE_C_FILES = filter(lambda x: 'third_party/zlib' not in x, CORE_C_FILES)
  248. ZLIB_INCLUDE = (os.path.join('/usr', 'include'),)
  249. if BUILD_WITH_SYSTEM_CARES:
  250. CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
  251. CARES_INCLUDE = (os.path.join('/usr', 'include'),)
  252. if BUILD_WITH_SYSTEM_RE2:
  253. CORE_C_FILES = filter(lambda x: 'third_party/re2' not in x, CORE_C_FILES)
  254. RE2_INCLUDE = (os.path.join('/usr', 'include', 're2'),)
  255. EXTENSION_INCLUDE_DIRECTORIES = ((PYTHON_STEM,) + CORE_INCLUDE + ABSL_INCLUDE +
  256. ADDRESS_SORTING_INCLUDE + CARES_INCLUDE +
  257. RE2_INCLUDE + SSL_INCLUDE + UPB_INCLUDE +
  258. UPB_GRPC_GENERATED_INCLUDE +
  259. UPBDEFS_GRPC_GENERATED_INCLUDE + ZLIB_INCLUDE)
  260. EXTENSION_LIBRARIES = ()
  261. if "linux" in sys.platform:
  262. EXTENSION_LIBRARIES += ('rt',)
  263. if not "win32" in sys.platform:
  264. EXTENSION_LIBRARIES += ('m',)
  265. if "win32" in sys.platform:
  266. EXTENSION_LIBRARIES += (
  267. 'advapi32',
  268. 'ws2_32',
  269. 'dbghelp',
  270. )
  271. if BUILD_WITH_SYSTEM_OPENSSL:
  272. EXTENSION_LIBRARIES += (
  273. 'ssl',
  274. 'crypto',
  275. )
  276. if BUILD_WITH_SYSTEM_ZLIB:
  277. EXTENSION_LIBRARIES += ('z',)
  278. if BUILD_WITH_SYSTEM_CARES:
  279. EXTENSION_LIBRARIES += ('cares',)
  280. if BUILD_WITH_SYSTEM_RE2:
  281. EXTENSION_LIBRARIES += ('re2',)
  282. DEFINE_MACROS = (('_WIN32_WINNT', 0x600),)
  283. asm_files = []
  284. asm_key = ''
  285. if BUILD_WITH_BORING_SSL_ASM and not BUILD_WITH_SYSTEM_OPENSSL:
  286. boringssl_asm_platform = BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM if BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM else util.get_platform(
  287. )
  288. LINUX_X86_64 = 'linux-x86_64'
  289. LINUX_ARM = 'linux-arm'
  290. LINUX_AARCH64 = 'linux-aarch64'
  291. if LINUX_X86_64 == boringssl_asm_platform:
  292. asm_key = 'crypto_linux_x86_64'
  293. elif LINUX_ARM == boringssl_asm_platform:
  294. asm_key = 'crypto_linux_arm'
  295. elif LINUX_AARCH64 == boringssl_asm_platform:
  296. asm_key = 'crypto_linux_aarch64'
  297. elif "mac" in boringssl_asm_platform and "x86_64" in boringssl_asm_platform:
  298. asm_key = 'crypto_mac_x86_64'
  299. else:
  300. print("ASM Builds for BoringSSL currently not supported on:",
  301. boringssl_asm_platform)
  302. if asm_key:
  303. asm_files = grpc_core_dependencies.ASM_SOURCE_FILES[asm_key]
  304. else:
  305. DEFINE_MACROS += (('OPENSSL_NO_ASM', 1),)
  306. if not DISABLE_LIBC_COMPATIBILITY:
  307. DEFINE_MACROS += (('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
  308. if "win32" in sys.platform:
  309. # TODO(zyc): Re-enable c-ares on x64 and x86 windows after fixing the
  310. # ares_library_init compilation issue
  311. DEFINE_MACROS += (
  312. ('WIN32_LEAN_AND_MEAN', 1),
  313. ('CARES_STATICLIB', 1),
  314. ('GRPC_ARES', 0),
  315. ('NTDDI_VERSION', 0x06000000),
  316. ('NOMINMAX', 1),
  317. )
  318. if '64bit' in platform.architecture()[0]:
  319. DEFINE_MACROS += (('MS_WIN64', 1),)
  320. elif sys.version_info >= (3, 5):
  321. # For some reason, this is needed to get access to inet_pton/inet_ntop
  322. # on msvc, but only for 32 bits
  323. DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),)
  324. else:
  325. DEFINE_MACROS += (
  326. ('HAVE_CONFIG_H', 1),
  327. ('GRPC_ENABLE_FORK_SUPPORT', 1),
  328. )
  329. LDFLAGS = tuple(EXTRA_LINK_ARGS)
  330. CFLAGS = tuple(EXTRA_COMPILE_ARGS)
  331. if "linux" in sys.platform or "darwin" in sys.platform:
  332. pymodinit_type = 'PyObject*' if PY3 else 'void'
  333. pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(
  334. pymodinit_type)
  335. DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
  336. DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
  337. # By default, Python3 distutils enforces compatibility of
  338. # c plugins (.so files) with the OSX version Python was built with.
  339. # We need OSX 10.10, the oldest which supports C++ thread_local.
  340. # Python 3.9: Mac OS Big Sur sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') returns int (11)
  341. if 'darwin' in sys.platform:
  342. mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
  343. if mac_target:
  344. mac_target = pkg_resources.parse_version(str(mac_target))
  345. if mac_target < pkg_resources.parse_version('10.10.0'):
  346. os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.10'
  347. os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
  348. r'macosx-[0-9]+\.[0-9]+-(.+)', r'macosx-10.10-\1',
  349. util.get_platform())
  350. def cython_extensions_and_necessity():
  351. cython_module_files = [
  352. os.path.join(PYTHON_STEM,
  353. name.replace('.', '/') + '.pyx')
  354. for name in CYTHON_EXTENSION_MODULE_NAMES
  355. ]
  356. config = os.environ.get('CONFIG', 'opt')
  357. prefix = 'libs/' + config + '/'
  358. if USE_PREBUILT_GRPC_CORE:
  359. extra_objects = [
  360. prefix + 'libares.a', prefix + 'libboringssl.a',
  361. prefix + 'libgpr.a', prefix + 'libgrpc.a'
  362. ]
  363. core_c_files = []
  364. else:
  365. core_c_files = list(CORE_C_FILES)
  366. extra_objects = []
  367. extensions = [
  368. _extension.Extension(
  369. name=module_name,
  370. sources=([module_file] + list(CYTHON_HELPER_C_FILES) +
  371. core_c_files + asm_files),
  372. include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
  373. libraries=list(EXTENSION_LIBRARIES),
  374. define_macros=list(DEFINE_MACROS),
  375. extra_objects=extra_objects,
  376. extra_compile_args=list(CFLAGS),
  377. extra_link_args=list(LDFLAGS),
  378. ) for (module_name, module_file
  379. ) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
  380. ]
  381. need_cython = BUILD_WITH_CYTHON
  382. if not BUILD_WITH_CYTHON:
  383. need_cython = need_cython or not commands.check_and_update_cythonization(
  384. extensions)
  385. # TODO: the strategy for conditional compiling and exposing the aio Cython
  386. # dependencies will be revisited by https://github.com/grpc/grpc/issues/19728
  387. return commands.try_cythonize(extensions,
  388. linetracing=ENABLE_CYTHON_TRACING,
  389. mandatory=BUILD_WITH_CYTHON), need_cython
  390. CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity()
  391. PACKAGE_DIRECTORIES = {
  392. '': PYTHON_STEM,
  393. }
  394. INSTALL_REQUIRES = (
  395. "six>=1.5.2",
  396. "futures>=2.2.0; python_version<'3.2'",
  397. "enum34>=1.0.4; python_version<'3.4'",
  398. )
  399. EXTRAS_REQUIRES = {
  400. 'protobuf': 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
  401. }
  402. SETUP_REQUIRES = INSTALL_REQUIRES + (
  403. 'Sphinx~=1.8.1',
  404. 'six>=1.10',
  405. ) if ENABLE_DOCUMENTATION_BUILD else ()
  406. try:
  407. import Cython
  408. except ImportError:
  409. if BUILD_WITH_CYTHON:
  410. sys.stderr.write(
  411. "You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
  412. "but do not have Cython installed. We won't stop you from using "
  413. "other commands, but the extension files will fail to build.\n")
  414. elif need_cython:
  415. sys.stderr.write(
  416. 'We could not find Cython. Setup may take 10-20 minutes.\n')
  417. SETUP_REQUIRES += ('cython>=0.23',)
  418. COMMAND_CLASS = {
  419. 'doc': commands.SphinxDocumentation,
  420. 'build_project_metadata': commands.BuildProjectMetadata,
  421. 'build_py': commands.BuildPy,
  422. 'build_ext': commands.BuildExt,
  423. 'gather': commands.Gather,
  424. 'clean': commands.Clean,
  425. }
  426. # Ensure that package data is copied over before any commands have been run:
  427. credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials')
  428. try:
  429. os.mkdir(credentials_dir)
  430. except OSError:
  431. pass
  432. shutil.copyfile(os.path.join('etc', 'roots.pem'),
  433. os.path.join(credentials_dir, 'roots.pem'))
  434. PACKAGE_DATA = {
  435. # Binaries that may or may not be present in the final installation, but are
  436. # mentioned here for completeness.
  437. 'grpc._cython': [
  438. '_credentials/roots.pem',
  439. '_windows/grpc_c.32.python',
  440. '_windows/grpc_c.64.python',
  441. ],
  442. }
  443. PACKAGES = setuptools.find_packages(PYTHON_STEM)
  444. setuptools.setup(
  445. name='grpcio',
  446. version=grpc_version.VERSION,
  447. description='HTTP/2-based RPC framework',
  448. author='The gRPC Authors',
  449. author_email='grpc-io@googlegroups.com',
  450. url='https://grpc.io',
  451. license=LICENSE,
  452. classifiers=CLASSIFIERS,
  453. long_description=open(README).read(),
  454. ext_modules=CYTHON_EXTENSION_MODULES,
  455. packages=list(PACKAGES),
  456. package_dir=PACKAGE_DIRECTORIES,
  457. package_data=PACKAGE_DATA,
  458. install_requires=INSTALL_REQUIRES,
  459. extras_require=EXTRAS_REQUIRES,
  460. setup_requires=SETUP_REQUIRES,
  461. cmdclass=COMMAND_CLASS,
  462. )