Skip to content

Commit

Permalink
Hooks: distutils: Fix no suitable dest location found for pyconfig.h.
Browse files Browse the repository at this point in the history
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 pyinstaller#5018.
  • Loading branch information
bwoodsend committed Oct 3, 2020
1 parent 2d707ea commit 389d7c6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 13 deletions.
66 changes: 53 additions & 13 deletions PyInstaller/hooks/hook-distutils.py
@@ -1,4 +1,4 @@
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Copyright (c) 2005-2020, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
Expand All @@ -7,7 +7,7 @@
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

"""
`distutils`-specific post-import hook.
Expand All @@ -17,19 +17,59 @@
runtime for platform-specific metadata.
"""

# TODO Verify that bundling Makefile and pyconfig.h is still required for Python 3.
from distutils import sysconfig
import sys
from os import path
from pathlib import Path

import os
import sysconfig
from PyInstaller.utils.hooks import logger

from PyInstaller.utils.hooks import relpath_to_config_or_make
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.

_CONFIG_H = sysconfig.get_config_h_filename()
_MAKEFILE = sysconfig.get_makefile_filename()
datas = []

# Data files in PyInstaller hook format.
datas = [(_CONFIG_H, relpath_to_config_or_make(_CONFIG_H))]
# Locate the ``Include`` folder containing the two files.
include_src = 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.
include_dest = sysconfig.get_python_inc(prefix=".")

# 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)))
makefile_src = path.join(include_src, "pyconfig.h")
if path.exists(makefile_src):
datas.append((makefile_src, include_dest))
logger.debug("Add pyconfig.h from '{}' to '{}'."
.format(include_src, include_dest))
else:
logger.debug("Skip non-existent pyconfig.h from '{}'."
.format(include_src))

# The above works well for pyconfig.h. But there is no equivalent function
# for makefile which has the ``prefix="."`` option. Work out which prefix
# the above used:
prefix = path.join(
*Path(include_src).parts[: -len(Path(include_dest).parts)]
)

makefile_src = sysconfig.get_makefile_filename()
if path.exists(makefile_src):
makefile_dest = path.dirname(path.relpath(makefile_src, prefix))
datas.append((makefile_src, makefile_dest))
logger.debug("Add Makefile from '{}' to '{}'."
.format(makefile_src, makefile_dest))
else:
logger.debug("Skip non-existent Makefile from '{}'."
.format(makefile_src))


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"]
1 change: 1 addition & 0 deletions news/5218.hooks.rst
@@ -0,0 +1 @@
Update hook for ``distutils.sysconfig`` to be compatible with pyenv-virtualenv.

0 comments on commit 389d7c6

Please sign in to comment.