setup.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. import os
  32. import os.path
  33. import pkg_resources
  34. import platform
  35. import shlex
  36. import shutil
  37. import sys
  38. import sysconfig
  39. import setuptools
  40. from setuptools.command import egg_info
  41. # Redirect the manifest template from MANIFEST.in to PYTHON-MANIFEST.in.
  42. egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
  43. PY3 = sys.version_info.major == 3
  44. PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
  45. CORE_INCLUDE = ('include', '.',)
  46. BORINGSSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),)
  47. ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
  48. # Ensure we're in the proper directory whether or not we're being used by pip.
  49. os.chdir(os.path.dirname(os.path.abspath(__file__)))
  50. sys.path.insert(0, os.path.abspath(PYTHON_STEM))
  51. # Break import-style to ensure we can actually find our in-repo dependencies.
  52. import _unixccompiler_patch
  53. import commands
  54. import grpc_core_dependencies
  55. import grpc_version
  56. if 'win32' in sys.platform:
  57. _unixccompiler_patch.monkeypatch_unix_compiler()
  58. LICENSE = '3-clause BSD'
  59. # Environment variable to determine whether or not the Cython extension should
  60. # *use* Cython or use the generated C files. Note that this requires the C files
  61. # to have been generated by building first *with* Cython support.
  62. BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
  63. # Environment variable to determine whether or not to enable coverage analysis
  64. # in Cython modules.
  65. ENABLE_CYTHON_TRACING = os.environ.get(
  66. 'GRPC_PYTHON_ENABLE_CYTHON_TRACING', False)
  67. # There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are
  68. # entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
  69. # We use these environment variables to thus get around that without locking
  70. # ourselves in w.r.t. the multitude of operating systems this ought to build on.
  71. # By default we assume a GCC-like compiler.
  72. EXTRA_COMPILE_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_CFLAGS', ''))
  73. EXTRA_LINK_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_LDFLAGS', ''))
  74. CYTHON_EXTENSION_PACKAGE_NAMES = ()
  75. CYTHON_EXTENSION_MODULE_NAMES = ('grpc._cython.cygrpc',)
  76. CYTHON_HELPER_C_FILES = ()
  77. CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
  78. EXTENSION_INCLUDE_DIRECTORIES = (
  79. (PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE)
  80. EXTENSION_LIBRARIES = ()
  81. if "linux" in sys.platform:
  82. EXTENSION_LIBRARIES += ('rt',)
  83. if not "win32" in sys.platform:
  84. EXTENSION_LIBRARIES += ('m',)
  85. if "win32" in sys.platform:
  86. EXTENSION_LIBRARIES += ('ws2_32',)
  87. DEFINE_MACROS = (
  88. ('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),
  89. ('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
  90. if "win32" in sys.platform:
  91. DEFINE_MACROS += (('OPENSSL_WINDOWS', 1), ('WIN32_LEAN_AND_MEAN', 1),)
  92. if '64bit' in platform.architecture()[0]:
  93. DEFINE_MACROS += (('MS_WIN64', 1),)
  94. LDFLAGS = tuple(EXTRA_LINK_ARGS)
  95. CFLAGS = tuple(EXTRA_COMPILE_ARGS)
  96. if "linux" in sys.platform:
  97. LDFLAGS += ('-Wl,-wrap,memcpy',)
  98. if "linux" in sys.platform or "darwin" in sys.platform:
  99. CFLAGS += ('-fvisibility=hidden',)
  100. pymodinit_type = 'PyObject*' if PY3 else 'void'
  101. pymodinit = '__attribute__((visibility ("default"))) {}'.format(pymodinit_type)
  102. DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
  103. # By default, Python3 distutils enforces compatibility of
  104. # c plugins (.so files) with the OSX version Python3 was built with.
  105. # For Python3.4, this is OSX 10.6, but we need Thread Local Support (__thread)
  106. if 'darwin' in sys.platform and PY3:
  107. mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
  108. if mac_target and (pkg_resources.parse_version(mac_target) <
  109. pkg_resources.parse_version('10.7.0')):
  110. os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
  111. def cython_extensions(module_names, extra_sources, include_dirs,
  112. libraries, define_macros, build_with_cython=False):
  113. # Set compiler directives linetrace argument only if we care about tracing;
  114. # this is due to Cython having different behavior between linetrace being
  115. # False and linetrace being unset. See issue #5689.
  116. cython_compiler_directives = {}
  117. if ENABLE_CYTHON_TRACING:
  118. define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)]
  119. cython_compiler_directives['linetrace'] = True
  120. file_extension = 'pyx' if build_with_cython else 'c'
  121. module_files = [os.path.join(PYTHON_STEM,
  122. name.replace('.', '/') + '.' + file_extension)
  123. for name in module_names]
  124. extensions = [
  125. _extension.Extension(
  126. name=module_name,
  127. sources=[module_file] + extra_sources,
  128. include_dirs=include_dirs, libraries=libraries,
  129. define_macros=define_macros,
  130. extra_compile_args=list(CFLAGS),
  131. extra_link_args=list(LDFLAGS),
  132. ) for (module_name, module_file) in zip(module_names, module_files)
  133. ]
  134. if build_with_cython:
  135. import Cython.Build
  136. return Cython.Build.cythonize(
  137. extensions,
  138. include_path=include_dirs,
  139. compiler_directives=cython_compiler_directives)
  140. else:
  141. return extensions
  142. CYTHON_EXTENSION_MODULES = cython_extensions(
  143. list(CYTHON_EXTENSION_MODULE_NAMES),
  144. list(CYTHON_HELPER_C_FILES) + list(CORE_C_FILES),
  145. list(EXTENSION_INCLUDE_DIRECTORIES), list(EXTENSION_LIBRARIES),
  146. list(DEFINE_MACROS), bool(BUILD_WITH_CYTHON))
  147. PACKAGE_DIRECTORIES = {
  148. '': PYTHON_STEM,
  149. }
  150. INSTALL_REQUIRES = (
  151. 'six>=1.5.2',
  152. 'enum34>=1.0.4',
  153. 'futures>=2.2.0',
  154. # TODO(atash): eventually split the grpcio package into a metapackage
  155. # depending on protobuf and the runtime component (independent of protobuf)
  156. 'protobuf>=3.0.0a3',
  157. )
  158. SETUP_REQUIRES = INSTALL_REQUIRES + (
  159. 'sphinx>=1.3',
  160. 'sphinx_rtd_theme>=0.1.8',
  161. 'six>=1.10',
  162. )
  163. COMMAND_CLASS = {
  164. 'doc': commands.SphinxDocumentation,
  165. 'build_project_metadata': commands.BuildProjectMetadata,
  166. 'build_py': commands.BuildPy,
  167. 'build_ext': commands.BuildExt,
  168. 'gather': commands.Gather,
  169. }
  170. # Ensure that package data is copied over before any commands have been run:
  171. credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials')
  172. try:
  173. os.mkdir(credentials_dir)
  174. except OSError:
  175. pass
  176. shutil.copyfile(os.path.join('etc', 'roots.pem'),
  177. os.path.join(credentials_dir, 'roots.pem'))
  178. PACKAGE_DATA = {
  179. # Binaries that may or may not be present in the final installation, but are
  180. # mentioned here for completeness.
  181. 'grpc._cython': [
  182. '_credentials/roots.pem',
  183. '_windows/grpc_c.32.python',
  184. '_windows/grpc_c.64.python',
  185. ],
  186. }
  187. PACKAGES = setuptools.find_packages(PYTHON_STEM)
  188. setuptools.setup(
  189. name='grpcio',
  190. version=grpc_version.VERSION,
  191. license=LICENSE,
  192. ext_modules=CYTHON_EXTENSION_MODULES,
  193. packages=list(PACKAGES),
  194. package_dir=PACKAGE_DIRECTORIES,
  195. package_data=PACKAGE_DATA,
  196. install_requires=INSTALL_REQUIRES,
  197. setup_requires=SETUP_REQUIRES,
  198. cmdclass=COMMAND_CLASS,
  199. )