111 lines
3.4 KiB
Python
111 lines
3.4 KiB
Python
# -*- mode: python ; coding: utf-8 -*-
|
|
import os
|
|
import sys
|
|
import PyQt5
|
|
|
|
# --- MONKEYPATCH PyInstaller QT Detection (Force correct path) ---
|
|
try:
|
|
from PyInstaller.utils.hooks import qt
|
|
|
|
# 1. Find the real plugin path
|
|
qt5_dir = os.path.dirname(PyQt5.__file__)
|
|
possible_plugin_paths = [
|
|
os.path.join(qt5_dir, 'Qt', 'plugins'),
|
|
os.path.join(qt5_dir, 'plugins'),
|
|
]
|
|
real_plugin_path = None
|
|
for p in possible_plugin_paths:
|
|
if os.path.exists(p):
|
|
real_plugin_path = p
|
|
break
|
|
|
|
# 2. Override the failing function
|
|
if real_plugin_path:
|
|
print(">>> FORCING QT PLUGINS PATH: {}".format(real_plugin_path))
|
|
|
|
# Save original just in case, though we ignore it
|
|
original_qt_plugins_dir = qt.qt_plugins_dir
|
|
|
|
def new_qt_plugins_dir(namespace=None):
|
|
return real_plugin_path
|
|
|
|
qt.qt_plugins_dir = new_qt_plugins_dir
|
|
|
|
# Also set env var as backup
|
|
os.environ['QT_PLUGIN_PATH'] = real_plugin_path
|
|
else:
|
|
print(">>> ERROR: Could not find PyQt5 plugins to monkeypatch!")
|
|
|
|
except ImportError:
|
|
print(">>> WARNING: Could not import PyInstaller.utils.hooks.qt for patching")
|
|
except Exception as e:
|
|
print(">>> WARNING: Monkeypatch failed: {}".format(e))
|
|
# -----------------------------------------------------------------------------
|
|
|
|
block_cipher = None
|
|
|
|
a = Analysis(
|
|
['main.py'],
|
|
pathex=[],
|
|
binaries=[],
|
|
# Bundle tools to sql_tools subfolder
|
|
datas=[
|
|
('icon.png', '.'),
|
|
('sql_tools/pg_dump.exe', 'sql_tools'),
|
|
('sql_tools/mysqldump.exe', 'sql_tools')
|
|
],
|
|
hiddenimports=['PyQt5', 'pymysql', 'psycopg2', 'apscheduler'],
|
|
hookspath=[],
|
|
runtime_hooks=['rthook_qt_fix.py'],
|
|
# Context7 Optimization: Exclude unused modules to reduce size
|
|
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter', 'matplotlib', 'numpy', 'scipy', 'pandas', 'PIL.ImageTk'],
|
|
win_no_prefer_redirects=False,
|
|
cipher=block_cipher,
|
|
)
|
|
|
|
# --- MANUAL BUNDLING OF PLATFORMS (Fix "platform plugin windows not found") ---
|
|
# Re-locate the plugins directory (redundant but safe)
|
|
qt5_dir = os.path.dirname(PyQt5.__file__)
|
|
plugin_sources = [
|
|
os.path.join(qt5_dir, 'Qt', 'plugins', 'platforms'),
|
|
os.path.join(qt5_dir, 'plugins', 'platforms'),
|
|
]
|
|
found_plugin = None
|
|
for p in plugin_sources:
|
|
if os.path.exists(p):
|
|
found_plugin = p
|
|
break
|
|
|
|
if found_plugin:
|
|
print(">>> MANUALLY BUNDLING PLATFORMS FROM: {}".format(found_plugin))
|
|
a.datas += Tree(found_plugin, prefix='platforms') # Bundle as root/platforms/
|
|
|
|
# Also bundle as root/qt/plugins/platforms just to match common fallback paths
|
|
# a.datas += Tree(found_plugin, prefix='qt/plugins/platforms')
|
|
else:
|
|
print(">>> ERROR: Could not find 'platforms' folder for bundling!")
|
|
# -----------------------------------------------------------------------------
|
|
|
|
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
|
|
|
# ONEFILE Mode: Everything bundled into single EXE
|
|
exe = EXE(
|
|
pyz,
|
|
a.scripts,
|
|
a.binaries,
|
|
a.zipfiles,
|
|
a.datas,
|
|
[],
|
|
name='ProBackup',
|
|
debug=False,
|
|
bootloader_ignore_signals=False,
|
|
strip=False,
|
|
upx=True,
|
|
upx_exclude=[],
|
|
runtime_tmpdir=None,
|
|
console=False,
|
|
disable_windowed_traceback=False,
|
|
argv_emulation=False,
|
|
icon='icon.ico',
|
|
)
|