From e390ffea34f9b9d2243e80ed47e7954dd4c4d930 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 10 Nov 2022 12:42:04 +0100 Subject: setup.py: provide better err msg if can't compile ...also refactor it a bit and add install instructions for Alpine Linux Signed-off-by: Giampaolo Rodola --- INSTALL.rst | 5 ++++ setup.py | 80 +++++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/INSTALL.rst b/INSTALL.rst index 46aee6cd..4f5831e6 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -25,6 +25,11 @@ RedHat / CentOS:: sudo yum install gcc python3-devel pip install --no-binary :all: psutil +Alpine:: + + sudo apk add gcc python3-dev + pip install --no-binary :all: psutil + Windows (build) --------------- diff --git a/setup.py b/setup.py index b3f20666..31777b9d 100755 --- a/setup.py +++ b/setup.py @@ -109,6 +109,8 @@ def get_version(): VERSION = get_version() macros.append(('PSUTIL_VERSION', int(VERSION.replace('.', '')))) +# Py_LIMITED_API lets us create a single wheel which works with multiple +# python versions, including unreleased ones. if bdist_wheel and CP36_PLUS and (MACOS or LINUX or WINDOWS): py_limited_api = {"py_limited_api": True} macros.append(('Py_LIMITED_API', '0x03060000')) @@ -147,11 +149,41 @@ def silenced_output(stream_name): setattr(sys, stream_name, orig) -def missdeps(msg): - s = hilite("C compiler or Python headers are not installed ", color="red") - s += hilite("on this system. Try to run:\n", color="red") - s += hilite(msg, color="red", bold=True) - print(s, file=sys.stderr) +def missdeps(cmdline): + s = "psutil could not be installed from sources" + if not SUNOS and not which("gcc"): + s += " because gcc is not installed. " + else: + s += ". Perhaps Python header files are not installed. " + s += "Try running:\n" + s += " %s" % cmdline + print(hilite(s, color="red", bold=True), file=sys.stderr) + + +def unix_can_compile(c_code): + from distutils.errors import CompileError + from distutils.unixccompiler import UnixCCompiler + + with tempfile.NamedTemporaryFile( + suffix='.c', delete=False, mode="wt") as f: + f.write(c_code) + + tempdir = tempfile.mkdtemp() + try: + compiler = UnixCCompiler() + # https://github.com/giampaolo/psutil/pull/1568 + if os.getenv('CC'): + compiler.set_executable('compiler_so', os.getenv('CC')) + with silenced_output('stderr'): + with silenced_output('stdout'): + compiler.compile([f.name], output_dir=tempdir) + except CompileError: + return False + else: + return True + finally: + os.remove(f.name) + shutil.rmtree(tempdir) if WINDOWS: @@ -263,36 +295,11 @@ elif NETBSD: **py_limited_api) elif LINUX: - def get_ethtool_macro(): - # see: https://github.com/giampaolo/psutil/issues/659 - from distutils.errors import CompileError - from distutils.unixccompiler import UnixCCompiler - - with tempfile.NamedTemporaryFile( - suffix='.c', delete=False, mode="wt") as f: - f.write("#include ") - - output_dir = tempfile.mkdtemp() - try: - compiler = UnixCCompiler() - # https://github.com/giampaolo/psutil/pull/1568 - if os.getenv('CC'): - compiler.set_executable('compiler_so', os.getenv('CC')) - with silenced_output('stderr'): - with silenced_output('stdout'): - compiler.compile([f.name], output_dir=output_dir) - except CompileError: - return ("PSUTIL_ETHTOOL_MISSING_TYPES", 1) - else: - return None - finally: - os.remove(f.name) - shutil.rmtree(output_dir) + # see: https://github.com/giampaolo/psutil/issues/659 + if not unix_can_compile("#include "): + macros.append(("PSUTIL_ETHTOOL_MISSING_TYPES", 1)) macros.append(("PSUTIL_LINUX", 1)) - ETHTOOL_MACRO = get_ethtool_macro() - if ETHTOOL_MACRO is not None: - macros.append(ETHTOOL_MACRO) ext = Extension( 'psutil._psutil_linux', sources=sources + ['psutil/_psutil_linux.c'], @@ -455,13 +462,18 @@ def main(): setup(**kwargs) success = True finally: - if not success and POSIX and not which('gcc'): + cmd = sys.argv[1] if len(sys.argv) >= 2 else '' + if not success and POSIX and \ + cmd.startswith(("build", "install", "sdist", "bdist", + "develop")): py3 = "3" if PY3 else "" if LINUX: if which('dpkg'): missdeps("sudo apt-get install gcc python%s-dev" % py3) elif which('rpm'): missdeps("sudo yum install gcc python%s-devel" % py3) + elif which('apk'): + missdeps("sudo apk add gcc python%s-dev" % py3) elif MACOS: print(hilite("XCode (https://developer.apple.com/xcode/) " "is not installed"), color="red", file=sys.stderr) -- cgit v1.2.1