From 58a1dc2bb31f4bf3581131fba80497c40ddc947d Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Thu, 21 Jan 2016 14:23:55 -0800 Subject: [PATCH] Add compiler error diagnostics to Python setup --- PYTHON-MANIFEST.in | 1 + setup.py | 2 +- src/python/grpcio/commands.py | 10 +++- src/python/grpcio/support.py | 91 +++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 src/python/grpcio/support.py diff --git a/PYTHON-MANIFEST.in b/PYTHON-MANIFEST.in index 02bd9b5229415..6e54e1b3c64db 100644 --- a/PYTHON-MANIFEST.in +++ b/PYTHON-MANIFEST.in @@ -5,6 +5,7 @@ graft include/grpc graft third_party/boringssl include src/python/grpcio/commands.py include src/python/grpcio/grpc_core_dependencies.py +include src/python/grpcio/support.py include src/python/grpcio/README.rst include requirements.txt include etc/roots.pem diff --git a/setup.py b/setup.py index 63b56f3532799..113e49ecfe55a 100644 --- a/setup.py +++ b/setup.py @@ -48,7 +48,7 @@ # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(0, PYTHON_STEM) +sys.path.insert(0, os.path.abspath(PYTHON_STEM)) # Break import-style to ensure we can actually find our in-repo dependencies. import commands diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index bd12c5579cbcd..ff35c458617b9 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -37,9 +37,9 @@ import sys import setuptools +from setuptools.command import build_ext from setuptools.command import build_py from setuptools.command import test -from setuptools.command import build_ext PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) @@ -186,7 +186,13 @@ def build_extensions(self): if compiler in BuildExt.LINK_OPTIONS: for extension in self.extensions: extension.extra_link_args += list(BuildExt.LINK_OPTIONS[compiler]) - build_ext.build_ext.build_extensions(self) + try: + build_ext.build_ext.build_extensions(self) + except KeyboardInterrupt: + raise + except Exception as error: + support.diagnose_build_ext_error(self, error) + raise CommandError("Failed `build_ext` step.") class Gather(setuptools.Command): diff --git a/src/python/grpcio/support.py b/src/python/grpcio/support.py new file mode 100644 index 0000000000000..bbc509653d110 --- /dev/null +++ b/src/python/grpcio/support.py @@ -0,0 +1,91 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +import os +import os.path +import shutil +import sys +import tempfile + +from distutils import errors + +import commands + + +C_PYTHON_DEV = """ +#include +int main(int argc, char **argv) { return 0; } +""" +C_PYTHON_DEV_ERROR_MESSAGE = """ +Could not find . This could mean the following: + * You're on Ubuntu and haven't `apt-get install`ed `python-dev`. + * You're on Mac OS X and the usual Python framework was somehow corrupted + (check your environment variables or try re-installing?) + * You're on Windows and your Python installation was somehow corrupted + (check your environment variables or try re-installing?) + * Note: Windows users should look into installing `vcpython27`. +""" + +C_CHECKS = { + C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE, +} + +def _compile(compiler, source_string): + tempdir = tempfile.mkdtemp() + cpath = os.path.join(tempdir, 'a.c') + with open(cpath, 'w') as cfile: + cfile.write(source_string) + try: + compiler.compile([cpath]) + except errors.CompileError as error: + return error + finally: + shutil.rmtree(tempdir) + +def _expect_compile(compiler, source_string, error_message): + if _compile(compiler, source_string) is not None: + sys.stderr.write(error_message) + raise commands.CommandError( + "Diagnostics found a compilation environment issue:\n{}" + .format(error_message)) + +def diagnose_build_ext_error(build_ext, error): + { + errors.CompileError: diagnose_compile_error + }[type(error)](build_ext, error) + +def diagnose_compile_error(build_ext, error): + """Attempt to run a few test files through the compiler to see if we can + diagnose the reason for the compile failure.""" + for c_check, message in C_CHECKS.items(): + _expect_compile(build_ext.compiler, c_check, message) + raise commands.CommandError( + "\n\nWe could not diagnose your build failure. Please file an issue at " + "http://www.github.com/grpc/grpc with `[Python install]` in the title.")