# ------------------------------------------------------------------
|
# Copyright (c) 2025 PyInstaller Development Team.
|
#
|
# This file is distributed under the terms of the GNU General Public
|
# License (version 2.0 or later).
|
#
|
# The full license is available in LICENSE, distributed with
|
# this software.
|
#
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
# ------------------------------------------------------------------
|
|
import os
|
import pathlib
|
import platform
|
|
from PyInstaller.utils.hooks import get_package_paths, logger
|
|
|
# tkinterdnd2 contains a tkdnd sub-directory which contains platform-specific directories with shared library and .tcl
|
# files. Collect only the relevant directory, by matching the decision logic from:
|
# https://github.com/Eliav2/tkinterdnd2/blob/9a55907e430234bf8ab72ea614f84af9cc89598c/tkinterdnd2/TkinterDnD.py#L33-L51
|
def _collect_platform_subdir(system, machine):
|
datas = []
|
binaries = []
|
|
# Under Windows, `platform.machine()` returns the identifier of the *host* architecture, which does not necessarily
|
# match the architecture of the running process (for example, when running x86 process under x64 Windows, or when
|
# running either x86 or x64 process under arm64 Windows). The architecture of the running process can be obtained
|
# from the `PROCESSOR_ARCHITECTURE` environment variable, which is automatically set by Windows / WOW64 subsystem.
|
#
|
# NOTE: at the time of writing (tkinterdnd2 v0.4.2), tkinterdnd2 does not account for this, and attempts to load
|
# the shared library from incorrect directory; as this fails due to architecture mismatch, there is no point in
|
# us trying to collect that (incorrect) directory.
|
if system == "Windows":
|
machine = os.environ.get("PROCESSOR_ARCHITECTURE", machine)
|
|
# Resolve the platform-specific sub-directory name and shared library suffix.
|
DIR_NAMES = {
|
"Darwin": {
|
"arm64": "osx-arm64",
|
"x86_64": "osx-x64",
|
},
|
"Linux": {
|
"aarch64": "linux-arm64",
|
"x86_64": "linux-x64",
|
},
|
"Windows": {
|
"ARM64": "win-arm64",
|
"AMD64": "win-x64",
|
"x86": "win-x86",
|
}
|
}
|
dir_name = DIR_NAMES.get(system, {}).get(machine, None)
|
|
LIB_SUFFICES = {
|
"Darwin": "*.dylib",
|
"Linux": "*.so",
|
"Windows": "*.dll",
|
}
|
lib_suffix = LIB_SUFFICES.get(system, None)
|
|
if dir_name is None or lib_suffix is None:
|
logger.warning(
|
"hook-tkinterdnd2: unsupported platform (%s, %s)! Platform-specific directory will not be collected!",
|
system, machine
|
)
|
return datas, binaries
|
|
pkg_base, pkg_dir = get_package_paths("tkinterdnd2")
|
|
dest_dir = os.path.join("tkinterdnd2", "tkdnd", dir_name)
|
src_path = pathlib.Path(pkg_dir) / "tkdnd" / dir_name
|
|
if not src_path.is_dir():
|
logger.warning("hook-tkinterdnd2: platform-specific sub-directory %r does not exist!", str(src_path))
|
return datas, binaries
|
|
# Collect the shared library.
|
for entry in src_path.glob(lib_suffix):
|
binaries.append((str(entry), dest_dir))
|
|
# Collect the .tcl files.
|
for entry in src_path.glob("*.tcl"):
|
datas.append((str(entry), dest_dir))
|
|
return datas, binaries
|
|
|
datas, binaries = _collect_platform_subdir(platform.system(), platform.machine())
|