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: for source in extension.sources:
base, file_ext = os.path.splitext(source) base, file_ext = os.path.splitext(source)
if file_ext == '.pyx': if file_ext == '.pyx':
generated_pyx_source = next( generated_pyx_source = next((base + gen_ext for gen_ext in (
(base + gen_ext for gen_ext in ( '.c',
'.c', '.cpp',
'.cpp', ) if os.path.isfile(base + gen_ext)), None)
) if os.path.isfile(base + gen_ext)), None)
if generated_pyx_source: if generated_pyx_source:
generated_pyx_sources.append(generated_pyx_source) generated_pyx_sources.append(generated_pyx_source)
else: else:
@ -195,8 +194,7 @@ def try_cythonize(extensions, linetracing=False, mandatory=True):
return Cython.Build.cythonize( return Cython.Build.cythonize(
extensions, extensions,
include_path=[ include_path=[
include_dir include_dir for extension in extensions
for extension in extensions
for include_dir in extension.include_dirs for include_dir in extension.include_dirs
] + [CYTHON_STEM], ] + [CYTHON_STEM],
compiler_directives=cython_compiler_directives) compiler_directives=cython_compiler_directives)
@ -212,50 +210,38 @@ class BuildExt(build_ext.build_ext):
LINK_OPTIONS = {} LINK_OPTIONS = {}
def build_extensions(self): 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 # This special conditioning is here due to difference of compiler
# behavior in gcc and clang. The clang doesn't take --stdc++11 # behavior in gcc and clang. The clang doesn't take --stdc++11
# flags but gcc does. Since the setuptools of Python only support # 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. # 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 # *By default*, macOS and FreBSD use clang and Linux use gcc
# the special condition here is checking platform. #
if "darwin" in sys.platform: # If we are not using a permissive compiler that's OK with being
config = os.environ.get('CONFIG', 'opt') # passed wrong std flags, swap out compile function by adding a filter
target_path = os.path.abspath( # for it.
os.path.join( if not compiler_ok_with_extra_std():
os.path.dirname(os.path.realpath(__file__)), '..', '..', old_compile = self.compiler._compile
'..', 'libs', config))
targets = [ def new_compile(obj, src, ext, cc_args, extra_postargs, pp_opts):
os.path.join(target_path, 'libboringssl.a'), if src[-2:] == '.c':
os.path.join(target_path, 'libares.a'), extra_postargs = [
os.path.join(target_path, 'libgpr.a'), arg for arg in extra_postargs if not '-std=c++' in arg
os.path.join(target_path, 'libgrpc.a') ]
] return old_compile(obj, src, ext, cc_args, extra_postargs,
# Running make separately for Mac means we lose all pp_opts)
# Extension.define_macros configured in setup.py. Re-add the macro
# for gRPC Core's fork handlers. self.compiler._compile = new_compile
# 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!")
compiler = self.compiler.compiler_type compiler = self.compiler.compiler_type
if compiler in BuildExt.C_OPTIONS: if compiler in BuildExt.C_OPTIONS:

Loading…
Cancel
Save