Remove GhostScript, use SumatraPDF only for printing

- Remove find_ghostscript() and print_pdf_with_ghostscript() from print_label.py
- SumatraPDF is now the primary print method with -print-settings noscale
- Fix SumatraPDF arg order: file_path moved to last position
- Add -appdata-dir so SumatraPDF reads conf/SumatraPDF-settings.txt (PrintScale=noscale)
- win32api ShellExecute kept as last-resort fallback
- Remove GhostScript bundling from LabelPrinter.spec and build_exe.py
- Add conf/ folder pre-flight check to build_exe.py
- Rebuild dist/LabelPrinter.exe (41 MB, SumatraPDF-only)
This commit is contained in:
2026-02-25 10:00:56 +02:00
parent faef90f98b
commit b35f278c1e
71 changed files with 99 additions and 16518 deletions

View File

@@ -11,91 +11,41 @@ To build for Windows:
3. Run this script: python build_exe.py
4. The Windows .exe will be created in the dist/ folder
GhostScript bundling
--------------------
If GhostScript is installed on this build machine the script will
automatically copy the required files into conf\\ghostscript\\ before
calling PyInstaller so they are embedded in LabelPrinter.exe.
The target machine then needs NO separate GhostScript install.
Printing method
---------------
SumatraPDF is bundled inside the exe and used for all printing.
It sends the PDF at its exact 35x25 mm page size via -print-settings noscale.
No GhostScript installation required on the build or target machine.
"""
import os
import sys
import subprocess
import shutil
# Get the current directory
script_dir = os.path.dirname(os.path.abspath(__file__))
def prepare_ghostscript():
def check_conf_folder():
"""
Find the system GhostScript installation and copy the minimum files
needed for bundling into conf\\ghostscript\\.
Files copied:
conf\\ghostscript\\bin\\gswin64c.exe (or 32-bit variant)
conf\\ghostscript\\bin\\gsdll64.dll
conf\\ghostscript\\lib\\*.ps (PostScript init files)
Returns True if GhostScript was found and prepared, False otherwise.
Verify that required files are present in the conf\ folder before building.
Returns True if all required files exist, False otherwise.
"""
import glob
gs_exe = None
gs_dll = None
gs_lib = None
for pf in [r"C:\Program Files", r"C:\Program Files (x86)"]:
gs_base = os.path.join(pf, "gs")
if not os.path.isdir(gs_base):
continue
# Iterate versions newest-first
for ver_dir in sorted(os.listdir(gs_base), reverse=True):
bin_dir = os.path.join(gs_base, ver_dir, "bin")
lib_dir = os.path.join(gs_base, ver_dir, "lib")
if os.path.exists(os.path.join(bin_dir, "gswin64c.exe")):
gs_exe = os.path.join(bin_dir, "gswin64c.exe")
gs_dll = os.path.join(bin_dir, "gsdll64.dll")
gs_lib = lib_dir
break
if os.path.exists(os.path.join(bin_dir, "gswin32c.exe")):
gs_exe = os.path.join(bin_dir, "gswin32c.exe")
gs_dll = os.path.join(bin_dir, "gsdll32.dll")
gs_lib = lib_dir
break
if gs_exe:
break
if not gs_exe:
print(" WARNING: GhostScript not found on this machine.")
print(" The exe will still build but GhostScript will NOT be bundled.")
print(" Install GhostScript from https://ghostscript.com/releases/gsdnld.html")
print(" then rebuild for sharp vector-quality printing.")
return False
dest_bin = os.path.join("conf", "ghostscript", "bin")
dest_lib = os.path.join("conf", "ghostscript", "lib")
os.makedirs(dest_bin, exist_ok=True)
os.makedirs(dest_lib, exist_ok=True)
print(f" GhostScript found: {os.path.dirname(gs_exe)}")
shutil.copy2(gs_exe, dest_bin)
print(f" Copied: {os.path.basename(gs_exe)}")
if os.path.exists(gs_dll):
shutil.copy2(gs_dll, dest_bin)
print(f" Copied: {os.path.basename(gs_dll)}")
count = 0
for ps_file in glob.glob(os.path.join(gs_lib, "*.ps")):
shutil.copy2(ps_file, dest_lib)
count += 1
print(f" Copied {count} .ps init files from lib/")
print(f" GhostScript prepared in conf\\ghostscript\\")
return True
required = [
os.path.join('conf', 'SumatraPDF.exe'),
os.path.join('conf', 'SumatraPDF-settings.txt'),
os.path.join('conf', 'label_template_ok.svg'),
os.path.join('conf', 'label_template_nok.svg'),
os.path.join('conf', 'label_template.svg'),
]
all_ok = True
for f in required:
if os.path.exists(f):
print(f" OK: {f}")
else:
print(f" MISSING: {f}")
all_ok = False
return all_ok
if __name__ == '__main__':
@@ -106,15 +56,14 @@ if __name__ == '__main__':
# Change to script directory so relative paths work
os.chdir(script_dir)
# Step 1: Prepare GhostScript for bundling (Windows only)
if sys.platform == "win32":
print("\n[1/2] Preparing GhostScript for bundling...")
prepare_ghostscript()
else:
print("\n[1/2] Skipping GhostScript prep (non-Windows build machine)")
# Step 1: Verify conf\ folder contents
print("\n[1/2] Checking conf\\ folder...")
if not check_conf_folder():
print("\nERROR: One or more required conf\\ files are missing.")
print("Place SumatraPDF.exe and the SVG templates in the conf\\ folder, then retry.")
sys.exit(1)
# Step 2: Build with PyInstaller using the handcrafted spec file.
# The spec's Python code auto-detects conf\\ghostscript\\ and includes it.
print("\n[2/2] Building standalone executable via LabelPrinter.spec...")
print("This may take a few minutes...\n")
@@ -130,8 +79,7 @@ if __name__ == '__main__':
print("=" * 60)
print("\nExecutable location: ./dist/LabelPrinter.exe")
print("\nBundled components:")
print(" - GhostScript (vector-quality printing)")
print(" - SumatraPDF (fallback printing)")
print(" - SumatraPDF (primary printing, noscale 35x25 mm)")
print(" - SVG templates, conf files")
print("\nYou can now:")
print(" 1. Double-click LabelPrinter.exe to run")