diff options
| -rw-r--r-- | PicoStream.spec | 77 | ||||
| -rw-r--r-- | justfile | 2 |
2 files changed, 62 insertions, 17 deletions
diff --git a/PicoStream.spec b/PicoStream.spec index fb14691..f6fdcb9 100644 --- a/PicoStream.spec +++ b/PicoStream.spec @@ -1,44 +1,89 @@ # -*- mode: python ; coding: utf-8 -*- +import glob +import os +import sys + + +def find_libffi_dll(): + """ + Find the libffi-*.dll file required for _ctypes on Windows. + Searches in common locations for standard, venv, and Conda Python. + """ + if sys.platform != "win32": + return [] + + search_paths = [] + # Active environment's DLLs directory + search_paths.append(os.path.join(sys.prefix, "DLLs")) + + # Base Python installation's directories (if in a venv) + if hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix: + search_paths.append(os.path.join(sys.base_prefix, "DLLs")) + search_paths.append(os.path.join(sys.base_prefix, "Library", "bin")) + + # Conda environment's directory (if CONDA_PREFIX is set) + conda_prefix = os.environ.get("CONDA_PREFIX") + if conda_prefix: + search_paths.append(os.path.join(conda_prefix, "Library", "bin")) + + print("--- Searching for libffi DLL on Windows ---") + unique_paths = sorted(list(set(p for p in search_paths if os.path.isdir(p)))) + + for path in unique_paths: + print(f" - Checking: {path}") + dll_pattern = os.path.join(path, "libffi-*.dll") + found_dlls = glob.glob(dll_pattern) + if found_dlls: + dll_path = found_dlls[0] + print(f" - Found: {dll_path}") + return [(dll_path, ".")] # (source, destination_in_bundle) + + print("\nERROR: Could not find libffi-*.dll on Windows.") + sys.exit(1) + + +# --- PyInstaller Spec --- +app_name = 'PicoStream' +binaries = find_libffi_dll() if sys.platform == "win32" else [] a = Analysis( - ['picostream\\main.py'], + ['picostream/main.py'], pathex=[], - binaries=[], + binaries=binaries, datas=[], hiddenimports=[], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=None, noarchive=False, - optimize=0, ) -pyz = PYZ(a.pure) +pyz = PYZ(a.pure, a.zipped_data, cipher=None) exe = EXE( pyz, a.scripts, + a.binaries, + a.zipfiles, + a.datas, [], - exclude_binaries=True, - name='PicoStream', + name=app_name, debug=False, bootloader_ignore_signals=False, strip=False, upx=True, - console=False, + upx_exclude=[], + runtime_tmpdir=None, + console=False, # Creates a windowed (not console) executable disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, + icon=None, ) -coll = COLLECT( - exe, - a.binaries, - a.datas, - strip=False, - upx=True, - upx_exclude=[], - name='PicoStream', -) +# NOTE: The absence of a COLLECT block is what defines a one-file build. @@ -8,5 +8,5 @@ gui: # Build the picostream GUI executable build-gui: uv pip install pyinstaller pyinstaller-hooks-contrib - uv run pyinstaller PicoStream.spec --noconfirm + uv run pyinstaller --clean PicoStream.spec --noconfirm |
