# -*- mode: python ; coding: utf-8 -*- import os from pathlib import Path # 🔥 Base path fiable (indépendant du dossier de lancement) BASE_DIR = Path(os.getcwd()).resolve() if not (BASE_DIR / "src").exists(): raise Exception("Lance PyInstaller depuis la racine du projet") print("BASE_DIR =", BASE_DIR) # ------------------------------------------------------------------ # Analysis # ------------------------------------------------------------------ a = Analysis( [str(BASE_DIR / 'src' / 'main.py')], pathex=['src'], binaries=[], datas=[ # Assets critiques (str(BASE_DIR / 'assets' / 'Icon.ico'), 'assets'), # Styles (str(BASE_DIR / 'styles' / 'styles.qss'), 'styles'), # UI (tu peux ajouter d'autres .ui ici) (str(BASE_DIR / 'ui' / 'mainwindow_vertical_pager.ui'), 'ui'), ], hiddenimports=[ "asyncio", "pypresence" ], hookspath=[], hooksconfig={ # 🔥 STRICT MINIMUM "qt_plugins": ["platforms"] }, runtime_hooks=[], # 🔥 Exclusions excludes=[ # PySide6 - modules non utilisés 'PySide6.Qt3DAnimation', 'PySide6.Qt3DCore', 'PySide6.Qt3DExtras', 'PySide6.Qt3DInput', 'PySide6.Qt3DLogic', 'PySide6.Qt3DRender', 'PySide6.QtAxContainer', 'PySide6.QtBluetooth', 'PySide6.QtCharts', 'PySide6.QtConcurrent', 'PySide6.QtDataVisualization', 'PySide6.QtDesigner', 'PySide6.QtHelp', 'PySide6.QtLocation', # 'PySide6.QtMultimedia', # Nécessaire pour l'audio 'PySide6.QtMultimediaWidgets', # 'PySide6.QtNetwork', # Dépendance à QtMultimedia 'PySide6.QtNetworkAuth', 'PySide6.QtNfc', 'PySide6.QtOpenGL', 'PySide6.QtOpenGLWidgets', 'PySide6.QtPdf', 'PySide6.QtPdfWidgets', 'PySide6.QtPositioning', 'PySide6.QtPrintSupport', 'PySide6.QtQml', 'PySide6.QtQuick', 'PySide6.QtQuick3D', 'PySide6.QtQuickControls2', 'PySide6.QtQuickWidgets', 'PySide6.QtRemoteObjects', 'PySide6.QtScxml', 'PySide6.QtSensors', 'PySide6.QtSerialBus', 'PySide6.QtSerialPort', 'PySide6.QtSpatialAudio', 'PySide6.QtSql', 'PySide6.QtStateMachine', 'PySide6.QtSvg', 'PySide6.QtSvgWidgets', 'PySide6.QtTest', 'PySide6.QtTextToSpeech', 'PySide6.QtWebChannel', 'PySide6.QtWebEngineCore', 'PySide6.QtWebEngineQuick', 'PySide6.QtWebEngineWidgets', 'PySide6.QtWebSockets', 'PySide6.QtXml', # Tests / dev tools "test", "tests", "unittest", "doctest", "pydoc", "pydoc_data", # Packaging / build tooling "distutils", "setuptools", "pkg_resources", "pip", "ensurepip", # GUI stdlib inutiles "tkinter", "turtle", "idlelib", "curses", # Legacy / obsolete "lib2to3", "2to3", "nis", "ossaudiodev", "spwd", # RPC / servers non utilisés "xmlrpc", "wsgiref", "cgi", "cgitb", # Data / DB non utilisés "sqlite3", "dbm", "dbm.dumb", "csv", # Concurrency non utilisée dans ton code "multiprocessing", #"concurrent", #"asyncio", # REPL / terminal "readline", "code", # "codeop", # Nécessaire "cmd", # mail / network protocols non utilisés "mailbox", "imaplib", "poplib", "smtplib", "nntplib", "telnetlib", "ftplib", "netrc", # Docs / browsing / parsing non utilisés directement "pydoc_data", "mailbox", "imaplib", "poplib", "smtplib", "nntplib", "telnetlib", # XML optionnel : agressif mais plutôt safe ici "xml.dom", "xml.etree", "xml.parsers", "xml.sax", # Compression / archive optionnelles si non utilisées "bz2", "lzma", "gzip", #"zipfile", # Nécessaire à cause de pyinstaller "tarfile", "zipapp", # audio stdlib non utilisée "aifc", "wave", "sunau", "chunk", # divers peu probables "mailcap", "xdrlib", "tabnanny", "getpass", # Windows services non utilisés "win32service", "win32serviceutil", ], noarchive=False, optimize=2, ) # ------------------------------------------------------------------ # 🔥 Nettoyage DLL Qt (SAFE) # ------------------------------------------------------------------ unwanted_dlls = [ 'Qt6Pdf', 'Qt6Quick', 'Qt6Qml', 'Qt6QmlModels', 'Qt6QmlWorkerScript', 'Qt6WebEngine', 'Qt6WebEngineCore', 'Qt63DCore', 'Qt63DRender', 'Qt63DAnimation', 'Qt63DExtras', 'Qt63DInput', 'Qt63DLogic', 'Qt6Charts', 'Qt6DataVisualization', 'Qt6Bluetooth', 'Qt6Nfc', 'Qt6Positioning', 'Qt6Location', 'Qt6RemoteObjects', 'Qt6Scxml', 'Qt6Sensors', 'Qt6SerialBus', 'Qt6SerialPort', 'Qt6SpatialAudio', 'Qt6StateMachine', # 'Qt6Svg', # Dependance lecteur svg 'Qt6TextToSpeech', 'Qt6WebChannel', 'Qt6WebSockets', 'Qt6Sql', 'Qt6Test', # 'Qt6OpenGL', # Dependance a Qt6UiTools 'Qt6PrintSupport', # 'Qt6Xml', # Dependance fichier .ui 'Qt6Help', 'Qt6Designer', 'Qt6Concurrent', ] a.binaries = [ (name, path, typecode) for name, path, typecode in a.binaries if not any(u.lower() in name.lower() for u in unwanted_dlls) ] # ------------------------------------------------------------------ # 🔥 Suppression traductions Qt (gain taille) # ------------------------------------------------------------------ a.datas = [ f for f in a.datas if "translations" not in f[0].lower() and not f[0].endswith('.qm') ] pyz = PYZ(a.pure, a.zipped_data) exe = EXE( pyz, a.scripts, a.binaries, a.datas, [], name='La Tanière Launcher', debug=False, bootloader_ignore_signals=False, strip=False, # 🔥 Compression max upx=True, upx_exclude=[ "_uuid.pyd", "Qt6Core.dll", "Qt6Gui.dll", "Qt6Widgets.dll", "Qt6UiTools.dll", "qwindows.dll", "python3*.dll", "vcruntime*.dll", "msvcp*.dll", ], runtime_tmpdir=None, console=False, # 🔥 ONEFILE onefile=True, disable_windowed_traceback=True, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, # 🔥 Icône EXE (important mais pas suffisant seul) icon=str(BASE_DIR / 'assets' / 'Icon.ico'), )