diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index b805f4277b0..ec03cbf4992 100644 --- a/src/python/grpcio/commands.py +++ b/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: