generalize macOS workaround for -std=c++11 passed in C mode

GCC allows this, but notably clang does not. Other systems,
like FreeBSD and some Linux distros ship with clang as default
compiler. While here, switch the approach to filtering out std
flag since the make workaround relies on GNU make syntax and
'make' binary could be bmake and/or gmake could be absent.

The idea to filter the flags was taken from an answer to this
Stack Overflow question:
https://stackoverflow.com/questions/15527611/how-do-i-specify-different-compiler-flags-in-distutils-for-just-one-python-c-ext
pull/18116/head
Nikolai Lifanov 6 years ago
parent b889461b46
commit c1451e83d5
  1. 80
      src/python/grpcio/commands.py

@ -149,11 +149,10 @@ def check_and_update_cythonization(extensions):
for source in extension.sources:
base, file_ext = os.path.splitext(source)
if file_ext == '.pyx':
generated_pyx_source = next(
(base + gen_ext for gen_ext in (
'.c',
'.cpp',
) if os.path.isfile(base + gen_ext)), None)
generated_pyx_source = next((base + gen_ext for gen_ext in (
'.c',
'.cpp',
) if os.path.isfile(base + gen_ext)), None)
if generated_pyx_source:
generated_pyx_sources.append(generated_pyx_source)
else:
@ -195,8 +194,7 @@ def try_cythonize(extensions, linetracing=False, mandatory=True):
return Cython.Build.cythonize(
extensions,
include_path=[
include_dir
for extension in extensions
include_dir for extension in extensions
for include_dir in extension.include_dirs
] + [CYTHON_STEM],
compiler_directives=cython_compiler_directives)
@ -212,50 +210,38 @@ class BuildExt(build_ext.build_ext):
LINK_OPTIONS = {}
def build_extensions(self):
def compiler_ok_with_extra_std():
"""Test if default compiler is okay with specifying c++ version
when invokec in C mode. GCC is okay with this, while clang is not.
"""
cc_test = subprocess.Popen(['cc', '-x', 'c', '-std=c++11', '-'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
_, cc_err = cc_test.communicate(input='int main(){return 0;}')
return not 'invalid argument' in cc_err
# This special conditioning is here due to difference of compiler
# behavior in gcc and clang. The clang doesn't take --stdc++11
# flags but gcc does. Since the setuptools of Python only support
# all C or all C++ compilation, the mix of C and C++ will crash.
# *By default*, the macOS use clang and Linux use gcc, that's why
# the special condition here is checking platform.
if "darwin" in sys.platform:
config = os.environ.get('CONFIG', 'opt')
target_path = os.path.abspath(
os.path.join(
os.path.dirname(os.path.realpath(__file__)), '..', '..',
'..', 'libs', config))
targets = [
os.path.join(target_path, 'libboringssl.a'),
os.path.join(target_path, 'libares.a'),
os.path.join(target_path, 'libgpr.a'),
os.path.join(target_path, 'libgrpc.a')
]
# Running make separately for Mac means we lose all
# Extension.define_macros configured in setup.py. Re-add the macro
# for gRPC Core's fork handlers.
# TODO(ericgribkoff) Decide what to do about the other missing core
# macros, including GRPC_ENABLE_FORK_SUPPORT, which defaults to 1
# on Linux but remains unset on Mac.
extra_defines = [
'EXTRA_DEFINES="GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1"'
]
# Ensure the BoringSSL are built instead of using system provided
# libraries. It prevents dependency issues while distributing to
# Mac users who use MacPorts to manage their libraries. #17002
mod_env = dict(os.environ)
mod_env['REQUIRE_CUSTOM_LIBRARIES_opt'] = '1'
make_process = subprocess.Popen(
['make'] + extra_defines + targets,
env=mod_env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
make_out, make_err = make_process.communicate()
if make_out and make_process.returncode != 0:
sys.stdout.write(str(make_out) + '\n')
if make_err:
sys.stderr.write(str(make_err) + '\n')
if make_process.returncode != 0:
raise Exception("make command failed!")
# *By default*, macOS and FreBSD use clang and Linux use gcc
#
# If we are not using a permissive compiler that's OK with being
# passed wrong std flags, swap out compile function by adding a filter
# for it.
if not compiler_ok_with_extra_std():
old_compile = self.compiler._compile
def new_compile(obj, src, ext, cc_args, extra_postargs, pp_opts):
if src[-2:] == '.c':
extra_postargs = [
arg for arg in extra_postargs if not '-std=c++' in arg
]
return old_compile(obj, src, ext, cc_args, extra_postargs,
pp_opts)
self.compiler._compile = new_compile
compiler = self.compiler.compiler_type
if compiler in BuildExt.C_OPTIONS:

Loading…
Cancel
Save