setup.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. # Copyright 2015, Google Inc.
  2. # All rights reserved.
  3. #
  4. # Redistribution and use in source and binary forms, with or without
  5. # modification, are permitted provided that the following conditions are
  6. # met:
  7. #
  8. # * Redistributions of source code must retain the above copyright
  9. # notice, this list of conditions and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above
  11. # copyright notice, this list of conditions and the following disclaimer
  12. # in the documentation and/or other materials provided with the
  13. # distribution.
  14. # * Neither the name of Google Inc. nor the names of its
  15. # contributors may be used to endorse or promote products derived from
  16. # this software without specific prior written permission.
  17. #
  18. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. """A setup module for the GRPC Python package."""
  30. from distutils import extension as _extension
  31. from distutils import util
  32. import os
  33. import os.path
  34. import pkg_resources
  35. import platform
  36. import re
  37. import shlex
  38. import shutil
  39. import sys
  40. import sysconfig
  41. import setuptools
  42. from setuptools.command import egg_info
  43. # Redirect the manifest template from MANIFEST.in to PYTHON-MANIFEST.in.
  44. egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
  45. PY3 = sys.version_info.major == 3
  46. PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
  47. CORE_INCLUDE = ('include', '.',)
  48. BORINGSSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),)
  49. ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
  50. CARES_INCLUDE = (
  51. os.path.join('third_party', 'cares'),
  52. os.path.join('third_party', 'cares', 'cares'),)
  53. if 'linux' in sys.platform:
  54. CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
  55. if 'darwin' in sys.platform:
  56. CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
  57. # Ensure we're in the proper directory whether or not we're being used by pip.
  58. os.chdir(os.path.dirname(os.path.abspath(__file__)))
  59. sys.path.insert(0, os.path.abspath(PYTHON_STEM))
  60. # Break import-style to ensure we can actually find our in-repo dependencies.
  61. import _unixccompiler_patch
  62. import commands
  63. import grpc_core_dependencies
  64. import grpc_version
  65. if 'win32' in sys.platform:
  66. _unixccompiler_patch.monkeypatch_unix_compiler()
  67. LICENSE = '3-clause BSD'
  68. # Environment variable to determine whether or not the Cython extension should
  69. # *use* Cython or use the generated C files. Note that this requires the C files
  70. # to have been generated by building first *with* Cython support. Even if this
  71. # is set to false, if the script detects that the generated `.c` file isn't
  72. # present, then it will still attempt to use Cython.
  73. BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
  74. # Environment variable to determine whether or not to enable coverage analysis
  75. # in Cython modules.
  76. ENABLE_CYTHON_TRACING = os.environ.get(
  77. 'GRPC_PYTHON_ENABLE_CYTHON_TRACING', False)
  78. # There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are
  79. # entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
  80. # We use these environment variables to thus get around that without locking
  81. # ourselves in w.r.t. the multitude of operating systems this ought to build on.
  82. # We can also use these variables as a way to inject environment-specific
  83. # compiler/linker flags. We assume GCC-like compilers and/or MinGW as a
  84. # reasonable default.
  85. EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
  86. EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
  87. if EXTRA_ENV_COMPILE_ARGS is None:
  88. EXTRA_ENV_COMPILE_ARGS = '-fno-wrapv'
  89. if 'win32' in sys.platform:
  90. # We use define flags here and don't directly add to DEFINE_MACROS below to
  91. # ensure that the expert user/builder has a way of turning it off (via the
  92. # envvars) without adding yet more GRPC-specific envvars.
  93. # See https://sourceforge.net/p/mingw-w64/bugs/363/
  94. if '32' in platform.architecture()[0]:
  95. EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
  96. else:
  97. EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
  98. elif "linux" in sys.platform or "darwin" in sys.platform:
  99. EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden'
  100. if EXTRA_ENV_LINK_ARGS is None:
  101. EXTRA_ENV_LINK_ARGS = '-lpthread'
  102. if 'win32' in sys.platform:
  103. # TODO(atash) check if this is actually safe to just import and call on
  104. # non-Windows (to avoid breaking import style)
  105. from distutils.cygwinccompiler import get_msvcr
  106. msvcr = get_msvcr()[0]
  107. # TODO(atash) sift through the GCC specs to see if libstdc++ can have any
  108. # influence on the linkage outcome on MinGW for non-C++ programs.
  109. EXTRA_ENV_LINK_ARGS += (
  110. ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr} '
  111. '-static'.format(msvcr=msvcr))
  112. elif "linux" in sys.platform:
  113. EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy'
  114. EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
  115. EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)
  116. CYTHON_EXTENSION_PACKAGE_NAMES = ()
  117. CYTHON_EXTENSION_MODULE_NAMES = ('grpc._cython.cygrpc',)
  118. CYTHON_HELPER_C_FILES = ()
  119. CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
  120. EXTENSION_INCLUDE_DIRECTORIES = (
  121. (PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE +
  122. CARES_INCLUDE)
  123. EXTENSION_LIBRARIES = ()
  124. if "linux" in sys.platform:
  125. EXTENSION_LIBRARIES += ('rt',)
  126. if not "win32" in sys.platform:
  127. EXTENSION_LIBRARIES += ('m',)
  128. if "win32" in sys.platform:
  129. EXTENSION_LIBRARIES += ('ws2_32',)
  130. DEFINE_MACROS = (
  131. ('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),
  132. ('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
  133. if "win32" in sys.platform:
  134. DEFINE_MACROS += (('OPENSSL_WINDOWS', 1), ('WIN32_LEAN_AND_MEAN', 1),
  135. ('CARES_STATICLIB', 1),)
  136. if '64bit' in platform.architecture()[0]:
  137. DEFINE_MACROS += (('MS_WIN64', 1),)
  138. else:
  139. DEFINE_MACROS += (('HAVE_CONFIG_H', 1),)
  140. LDFLAGS = tuple(EXTRA_LINK_ARGS)
  141. CFLAGS = tuple(EXTRA_COMPILE_ARGS)
  142. if "linux" in sys.platform or "darwin" in sys.platform:
  143. pymodinit_type = 'PyObject*' if PY3 else 'void'
  144. pymodinit = '__attribute__((visibility ("default"))) {}'.format(pymodinit_type)
  145. DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
  146. # By default, Python3 distutils enforces compatibility of
  147. # c plugins (.so files) with the OSX version Python3 was built with.
  148. # For Python3.4, this is OSX 10.6, but we need Thread Local Support (__thread)
  149. if 'darwin' in sys.platform and PY3:
  150. mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
  151. if mac_target and (pkg_resources.parse_version(mac_target) <
  152. pkg_resources.parse_version('10.7.0')):
  153. os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
  154. os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
  155. r'macosx-[0-9]+\.[0-9]+-(.+)',
  156. r'macosx-10.7-\1',
  157. util.get_platform())
  158. def cython_extensions_and_necessity():
  159. cython_module_files = [os.path.join(PYTHON_STEM,
  160. name.replace('.', '/') + '.pyx')
  161. for name in CYTHON_EXTENSION_MODULE_NAMES]
  162. extensions = [
  163. _extension.Extension(
  164. name=module_name,
  165. sources=[module_file] + list(CYTHON_HELPER_C_FILES) + list(CORE_C_FILES),
  166. include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
  167. libraries=list(EXTENSION_LIBRARIES),
  168. define_macros=list(DEFINE_MACROS),
  169. extra_compile_args=list(CFLAGS),
  170. extra_link_args=list(LDFLAGS),
  171. ) for (module_name, module_file) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
  172. ]
  173. need_cython = BUILD_WITH_CYTHON
  174. if not BUILD_WITH_CYTHON:
  175. need_cython = need_cython or not commands.check_and_update_cythonization(extensions)
  176. return commands.try_cythonize(extensions, linetracing=ENABLE_CYTHON_TRACING, mandatory=BUILD_WITH_CYTHON), need_cython
  177. CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity()
  178. PACKAGE_DIRECTORIES = {
  179. '': PYTHON_STEM,
  180. }
  181. INSTALL_REQUIRES = (
  182. 'six>=1.5.2',
  183. 'enum34>=1.0.4',
  184. 'futures>=2.2.0',
  185. # TODO(atash): eventually split the grpcio package into a metapackage
  186. # depending on protobuf and the runtime component (independent of protobuf)
  187. 'protobuf>=3.0.0',
  188. )
  189. SETUP_REQUIRES = INSTALL_REQUIRES + (
  190. 'sphinx>=1.3',
  191. 'sphinx_rtd_theme>=0.1.8',
  192. 'six>=1.10',
  193. )
  194. if BUILD_WITH_CYTHON:
  195. sys.stderr.write(
  196. "You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
  197. "but do not have Cython installed. We won't stop you from using "
  198. "other commands, but the extension files will fail to build.\n")
  199. elif need_cython:
  200. sys.stderr.write(
  201. 'We could not find Cython. Setup may take 10-20 minutes.\n')
  202. SETUP_REQUIRES += ('cython>=0.23',)
  203. COMMAND_CLASS = {
  204. 'doc': commands.SphinxDocumentation,
  205. 'build_project_metadata': commands.BuildProjectMetadata,
  206. 'build_py': commands.BuildPy,
  207. 'build_ext': commands.BuildExt,
  208. 'gather': commands.Gather,
  209. }
  210. # Ensure that package data is copied over before any commands have been run:
  211. credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials')
  212. try:
  213. os.mkdir(credentials_dir)
  214. except OSError:
  215. pass
  216. shutil.copyfile(os.path.join('etc', 'roots.pem'),
  217. os.path.join(credentials_dir, 'roots.pem'))
  218. PACKAGE_DATA = {
  219. # Binaries that may or may not be present in the final installation, but are
  220. # mentioned here for completeness.
  221. 'grpc._cython': [
  222. '_credentials/roots.pem',
  223. '_windows/grpc_c.32.python',
  224. '_windows/grpc_c.64.python',
  225. ],
  226. }
  227. PACKAGES = setuptools.find_packages(PYTHON_STEM)
  228. setuptools.setup(
  229. name='grpcio',
  230. version=grpc_version.VERSION,
  231. license=LICENSE,
  232. ext_modules=CYTHON_EXTENSION_MODULES,
  233. packages=list(PACKAGES),
  234. package_dir=PACKAGE_DIRECTORIES,
  235. package_data=PACKAGE_DATA,
  236. install_requires=INSTALL_REQUIRES,
  237. setup_requires=SETUP_REQUIRES,
  238. cmdclass=COMMAND_CLASS,
  239. )