Build-Pipeline

Build-Prozess für die WvdS FPC VSCode Extensions (Solution Manager, PAS2JS Studio, ISS Designer).

Übersicht

┌─────────────────────────────────────────────────────────────┐
│                      BUILD PIPELINE                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. COMPILE (pas2js)                                        │
│     ├── Unit Resolution (-Fu Pfade)                         │
│     ├── Pascal → JavaScript Transpilation                   │
│     └── Source Map Generierung + Repair                     │
│                                                             │
│  2. BUNDLE (esbuild)                                        │
│     ├── npm Dependencies inlinen (@xmldom/xmldom)           │
│     ├── Node.js Builtins externalisieren                    │
│     └── Minification (nur Release)                          │
│                                                             │
│  3. DEPLOY (manuell oder VSIX)                              │
│     ├── Copy dist/extension.js → ~/.vscode/extensions/      │
│     └── Oder: vsce package → .vsix                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Build-Scripts

Jede Extension hat ein eigenes build.ps1, orchestriert durch ci-build.ps1:

vsce/
├── ci-build.ps1                          ← CI-Orchestrator
├── wvds-fpc-solution-manager/
│   └── build.ps1                         ← SM Build
├── wvds-fpc-pas2js-studio/
│   └── build.ps1                         ← PAS2JS Build
├── wvds-fpc-iss-designer/
│   └── build.ps1                         ← ISS Build
└── wvds-fpc-tools/
    └── package.json                      ← Extension Pack (kein Build)

Phase 1: Kompilierung (pas2js)

Compiler-Aufruf

# Debug-Build
pas2js -Tnodejs -Jm -Jminclude -O1 -vd -Fu<paths> -o dist\extension.pas2js.js src-pas\extension.pas
 
# Release-Build
pas2js -Tnodejs -O2 -Fu<paths> -o dist\extension.pas2js.js src-pas\extension.pas

Compiler-Flags

Flag Beschreibung
-Tnodejs Target: Node.js (CommonJS Module)
-Jm Source Maps generieren
-Jminclude Pascal-Quellen in Source Map einbetten
-O1 Debug: minimale Optimierung
-O2 Release: volle Optimierung
-vd Debug: Verbose-Ausgabe
-Fu<path> Unit-Suchpfad hinzufügen
-o<file> Ausgabedatei

Verbotene Flags:

  • -Jl (Lowercase Identifiers): Bricht asm-Blöcke, die PascalCase-Parameter referenzieren (ModuleName, Value, VSCodeMod).
  • terser --mangle: Renamed Parameter, aber NICHT in asm-Blöcken → ReferenceError.

Unit-Suchpfade

Die Funktion Get-UnitPaths in build.ps1 definiert alle Suchpfade:

Kategorie Pfad (relativ zum Extension-Root) Beschreibung
pas2js Bindings ../../pas2js/NodeJS Node.js API Wrapper
../../pas2js/VSCode VSCode Extension API
../../pas2js/Browser Browser/DOM API
../../pas2js/Components/Runtime Runtime Renderer
../../pas2js/Components/Designer Design-Time Renderer
../../pas2js/Components/GUI/* GUI-Komponenten (30+ Ordner)
fpc-core ../../fpc-core/core Models, Parser
../../fpc-core/services Platform, WebView, Logger
../../fpc-core/utils Constants, Interop
../../fpc-core/build Build-System Logik
Extension-lokal src-pas/tree Tree View Provider
src-pas/services Extension-spezifische Services
src-pas/editor WebView Panels
src-pas/build Build-Logik
src-pas/debug Debug-Adapter
src-pas/tests Unit-Tests

Source Map Repair

pas2js hat einen Bug: Source-Map-Dateien enthalten manchmal Garbage-Bytes vor dem JSON. Repair-SourceMap entfernt alles vor dem ersten { Zeichen.

Phase 2: Bundling (esbuild)

Nach der pas2js-Kompilierung bündelt esbuild die npm-Dependencies:

pas2js → extension.pas2js.js → esbuild → extension.js

esbuild-Konfiguration

esbuild extension.pas2js.js `
  --bundle `
  --platform=node `         # Node.js Builtins (fs, path, ...) externalisieren
  --format=cjs `            # CommonJS für VSCode Extension Host
  --external:vscode `       # VSCode API als externen require belassen
  --target=node18 `         # Minimale Node.js Version
  --outfile=extension.js
  # Debug: --sourcemap=external
  # Release: --minify

Warum esbuild?

  • npm-Dependencies (z.B. @xmldom/xmldom) werden in eine Datei gebundelt
  • Kein node_modules im deployed Extension nötig
  • --minify ist safe für pas2js asm-Blöcke (anders als terser)
  • Schnell: ~50ms für das gesamte Bundle

Build-Output

dist/
├── extension.pas2js.js       # Intermediate (pas2js Output)
├── extension.pas2js.js.map   # Source Map (Debug)
├── extension.js              # Final Bundle (esbuild Output)
└── extension.js.map          # Bundled Source Map (Debug)

Phase 3: Deploy

Lokales Deployment (Entwicklung)

# Manuell: dist/extension.js in die installierte Extension kopieren
$extDir = "$env:USERPROFILE\.vscode\extensions\wvds.wvds-fpc-solution-manager-0.1.0"
Copy-Item dist\extension.js "$extDir\dist\extension.js"
Copy-Item dist\extension.js.map "$extDir\dist\extension.js.map"
 
# Dann: VSCode → Developer: Reload Window (Ctrl+Shift+P)

VSIX-Paketierung

# Einzelne Extension
.\build.ps1 -Vsix
 
# Ergebnis: D:\Workspace\binaries\{extension}\vscode\{Release|Debug}\*.vsix

CI-Orchestrator (ci-build.ps1)

ci-build.ps1 baut alle drei Extensions in einem Durchlauf:

Parameter

Parameter Beschreibung
-Debug Debug-Builds für alle Extensions
-Release Release-Builds für alle Extensions
-Test Unit-Tests ausführen
-Vsix VSIX-Pakete erstellen
-Archive VSIX in Nightly-Archiv kopieren
-Nightly Alias für -Debug -Release -Test -Vsix -Archive
-Extension sm/pas2js/iss Nur bestimmte Extension bauen
-KeepDays 30 Nightly-Archive älter als N Tage löschen

Ausführung

# Typischer Entwickler-Build
powershell -ExecutionPolicy Bypass -File ci-build.ps1 -Debug
 
# Vollständige Nightly-Pipeline
powershell -ExecutionPolicy Bypass -File ci-build.ps1 -Nightly
 
# Nur PAS2JS Studio Release + VSIX
powershell -ExecutionPolicy Bypass -File ci-build.ps1 -Release -Vsix -Extension pas2js

Pipeline-Ablauf

Für jede Extension (SM → PAS2JS → ISS):
  1. Prüfen ob build.ps1 existiert
  2. Debug-Build ausführen (wenn -Debug)
  3. Release-Build ausführen (wenn -Release)
  4. Tests ausführen (wenn -Test und HasTest)
  5. VSIX paketieren (wenn -Vsix)

Danach (wenn -Archive):
  6. VSIX in D:\Workspace\binaries\nightly\{yyyy-MM-dd}\ kopieren
  7. Archive älter als KeepDays Tage löschen

Abschluss:
  8. Summary mit OK/FAIL pro Extension + Gesamtzeit

Beispiel-Output

================================================
  WvdS FPC Tools - CI Build Pipeline
  2026-02-28 21:30:04
================================================
[21:30:04] Pipeline: Debug
[21:30:04] Extensions: ALL

--- Solution Manager ---
[21:30:04] Building Solution Manager [Debug]...
...
[21:30:06] Solution Manager completed in 2.1s

--- PAS2JS Studio ---
...

--- ISS Designer ---
...

================================================
  CI Summary
================================================
  Solution Manager: Debug:OK
  PAS2JS Studio: Debug:OK
  ISS Designer: Debug:OK

  Total: 5.9s
================================================
  PIPELINE SUCCESSFUL

Build-Modi

Modus Flag Optimierung Source Maps Minification
Debug build.ps1 -Debug -O1 Ja (eingebettet) Nein
Release build.ps1 -O2 Nein Ja (esbuild)
Test build.ps1 -Test -O1 Ja Nein

Watch-Mode

Für die Entwicklung: automatisches Neukompilieren bei Änderungen:

.\build.ps1 -Watch -Debug

Überwacht src-pas\\*.pas via FileSystemWatcher mit Debounce. ===== Qualitätsanforderungen =====

Null-Toleranz-Policy: Jeder Build MUSS mit zero errors, zero warnings, zero hints abschließen. Keine {$WARNINGS OFF} oder {$HINTS OFF} Direktiven erlaubt.

===== Fehlerbehebung ===== ==== „Unit not found“ ==== * -Fu Pfad in Get-UnitPaths prüfen * Neues Unterverzeichnis in localDirs Array aufnehmen * pas2js.cfg prüfen (RTL-Pfade) ==== „identifier not found“ in asm Block ==== * -Jl Flag entfernen (lowercased PascalCase-Bezeichner) * end Keyword → Bracket-Notation: r[„end“].line * Regex-Literale → new RegExp('pattern', 'flags') * this in Interface-Prozeduren = $mod, Implementation-Vars auf $impl ==== esbuild Bundling-Fehler ==== * require() muss statisch analysierbar sein (kein dynamischer String) * --external:vscode sicherstellen * --platform=node externalisiert Node.js Builtins automatisch ==== Source Map zeigt falschen Code ==== * Prüfen ob Repair-SourceMap lief (Garbage-Bytes) * -Jminclude für eingebettete Quellen nutzen ===== Dateien ===== | Datei | Beschreibung | ^ vsce/ci-build.ps1 | CI-Orchestrator für alle Extensions | ^ vsce/{extension}/build.ps1 | Extension-spezifisches Build-Script | ^ dist/extension.pas2js.js | Intermediate pas2js Output | ^ dist/extension.js | Final esbuild Bundle | ^ dist/extension.js.map'' | Source Map (nur Debug) | ===== Siehe auch ===== * Build-Targets * Release-Prozess * Testing * Entwicklungsumgebung

Zuletzt geändert: den 28.02.2026 um 21:15