diff options
author | Masood Malekghassemi <soltanmm@users.noreply.github.com> | 2016-01-25 13:04:30 -0800 |
---|---|---|
committer | Masood Malekghassemi <soltanmm@users.noreply.github.com> | 2016-01-25 13:04:30 -0800 |
commit | caf164ac549f14dc0f5bcd301e692b649e0e56b3 (patch) | |
tree | b446935432e8e1ed65c42432eb1698da1ccf238a | |
parent | 22f6dccec6bf1efd7e2a3cbb8e138662cf8d2e35 (diff) | |
parent | 58a1dc2bb31f4bf3581131fba80497c40ddc947d (diff) |
Merge pull request #4821 from soltanmm/install-doctor
Add compiler error diagnostics to Python setup
-rw-r--r-- | PYTHON-MANIFEST.in | 1 | ||||
-rw-r--r-- | setup.py | 2 | ||||
-rw-r--r-- | src/python/grpcio/commands.py | 10 | ||||
-rw-r--r-- | src/python/grpcio/support.py | 91 |
4 files changed, 101 insertions, 3 deletions
diff --git a/PYTHON-MANIFEST.in b/PYTHON-MANIFEST.in index 52ef1aba5b..2f5700d11a 100644 --- a/PYTHON-MANIFEST.in +++ b/PYTHON-MANIFEST.in @@ -6,6 +6,7 @@ graft third_party/boringssl graft third_party/zlib 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 @@ -49,7 +49,7 @@ ZLIB_INCLUDE = ('./third_party/zlib',) # 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 bd12c5579c..ff35c45861 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -37,9 +37,9 @@ import subprocess 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 @@ class BuildExt(build_ext.build_ext): 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 0000000000..bbc509653d --- /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 <Python.h> +int main(int argc, char **argv) { return 0; } +""" +C_PYTHON_DEV_ERROR_MESSAGE = """ +Could not find <Python.h>. 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.") |