From bd6827cb2f2162a5bb34360f0696f80991cf11af Mon Sep 17 00:00:00 2001 From: Vitali Graf Date: Sun, 15 Mar 2026 19:37:10 +0100 Subject: [PATCH] Docs: BUILD.md mit windows_distribution.md konsolidiert und Einzeldatei entfernt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gesamte Windows-Distribution-Dokumentation (ZIP, Setup.exe, MSI) in BUILD.md zusammengeführt. docs/windows_distribution.md entfernt, da redundant. Co-Authored-By: Claude Opus 4.6 --- BUILD.md | 214 ++++++++++++++----- docs/windows_distribution.md | 404 ----------------------------------- 2 files changed, 156 insertions(+), 462 deletions(-) delete mode 100644 docs/windows_distribution.md diff --git a/BUILD.md b/BUILD.md index 3178776..f01e193 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,15 +1,19 @@ # DocuMentor Build-Anleitung -## Schnellstart: Windows-Distribution erstellen - -### Voraussetzungen +## Voraussetzungen ```bash -# Dependencies installieren (inkl. Pillow für Icon-Generierung) +# Dependencies installieren (inkl. Pillow für Icon-Generierung und PyInstaller) uv sync --all-groups ``` -### Build ausführen +Für MSI-Installer zusätzlich: +- **WiX Toolset v6**: `dotnet tool install --global wix` + +Für Setup.exe zusätzlich: +- **Inno Setup**: https://jrsoftware.org/isdl.php + +## Schnellstart: ZIP-Distribution erstellen ```bash # Automatischer Build (empfohlen) @@ -22,16 +26,6 @@ Dies erstellt automatisch: 3. **Executable**: `dist/DocuMentor/DocuMentor.exe` (mit Icon und Versionsinformationen) 4. **ZIP-Archiv**: `dist/DocuMentor-YYYYMMDD-Windows.zip` -### Icon anpassen (optional) - -```bash -# Standard-Icon generieren -uv run python create_icon.py - -# Oder eigenes PNG-Icon konvertieren -uv run python create_icon.py mein-logo.png -``` - ### Manuelle Build-Schritte ```bash @@ -46,13 +40,64 @@ uv run pyinstaller --clean DocuMentor.spec # Mit Wine: wine dist/DocuMentor/DocuMentor.exe ``` -## Setup.exe erstellen (optional) +## MSI-Installer erstellen (WiX Toolset) -### Mit Inno Setup +### Schritt 1: PyInstaller Build erstellen -1. **Inno Setup installieren**: https://jrsoftware.org/isdl.php +```bash +uv run python build_windows.py +``` -2. **GUID generieren** für `installer.iss` (nur beim ersten Mal!): +### Schritt 2: ProductFiles.wxs generieren + +**WICHTIG**: WiX v6 hat das `heat` Tool entfernt. Stattdessen wird ein Python-Skript verwendet: + +```bash +# Generiert automatisch ProductFiles.wxs mit allen Dateien aus dist/DocuMentor +uv run python generate_wix_files.py +``` + +### Schritt 3: MSI kompilieren + +```bash +wix build DocuMentor.wxs ProductFiles.wxs -o DocuMentor.msi +``` + +### Schritt 4: MSI testen + +```bash +# Installation (als Administrator) +msiexec /i DocuMentor.msi + +# Silent Installation für Deployment +msiexec /i DocuMentor.msi /quiet /qn /norestart + +# Deinstallation +msiexec /x DocuMentor.msi +``` + +### MSI-Vorteile + +- Windows-Standard (`.msi` Format) +- Gruppen-Richtlinien-Deployment (GPO) für Enterprise +- Silent Installation (`msiexec /quiet`) +- Windows Installer Transaktionen und Rollback +- Patch-Unterstützung (.msp für Updates) +- Versionsupgrades automatisch verwaltet + +### MSI-Build automatisieren + +Alternativ zu den manuellen Schritten kann ein `build_msi.py` Skript verwendet werden: + +```bash +uv run python build_msi.py +``` + +Dieses Skript führt `generate_wix_files.py` und `wix build` automatisch nacheinander aus. + +## Setup.exe erstellen (Inno Setup) + +1. **GUID generieren** für `installer.iss` (nur beim ersten Mal!): ```bash uv run python generate_guid.py ``` @@ -61,25 +106,19 @@ uv run pyinstaller --clean DocuMentor.spec **WICHTIG**: Die GUID nur EINMAL generieren! Bei Updates dieselbe GUID verwenden. -3. **Windows-Build erstellen**: +2. **Windows-Build erstellen**: ```bash uv run python build_windows.py ``` - Dies erstellt automatisch das Icon und kopiert es nach `dist/DocuMentor/`. - -4. **Installer kompilieren**: +3. **Installer kompilieren**: ```bash iscc installer.iss ``` -5. **Ergebnis**: +4. **Ergebnis**: - `dist/installer/DocuMentor-Setup-0.1.0.exe` (mit Icon und Versionsinformationen) -## MSI erstellen (optional) - -Mit WiX Toolset - noch zu implementieren. - ## Konfiguration anpassen ### Icon anpassen @@ -110,16 +149,12 @@ Das Icon wird automatisch verwendet für: ### Versionsinformationen -**Automatische Generierung:** - Versionsinformationen werden automatisch aus `pyproject.toml` generiert: ```bash uv run python create_version_info.py ``` -Dies liest die Version aus `pyproject.toml` und erstellt `version_info.txt`. - **Version ändern:** In `pyproject.toml`: @@ -177,13 +212,13 @@ exe = EXE( ## Testing -### Lokales Testing +### Lokales Testing (Linux/WSL) ```bash # Build erstellen uv run python build_windows.py -# Mit Wine testen (Linux/WSL) +# Mit Wine testen wine dist/DocuMentor/DocuMentor.exe ``` @@ -205,13 +240,27 @@ wine dist/DocuMentor/DocuMentor.exe ### "Module not found" beim Start -**Lösung**: Hidden imports in `DocuMentor.spec` ergänzen: +**Lösung A** — Einfache Python-Module: Hidden imports in `DocuMentor.spec` ergänzen: ```python hiddenimports=[ - 'missing.module', + 'missing_module', ] ``` +**Lösung B** — Packages mit nativen Extensions (Rust/C, z.B. `connectorx`): +`hiddenimports` allein reicht nicht, da PyInstaller die `__init__.py` ins PYZ-Archiv packt, aber die `.pyd`-Extension separat im Dateisystem erwartet. Stattdessen `collect_all` verwenden: +```python +from PyInstaller.utils.hooks import collect_all +cx_datas, cx_binaries, cx_hiddenimports = collect_all('problematic_package') + +a = Analysis( + # ... + binaries=cx_binaries, + datas=cx_datas, + hiddenimports=cx_hiddenimports, +) +``` + ### Antivirus blockiert die .exe **Ursache**: Unsigned executables werden oft als verdächtig eingestuft. @@ -237,11 +286,46 @@ hiddenimports=[ datas=ui_files, # Muss gesetzt sein ``` +Im Code müssen Ressource-Pfade PyInstaller-kompatibel aufgelöst werden: +```python +import sys +from pathlib import Path + +if hasattr(sys, "_MEIPASS"): + res_path = Path(sys._MEIPASS) / "res" / "data.sql" +else: + res_path = Path(__file__).parents[3] / "src" / "res" / "data.sql" +``` + ## Automatisierung ### GitHub Actions (CI/CD) -Siehe `docs/windows_distribution.md` für vollständiges Beispiel. +```yaml +name: Build Windows Release + +on: + push: + tags: + - 'v*' + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Install uv + uses: astral-sh/setup-uv@v1 + + - name: Build + run: uv run python build_windows.py + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: dist/*.zip +``` ### Lokales Release-Skript @@ -268,30 +352,29 @@ echo " • ZIP: dist/DocuMentor-*-Windows.zip" echo " • Setup: dist/installer/DocuMentor-Setup-$VERSION.exe" ``` -## Distribution +## Distributions-Formate im Vergleich -### ZIP-Archiv +| | ZIP | Setup.exe (Inno Setup) | MSI (WiX) | +|---|---|---|---| +| **Portabel** | Ja | Nein | Nein | +| **Installation nötig** | Nein | Ja | Ja | +| **Deinstallation** | Nein | Ja | Ja | +| **Start-Menü** | Nein | Ja | Ja | +| **GPO-Deployment** | Nein | Nein | Ja | +| **Silent Install** | — | Ja | Ja | +| **Rollback** | — | Nein | Ja | +| **Patch-Support** | — | Nein | Ja (.msp) | -**Vorteile:** -- Einfach, portable -- Keine Installation nötig -- USB-Stick-fähig +## Externe Abhängigkeiten -**Verwendung:** -- Auf GitHub Releases hochladen -- Per E-Mail versenden -- Auf Webserver bereitstellen +DocuMentor benötigt diese Tools (NICHT im Installer enthalten): -### Setup.exe +1. **Java Runtime Environment (JRE) 11+** — Für Saxon und Apache FOP (https://adoptium.net/) +2. **Apache FOP** — XSL-FO zu PDF Konvertierung (https://xmlgraphics.apache.org/fop/) +3. **Saxon XSLT Prozessor** — XSLT 2.0/3.0 Transformationen (https://www.saxonica.com/) +4. **diff-pdf** — PDF-Vergleich (https://vslavik.github.io/diff-pdf/) -**Vorteile:** -- Professionell -- Start-Menü-Integration -- Deinstallation - -**Verwendung:** -- Primäre Distributions-Methode -- Auf Website zum Download anbieten +Nach der Installation müssen die Pfade zu diesen Tools in den DocuMentor-Einstellungen konfiguriert werden. ## Dokumentation für Endbenutzer @@ -300,6 +383,21 @@ Die `dist/DocuMentor/README.txt` wird automatisch erstellt und enthält: - Liste der externen Abhängigkeiten - Konfigurationshinweise -## Weitere Informationen +## Versionierung -Siehe `docs/windows_distribution.md` für detaillierte Dokumentation. +Version in folgenden Dateien aktualisieren: +1. `pyproject.toml` — `version = "X.Y.Z"` +2. `installer.iss` — `#define MyAppVersion "X.Y.Z"` + +Dann Versionsinformationen neu generieren: +```bash +uv run python create_version_info.py +``` + +## Lizenz und Rechtliches + +- PySide6 (LGPL): Dynamische Verlinkung ist OK +- Polars (MIT): Unproblematisch +- Pydantic (MIT): Unproblematisch + +Externe Tools (Saxon, FOP) haben eigene Lizenzen und müssen separat installiert werden. diff --git a/docs/windows_distribution.md b/docs/windows_distribution.md deleted file mode 100644 index e8f0c4f..0000000 --- a/docs/windows_distribution.md +++ /dev/null @@ -1,404 +0,0 @@ -# Windows Distribution Guide für DocuMentor - -## Überblick - -Dieses Dokument beschreibt, wie DocuMentor für Windows-Benutzer ohne Python-Installation verpackt wird. - -## Voraussetzungen - -### Auf dem Entwicklungssystem - -```bash -# Dependencies installieren (inkl. PyInstaller) -uv sync --all-groups -``` - -### Für Setup.exe (optional) - -- **Inno Setup**: Download von https://jrsoftware.org/isdl.php -- Oder **WiX Toolset** für MSI: https://wixtoolset.org/ - -## Build-Prozess - -### Option 1: Einfacher Build (ZIP-Distribution) - -```bash -# 1. PyInstaller installieren -uv sync --all-groups - -# 2. Build ausführen -uv run python build_windows.py -``` - -Dies erstellt: -- `dist/DocuMentor/DocuMentor.exe` - Eigenständige Executable -- `dist/DocuMentor-YYYYMMDD-Windows.zip` - Portable ZIP-Archiv - -### Option 2: Professionelle Setup.exe mit Inno Setup - -```bash -# 1. PyInstaller Build -uv run python build_windows.py - -# 2. Inno Setup Compiler ausführen -iscc installer.iss -``` - -Dies erstellt: -- `dist/installer/DocuMentor-Setup-0.1.0.exe` - Professioneller Installer - -### Option 3: MSI-Installer mit WiX - -**Voraussetzungen:** -```bash -# WiX Toolset v6 installieren (aktuell) -dotnet tool install --global wix -``` - -**Schritt 1: PyInstaller Build erstellen** -```bash -uv run python build_windows.py -``` - -**Schritt 2: ProductFiles.wxs generieren** - -**WICHTIG**: WiX v6 hat das `heat` Tool entfernt. Stattdessen verwenden wir ein Python-Skript: - -```bash -# Generiert automatisch ProductFiles.wxs mit allen Dateien aus dist/DocuMentor -uv run python generate_wix_files.py -``` - -**Schritt 3: MSI kompilieren** -```bash -# WiX v6 Build -wix build DocuMentor.wxs ProductFiles.wxs -o DocuMentor.msi -``` - -**Hinweis**: Die Dateien `DocuMentor.wxs` und `generate_wix_files.py` sind bereits im Repository vorhanden und WiX v4/v6-kompatibel. - -**Schritt 4: MSI testen** -```bash -# Installation (als Administrator) -msiexec /i DocuMentor.msi - -# Silent Installation für Deployment -msiexec /i DocuMentor.msi /quiet /qn /norestart - -# Deinstallation -msiexec /x DocuMentor.msi -``` - -**MSI-Vorteile gegenüber Inno Setup:** -- ✅ Windows-Standard (`.msi` Format) -- ✅ Gruppen-Richtlinien-Deployment (GPO) -- ✅ Silent Installation für Enterprise -- ✅ Windows Installer Service Transaktionen -- ✅ Rollback bei Fehlern -- ✅ Patch-Unterstützung (.msp) - -**Build-Automatisierung (`build_msi.py`):** -```python -"""WiX MSI Build-Skript für DocuMentor (WiX v6)""" -import subprocess -import sys -from pathlib import Path - -def build_msi(): - project_root = Path(__file__).parent - dist_dir = project_root / "dist" / "DocuMentor" - - if not dist_dir.exists(): - print("Fehler: PyInstaller Build nicht gefunden. Erst build_windows.py ausführen!") - sys.exit(1) - - # Schritt 1: ProductFiles.wxs generieren (ersetzt heat) - print("Generiere ProductFiles.wxs...") - subprocess.run([ - "uv", "run", "python", "generate_wix_files.py" - ], check=True) - - # Schritt 2: MSI kompilieren mit WiX v6 - print("Kompiliere MSI-Installer...") - subprocess.run([ - "wix", "build", - "DocuMentor.wxs", - "ProductFiles.wxs", - "-o", "DocuMentor.msi" - ], check=True) - - print("\n[OK] MSI erstellt: DocuMentor.msi") - -if __name__ == "__main__": - build_msi() -``` - -## Manuelle Schritte - -### 1. PyInstaller direkt verwenden - -```bash -# Cleanup -rm -rf build/ dist/ - -# Build -uv run pyinstaller --clean DocuMentor.spec - -# Testen -dist/DocuMentor/DocuMentor.exe -``` - -### 2. Anpassungen vornehmen - -**Icon hinzufügen:** -1. Icon-Datei (`.ico`) im Projekt speichern, z.B. `resources/icon.ico` -2. In `DocuMentor.spec` anpassen: - ```python - icon='resources/icon.ico' - ``` - -**Versionsinformationen:** -In `DocuMentor.spec` erweitern: -```python -exe = EXE( - # ... - version='version_info.txt', # Windows-Versionsinformationen -) -``` - -## PyInstaller .spec Konfiguration - -Die Datei `DocuMentor.spec` enthält: - -- **datas**: UI-Dateien (.ui), Ressource-Dateien (SQL, CSV) und connectorx-Package -- **binaries**: Native Extensions (connectorx `.pyd`) -- **hiddenimports**: Alle notwendigen PySide6/Polars-Module -- **collect_all('connectorx')**: Sammelt Python-Code, native `.pyd`-Extension und Metadaten als Einheit (nötig, da `polars` connectorx erst zur Laufzeit per `importlib.import_module()` lädt) -- **console=False**: GUI-Anwendung ohne Konsole -- **upx=True**: Kompression der Binaries - -### Wichtige Einstellungen - -```python -# Ein-Datei-Build (alles in einer .exe) -exe = EXE( - pyz, - a.scripts, - a.binaries, # Diese Zeilen - a.zipfiles, # auskommentieren - a.datas, # für One-File - # ... - onefile=True, # Hinzufügen -) -``` - -**Achtung**: One-File-Build ist langsamer beim Start, da alles temporär entpackt werden muss. - -## Distribution - -### ZIP-Archive - -```bash -# Automatisch durch build_windows.py erstellt -dist/DocuMentor-YYYYMMDD-Windows.zip -``` - -**Vorteile:** -- Einfach, portable -- Keine Installation nötig -- Kann auf USB-Stick verwendet werden - -**Nachteile:** -- Keine Deinstallationsroutine -- Keine Verknüpfungen -- Keine Registry-Einträge - -### Setup.exe mit Inno Setup - -**Vorteile:** -- Professionell -- Deinstallation integriert -- Start-Menü und Desktop-Icons -- Update-Mechanismus möglich - -**Nachteile:** -- Benötigt Administrator-Rechte (optional) -- Komplexere Konfiguration - -### MSI-Installer (WiX) - -**Vorteile:** -- Windows-Standard (.msi Format) -- Gruppen-Richtlinien-Deployment (GPO) für Enterprise -- Silent Installation möglich (`msiexec /quiet`) -- Windows Installer Transaktionen und Rollback -- Patch-Unterstützung (.msp für Updates) -- Deinstallation über Systemsteuerung integriert -- Versionsupgrades automatisch verwaltet - -**Nachteile:** -- Komplexere Erstellung als Inno Setup -- Benötigt WiX Toolset (kostenlos) -- XML-basierte Konfiguration -- Lernkurve für WiX-Syntax - -## Externe Abhängigkeiten - -DocuMentor benötigt diese Tools (NICHT im Installer enthalten): - -1. **Java Runtime Environment (JRE) 11+** - - Für Saxon und Apache FOP - - Download: https://adoptium.net/ - -2. **Apache FOP** - - XSL-FO zu PDF Konvertierung - - Download: https://xmlgraphics.apache.org/fop/ - -3. **Saxon XSLT Prozessor** - - XSLT 2.0/3.0 Transformationen - - Download: https://www.saxonica.com/ - -4. **diff-pdf** - - PDF-Vergleich - - Download: https://vslavik.github.io/diff-pdf/ - -### Benutzer-Anleitung - -Nach der Installation: - -1. DocuMentor starten -2. Beim ersten Start öffnet sich automatisch die Einstellungen -3. Pfade zu Java, Saxon, FOP und diff-pdf konfigurieren -4. Projekt-Verzeichnis wählen oder neues Projekt erstellen - -## Testing - -### Lokales Testing (Linux/WSL) - -```bash -# Build für Windows erstellen -uv run python build_windows.py - -# Executable mit Wine testen (falls verfügbar) -wine dist/DocuMentor/DocuMentor.exe -``` - -### Testing auf Windows - -1. ZIP auf Windows-System kopieren -2. Entpacken -3. `DocuMentor.exe` ausführen -4. Alle Features testen: - - Projekt öffnen/erstellen - - Tree-Navigation - - PDF-Generierung - - Einstellungen - -## Troubleshooting - -### Problem: "Module not found" Fehler - -**Lösung A** – Einfache Python-Module: Hidden imports in `DocuMentor.spec` ergänzen: -```python -hiddenimports=[ - # ... existing - 'missing_module', -] -``` - -**Lösung B** – Packages mit nativen Extensions (Rust/C, z.B. `connectorx`): -`hiddenimports` allein reicht nicht, da PyInstaller die `__init__.py` ins PYZ-Archiv packt, aber die `.pyd`-Extension separat im Dateisystem erwartet. Stattdessen `collect_all` verwenden: -```python -from PyInstaller.utils.hooks import collect_all -cx_datas, cx_binaries, cx_hiddenimports = collect_all('problematic_package') - -a = Analysis( - # ... - binaries=cx_binaries, - datas=cx_datas, - hiddenimports=cx_hiddenimports, -) -``` - -### Problem: UI-Dateien oder Ressourcen nicht gefunden - -**Lösung**: Prüfen ob datas korrekt konfiguriert. Ressource-Pfade müssen im Code PyInstaller-kompatibel aufgelöst werden (`sys._MEIPASS`): -```python -# In DocuMentor.spec: -datas=[ - ('src/ui/*.ui', 'ui'), - ('src/res/*', 'res'), -] - -# Im Code: -import sys -from pathlib import Path - -if hasattr(sys, "_MEIPASS"): - res_path = Path(sys._MEIPASS) / "res" / "data.sql" -else: - res_path = Path(__file__).parents[3] / "src" / "res" / "data.sql" -``` - -### Problem: Executable zu groß - -**Lösungen**: -1. UPX-Kompression aktivieren (bereits aktiv) -2. Excludes hinzufügen für ungenutzte Module: - ```python - excludes=['tkinter', 'matplotlib', 'test', 'unittest'] - ``` -3. One-File-Build verwenden (langsamer Start) - -### Problem: Antivirus blockiert - -**Lösung**: -- Code-Signing-Zertifikat verwenden -- Bei Microsoft einreichen für SmartScreen -- README mit Hinweis erweitern - -## Automatisierung mit CI/CD - -### GitHub Actions Beispiel - -```yaml -name: Build Windows Release - -on: - push: - tags: - - 'v*' - -jobs: - build: - runs-on: windows-latest - steps: - - uses: actions/checkout@v3 - - - name: Install uv - uses: astral-sh/setup-uv@v1 - - - name: Build - run: uv run python build_windows.py - - - name: Create Release - uses: softprops/action-gh-release@v1 - with: - files: dist/*.zip -``` - -## Versionierung - -Version in folgenden Dateien aktualisieren: -1. `pyproject.toml` - `version = "X.Y.Z"` -2. `installer.iss` - `#define MyAppVersion "X.Y.Z"` -3. Optional: `src/version.py` erstellen - -## Lizenz und Rechtliches - -- Alle Python-Dependencies sind in der Distribution enthalten -- PySide6 (LGPL): Dynamische Verlinkung ist OK -- Polars (MIT): Unproblematisch -- Pydantic (MIT): Unproblematisch - -Externe Tools (Saxon, FOP) haben eigene Lizenzen und müssen separat installiert werden.