Skip to content

Commit

Permalink
building: collect built-in extensions into lib-dynload sub-directory
Browse files Browse the repository at this point in the history
On macOS and linux, some of the python's built-ins have extension
modules that originally reside in python3.X/lib-dynload directory.
This directory is in sys.path, therefore the collected extensions
have no parent directory and end up directly in the _MEIPASS.

This commit explicitly diverts such extensions into lib-dynload
sub-directory in the _MEIPASS.

In addition to decluttering the _MEIPASS on linux and macOS, this
also prevents ctypes.CDLL() from picking up the extensions'
shared libraries and causing inconsistent behavior between
frozen and unfrozen application, which in some corner cases
leads to issues with shadowing, such as in pyinstaller#5583.
  • Loading branch information
rokm committed Mar 5, 2021
1 parent a21951d commit 4c2cdae
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion PyInstaller/building/api.py
Expand Up @@ -42,6 +42,16 @@
from PyInstaller.utils.win32 import winmanifest, icon, versioninfo, winresource


def _is_libdynload_extension(typ, dst, src):
"""
Determines if the given TOC entry is an EXTENSION coming from
python's lib-dynload directory.
"""
return typ == 'EXTENSION' \
and not os.path.dirname(os.path.normpath(dst)) \
and os.path.basename(os.path.dirname(src)) == 'lib-dynload'


class PYZ(Target):
"""
Creates a ZlibArchive that contains all pure Python modules.
Expand Down Expand Up @@ -233,6 +243,11 @@ def assemble(self):
# file is contained within python egg, it is added with the egg
continue
if typ in ('BINARY', 'EXTENSION', 'DEPENDENCY'):
if _is_libdynload_extension(typ, inm, fnm):
# Place extensions that originate from python's
# lib-dynload directory into _MEIPASS/lib-dynload
# instead of directly into _MEIPASS
inm = os.path.join('lib-dynload', inm)
if self.exclude_binaries and typ == 'EXTENSION':
self.dependencies.append((inm, fnm, typ))
elif not self.exclude_binaries or typ == 'DEPENDENCY':
Expand Down Expand Up @@ -734,7 +749,13 @@ def assemble(self):
or os.path.isabs(inm):
raise SystemExit('Security-Alert: try to store file outside '
'of dist-directory. Aborting. %r' % inm)
tofnm = os.path.join(self.name, inm)
if _is_libdynload_extension(typ, inm, fnm):
# Place extensions that originate from python's
# lib-dynload directory into _MEIPASS/lib-dynload
# instead of directly into _MEIPASS
tofnm = os.path.join(self.name, 'lib-dynload', inm)
else:
tofnm = os.path.join(self.name, inm)
todir = os.path.dirname(tofnm)
if not os.path.exists(todir):
os.makedirs(todir)
Expand Down

0 comments on commit 4c2cdae

Please sign in to comment.