# calendar_gui.spec # -*- mode: python ; coding: utf-8 -*- import os from PyInstaller.utils.hooks import collect_all # Collect reportlab barcode data as you already did datas = [] binaries = [] hiddenimports = [] tmp_ret = collect_all('reportlab.graphics.barcode') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] # ---- Analysis ---- a = Analysis( ['calendar_gui.py'], pathex=[os.getcwd()], binaries=binaries, datas=datas, hiddenimports=hiddenimports, hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=['scipy'], # keep your existing excludes noarchive=False, optimize=0, ) # ---- Helper: drop specific native libs / plugin files we listed ---- # IMPORTANT: do NOT drop essential Qt runtime libs needed for your platform. ESSENTIAL_QT_NAMES = [ 'libQt5Core.so', 'libQt5Gui.so', 'libQt5Widgets.so', 'libQt5XcbQpa.so', 'libpython3.12.so', 'libstdc++.so.6', 'libc.so.6' ] DROP_PATTERNS = [ # Pillow image codec libs you identified 'libavif-', 'libwebp-', 'liblcms2-', 'libsharpyuv', 'libwebpdemux', 'libwebpmux', # Qt optional subsystems you listed (Quick, Qml, QmlModels, Svg, WebSockets) 'libQt5Quick.so', 'libQt5Qml.so', 'libQt5QmlModels.so', 'libQt5Svg.so', 'libQt5WebSockets.so', 'libQt5EglFSDeviceIntegration.so', ] def should_drop_path(path_str): s = str(path_str) # never drop critical essentials for ess in ESSENTIAL_QT_NAMES: if ess in s: return False # drop if pattern matches for p in DROP_PATTERNS: if p in s: return True # also drop QML/translations directories if '/qml/' in s or '\\qml\\' in s: return True if '/translations/' in s or '\\translations\\' in s: return True return False # ---------- robust filtering for a.binaries / a.datas ---------- def _entry_src(obj): """ Return the 'source' part of a TOC entry for binaries/datas. PyInstaller entries may be (src, dest) or (src, dest, type) etc. """ try: # sequence-like entries (tuple/list) return obj[0] except Exception: # fallback: maybe it's already a path-like object return obj filtered_binaries = [] for entry in a.binaries: src = _entry_src(entry) if should_drop_path(src): # drop it # print("Dropping binary:", src) # uncomment for debugging continue filtered_binaries.append(entry) a.binaries = filtered_binaries filtered_datas = [] for entry in a.datas: src = _entry_src(entry) if should_drop_path(src): # print("Dropping data:", src) # uncomment for debugging continue filtered_datas.append(entry) a.datas = filtered_datas # ---------------------------------------------------------------- # ---- Build steps: PYZ, EXE, COLLECT ---- pyz = PYZ(a.pure, a.zipped_data, cipher=None) exe = EXE( pyz, a.scripts, [], exclude_binaries=True, name='azrechner', debug=False, bootloader_ignore_signals=False, strip=True, # on Linux: strip Python bootstrap (saves some MB) upx=True, console=False, ) coll = COLLECT( exe, a.binaries, a.zipfiles, a.datas, strip=True, # strip shared objects where safe upx=True, upx_exclude=[], # leave empty; PyInstaller will avoid known-bad files name='azrechner-trimmed', )