# -*- mode: python ; coding: utf-8 -*- """PyInstaller spec for ProxyChainManager. Build: python -m PyInstaller --noconfirm --clean ProxyChainManager.spec Always builds relative to the spec file's directory so the script works on any machine / CI runner. """ import os from pathlib import Path from PyInstaller.utils.hooks import collect_all # SPECPATH is provided by PyInstaller; fall back to CWD for IDE linters. _ROOT = Path(globals().get("SPECPATH", os.getcwd())).resolve() datas = [] binaries = [] hiddenimports = [ 'pystray._win32', 'PIL._tkinter_finder', ] tmp_ret = collect_all('customtkinter') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] # Bundle runtime data files. Each tuple is (src_relative_to_spec, dest_in_bundle). _BUNDLE_DATA = [ ('proxy_chain_manager/signup_extension', 'proxy_chain_manager/signup_extension'), ('proxy_chain_manager/world_map.png', 'proxy_chain_manager'), # B-06: Bundle gost.exe (and its SHA256 sidecar) so first run works # offline. scripts/prepare_bundled_gost.ps1 stages these files before # PyInstaller runs. Missing files are silently skipped so source # checkouts that haven't staged the binary still build. ('proxy_chain_manager/_bundled/gost.exe', 'proxy_chain_manager/_bundled'), ('proxy_chain_manager/_bundled/gost.exe.sha256','proxy_chain_manager/_bundled'), ] for src, dest in _BUNDLE_DATA: p = _ROOT / src if p.exists(): datas.append((str(p), dest)) a = Analysis( [str(_ROOT / 'run.py')], pathex=[str(_ROOT)], binaries=binaries, datas=datas, hiddenimports=hiddenimports, hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], noarchive=False, optimize=0, ) pyz = PYZ(a.pure) exe = EXE( pyz, a.scripts, a.binaries, a.datas, [], name='ProxyChainManager', debug=False, bootloader_ignore_signals=False, strip=False, upx=False, upx_exclude=[], runtime_tmpdir=None, console=False, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, uac_admin=True, )