From 0b26fc583f436b7d5ed562e814298d2db29623de Mon Sep 17 00:00:00 2001 From: bwoodsend Date: Fri, 2 Oct 2020 22:32:13 +0100 Subject: [PATCH] Hooks: distutils: Fix no suitable dest location found for pyconfig.h. Locating `pyconfig.h` and the `makefile` gets into a mess when using certain environment managers (pyenv-virtualenv) because PyInstaller, whilst trying to find an appropriate `dest` path to put the files in, gets confused by `sys.prefix` (or its varients) not being a parent dir of the config and makefiles. As a (seemingly more rubust) alternative, this commit uses `sysconfig.get_python_inc(prefix=".")` to choose a dest dir instead. See https://github.com/pyinstaller/pyinstaller/issues/5018. --- PyInstaller/hooks/hook-distutils.py | 55 ++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/PyInstaller/hooks/hook-distutils.py b/PyInstaller/hooks/hook-distutils.py index 61f779be2f5..b4f36ac2d8a 100644 --- a/PyInstaller/hooks/hook-distutils.py +++ b/PyInstaller/hooks/hook-distutils.py @@ -17,19 +17,42 @@ runtime for platform-specific metadata. """ -# TODO Verify that bundling Makefile and pyconfig.h is still required for Python 3. - -import os -import sysconfig - -from PyInstaller.utils.hooks import relpath_to_config_or_make - -_CONFIG_H = sysconfig.get_config_h_filename() -_MAKEFILE = sysconfig.get_makefile_filename() - -# Data files in PyInstaller hook format. -datas = [(_CONFIG_H, relpath_to_config_or_make(_CONFIG_H))] - -# The Makefile does not exist on all platforms, eg. on Windows -if os.path.exists(_MAKEFILE): - datas.append((_MAKEFILE, relpath_to_config_or_make(_MAKEFILE))) +from distutils import sysconfig +import sys +from os import path + +from PyInstaller.utils.hooks import logger + + +if sys.version_info < (3, 6): + # XXX: Pythons >= 3.6 no longer use these files. Once we drop 3.5 support + # we can delete this. + + datas = [] + + # Locate the ``Include`` folder containing the two files. + INCLUDE = sysconfig.get_python_inc() + # Get a dist target location. This seems to handle venv and its many + # variants better than our own attempts involving ``sys.prefix``. See + # https://github.com/pyinstaller/pyinstaller/issues/4775. + DEST = sysconfig.get_python_inc(prefix=".") + + for filename in ["pyconfig.h", "Makefile"]: + source = path.join(INCLUDE, filename) + if path.exists(source): + datas.append((source, DEST)) + logger.debug("Add '{}' from '{}' to '{}'." + .format(filename, INCLUDE, DEST)) + else: + logger.debug("Skip non-existent '{}' from '{}' to '{}'." + .format(filename, INCLUDE, DEST)) + +else: + # In Python 3.6 and later ``distutils.sysconfig`` takes on the same + # behaviour as regular ``sysconfig`` of moving the config vars to an + # extension module (see hook-sysconfig.py). But it doesn't use a nice + # `get extension module name` function like ``sysconfig`` does. However the + # extension module is the same file that ``sysconfig`` uses so if we run + # the hook for ``sysconfig``, the extension module will be located and + # included. + hiddenimports = ["sysconfig"]