15 from distutils
import cygwinccompiler
16 from distutils
import extension
17 from distutils
import util
26 from subprocess
import PIPE
32 from setuptools.command
import build_ext
36 _PACKAGE_PATH = os.path.realpath(os.path.dirname(__file__))
37 _README_PATH = os.path.join(_PACKAGE_PATH,
'README.rst')
39 os.chdir(os.path.dirname(os.path.abspath(__file__)))
40 sys.path.insert(0, os.path.abspath(
'.'))
42 import _parallel_compile_patch
43 import protoc_lib_deps
47 _EXT_INIT_SYMBOL =
None
48 if sys.version_info[0] == 2:
49 _EXT_INIT_SYMBOL =
"init_protoc_compiler"
51 _EXT_INIT_SYMBOL =
"PyInit__protoc_compiler"
56 'Development Status :: 5 - Production/Stable',
57 'Programming Language :: Python',
58 'Programming Language :: Python :: 3',
59 'License :: OSI Approved :: Apache Software License',
62 PY3 = sys.version_info.major == 3
66 """Parses a bool option from an environment variable"""
67 return os.environ.get(env_name, default).upper()
not in [
'FALSE',
'0',
'']
73 BUILD_WITH_CYTHON =
_env_bool_value(
'GRPC_PYTHON_BUILD_WITH_CYTHON',
'False')
83 'GRPC_PYTHON_BUILD_WITH_STATIC_LIBSTDCXX',
'False')
87 """Test if linker on system needs libatomic."""
88 code_test = (b
'#include <atomic>\n' +
89 b
'int main() { return std::atomic<int64_t>{}; }')
90 cxx = os.environ.get(
'CXX',
'c++')
91 cpp_test = subprocess.Popen([cxx,
'-x',
'c++',
'-std=c++14',
'-'],
95 cpp_test.communicate(input=code_test)
96 if cpp_test.returncode == 0:
100 cpp_test = subprocess.Popen(
101 [cxx,
'-x',
'c++',
'-std=c++14',
'-',
'-latomic'],
105 cpp_test.communicate(input=code_test)
106 return cpp_test.returncode == 0
110 """Custom build_ext command."""
119 filename = build_ext.build_ext.get_ext_filename(self, ext_name)
120 orig_ext_suffix = sysconfig.get_config_var(
'EXT_SUFFIX')
121 new_ext_suffix = os.getenv(
'GRPC_PYTHON_OVERRIDE_EXT_SUFFIX')
122 if new_ext_suffix
and filename.endswith(orig_ext_suffix):
123 filename = filename[:-
len(orig_ext_suffix)] + new_ext_suffix
134 EXTRA_ENV_COMPILE_ARGS = os.environ.get(
'GRPC_PYTHON_CFLAGS',
None)
135 EXTRA_ENV_LINK_ARGS = os.environ.get(
'GRPC_PYTHON_LDFLAGS',
None)
136 if EXTRA_ENV_COMPILE_ARGS
is None:
137 EXTRA_ENV_COMPILE_ARGS =
'-std=c++14'
138 if 'win32' in sys.platform:
139 if sys.version_info < (3, 5):
144 if '32' in platform.architecture()[0]:
145 EXTRA_ENV_COMPILE_ARGS +=
' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s -D_hypot=hypot'
147 EXTRA_ENV_COMPILE_ARGS +=
' -D_ftime=_ftime64 -D_timeb=__timeb64 -D_hypot=hypot'
151 EXTRA_ENV_COMPILE_ARGS +=
' /MT'
152 elif "linux" in sys.platform
or "darwin" in sys.platform:
153 EXTRA_ENV_COMPILE_ARGS +=
' -fno-wrapv -frtti'
154 if EXTRA_ENV_LINK_ARGS
is None:
155 EXTRA_ENV_LINK_ARGS =
''
175 if "darwin" in sys.platform:
176 EXTRA_ENV_LINK_ARGS +=
' -Wl,-exported_symbol,_{}'.
format(
178 if "linux" in sys.platform
or "darwin" in sys.platform:
179 EXTRA_ENV_LINK_ARGS +=
' -lpthread'
181 EXTRA_ENV_LINK_ARGS +=
' -latomic'
182 elif "win32" in sys.platform
and sys.version_info < (3, 5):
183 msvcr = cygwinccompiler.get_msvcr()[0]
184 EXTRA_ENV_LINK_ARGS += (
185 ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr}'
186 ' -static -lshlwapi'.
format(msvcr=msvcr))
188 EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
189 EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)
191 if BUILD_WITH_STATIC_LIBSTDCXX:
192 EXTRA_LINK_ARGS.append(
'-static-libstdc++')
194 CC_FILES = [os.path.normpath(cc_file)
for cc_file
in protoc_lib_deps.CC_FILES]
196 os.path.normpath(proto_file)
for proto_file
in protoc_lib_deps.PROTO_FILES
198 CC_INCLUDE = os.path.normpath(protoc_lib_deps.CC_INCLUDE)
199 PROTO_INCLUDE = os.path.normpath(protoc_lib_deps.PROTO_INCLUDE)
201 GRPC_PYTHON_TOOLS_PACKAGE =
'grpc_tools'
202 GRPC_PYTHON_PROTO_RESOURCES_NAME =
'_proto'
205 if "win32" in sys.platform:
206 DEFINE_MACROS += ((
'WIN32_LEAN_AND_MEAN', 1),)
207 if '64bit' in platform.architecture()[0]:
208 DEFINE_MACROS += ((
'MS_WIN64', 1),)
209 elif "linux" in sys.platform
or "darwin" in sys.platform:
210 DEFINE_MACROS += ((
'HAVE_PTHREAD', 1),)
215 if 'darwin' in sys.platform:
216 mac_target = sysconfig.get_config_var(
'MACOSX_DEPLOYMENT_TARGET')
217 if mac_target
and (pkg_resources.parse_version(mac_target) <
218 pkg_resources.parse_version(
'10.10.0')):
219 os.environ[
'MACOSX_DEPLOYMENT_TARGET'] =
'10.10'
220 os.environ[
'_PYTHON_HOST_PLATFORM'] = re.sub(
221 r'macosx-[0-9]+\.[0-9]+-(.+)',
r'macosx-10.10-\1',
226 tools_path = GRPC_PYTHON_TOOLS_PACKAGE.replace(
'.', os.path.sep)
227 proto_resources_path = os.path.join(tools_path,
228 GRPC_PYTHON_PROTO_RESOURCES_NAME)
230 for proto_file
in PROTO_FILES:
231 source = os.path.join(PROTO_INCLUDE, proto_file)
232 target = os.path.join(proto_resources_path, proto_file)
233 relative_target = os.path.join(GRPC_PYTHON_PROTO_RESOURCES_NAME,
236 os.makedirs(os.path.dirname(target))
237 except OSError
as error:
238 if error.errno == errno.EEXIST:
242 shutil.copy(source, target)
243 proto_files.append(relative_target)
244 return {GRPC_PYTHON_TOOLS_PACKAGE: proto_files}
248 if BUILD_WITH_CYTHON:
249 plugin_sources = [os.path.join(
'grpc_tools',
'_protoc_compiler.pyx')]
251 plugin_sources = [os.path.join(
'grpc_tools',
'_protoc_compiler.cpp')]
254 os.path.join(
'grpc_tools',
'main.cc'),
255 os.path.join(
'grpc_root',
'src',
'compiler',
'python_generator.cc')
256 ] + [os.path.join(CC_INCLUDE, cc_file)
for cc_file
in CC_FILES]
258 plugin_ext = extension.Extension(
259 name=
'grpc_tools._protoc_compiler',
260 sources=plugin_sources,
264 os.path.join(
'grpc_root',
'include'),
268 define_macros=list(DEFINE_MACROS),
269 extra_compile_args=list(EXTRA_COMPILE_ARGS),
270 extra_link_args=list(EXTRA_LINK_ARGS),
272 extensions = [plugin_ext]
273 if BUILD_WITH_CYTHON:
274 from Cython
import Build
275 return Build.cythonize(extensions)
280 setuptools.setup(name=
'grpcio-tools',
281 version=grpc_version.VERSION,
282 description=
'Protobuf code generator for gRPC',
283 long_description=
open(_README_PATH,
'r').
read(),
284 author=
'The gRPC Authors',
285 author_email=
'grpc-io@googlegroups.com',
286 url=
'https://grpc.io',
287 license=
'Apache License 2.0',
288 classifiers=CLASSIFIERS,
290 packages=setuptools.find_packages(
'.'),
291 python_requires=
'>=3.6',
293 'protobuf>=3.12.0, < 4.0dev',
294 'grpcio>={version}'.
format(version=grpc_version.VERSION),
299 'build_ext': BuildExt,