Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,13 +1 @@
# Ignore release artifacts and local build outputs
release-assets/

# macOS
.DS_Store

# VSCode workspace cache (keep recommended config files under version control)
.vscode/*
!.vscode/settings.json
!.vscode/extensions.json
!.vscode/tasks.json
!.vscode/launch.json

test/
87 changes: 87 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repository Purpose

This is a **documentation and tooling standards repository** for Delphi development — not a Delphi application itself. It contains:

- Style guides in English and German (`Delphi Style Guide EN.md` / `Delphi Style Guide DE.md`)
- Git templates (`Delphi GitIgnore.txt`, `Delphi GitAttributes.txt`)
- A universal Delphi build script for CI/CD use (`DelphiBuildDPROJ.ps1`)
- A WSL bridge to that script (`DelphiBuildDPROJ.sh`)
- Release tooling that converts Markdown guides to PDFs (`release-tools/`)

## Build Scripts

### Windows (PowerShell) — `DelphiBuildDPROJ.ps1`

```powershell
# Auto-detects latest Delphi from Windows Registry, builds Debug/Win32
.\DelphiBuildDPROJ.ps1 -ProjectFile "MyProject.dproj"

# Release build for Win64
.\DelphiBuildDPROJ.ps1 -ProjectFile "MyProject.dproj" -Config Release -Platform Win64

# Linux64 with full debug symbols and map file
.\DelphiBuildDPROJ.ps1 -ProjectFile "MyProject.dproj" -Platform Linux64 -LinuxMap
```

The script loads the Delphi environment by executing `rsvars.bat` from the detected installation path and then invokes MSBuild. Auto-detection reads `HKLM:\SOFTWARE\Embarcadero\BDS` (and the Wow6432Node variant).

### WSL — `DelphiBuildDPROJ.sh`

```bash
# Basic build (defaults: Debug / Win32)
./DelphiBuildDPROJ.sh -ProjectFile ./test/Project38.dproj

# Release build for Win64
./DelphiBuildDPROJ.sh -ProjectFile "./MyProject.dproj" -Config Release -Platform Win64

# Linux64 with debug symbols and map file
./DelphiBuildDPROJ.sh -ProjectFile "./MyProject.dproj" -Platform Linux64 -LinuxMap
```

This is a pure bridge: it converts WSL paths to Windows UNC paths via `wslpath -w` and delegates to `DelphiBuildDPROJ.ps1` via `powershell.exe -Command "& 'unc-path'"`. Requires WSL with `powershell.exe` accessible on the host and Delphi installed on Windows.

Parameters are identical to `DelphiBuildDPROJ.ps1` (minus `-IsWSL`, which is internal and no longer exists). Defaults (Debug / Win32) are applied by the PS1.

## Release Process

Releases bundle PDFs of the style guides with the git templates. Requires `pandoc` and `xelatex`.

```bash
# From project root
./release-tools/create-release.sh
```

Before running: update the version in `release-tools/release-config.yaml` and update the version/date header in both style guide files. After running, create a git tag (`git tag -a vX.Y.Z -m "..."`) and push.

## Bilingual Maintenance Rule

The style guide exists in both German and English. **Both files must be kept in sync.** Single-language PRs are acceptable — the maintainer handles the other language post-merge — but if you are editing one, note which language was updated so the gap is visible.

## Delphi Style Guide Conventions (Summary)

When editing the style guides, preserve these conventions (they are the content being documented):

| Element | Convention |
| ------------------- | ------------------------------------------------ |
| Local variables | `L` prefix — `LCustomer: TCustomer` |
| Parameters | `A` prefix — `const AValue: string` |
| Fields | `F` prefix — `FName: string` |
| Record fields | **No** `F` prefix (records differ from classes) |
| Loop counters | Lowercase, no prefix — `for var i := 0 to 10 do` |
| Classes / Records | `T` prefix |
| Interfaces | `I` prefix |
| Technical constants | `c` prefix — `cMaxRetries = 3` |
| String constants | `sc` prefix — `scErrorMessage = 'Error'` |

Other key rules documented in the guide:

- 2-space indentation, 120-char line limit
- `begin..end` always on separate lines
- `FreeAndNil(LObj)` instead of `LObj.Free`
- Inline variables (Delphi 10.3+), multiline strings (Delphi 12+)
- `TArray<T>` for fixed-size, `TList<T>` for dynamic, `TObjectList<T>` for owned objects
- Unit names follow namespace hierarchy: `Main.Form`, `Customer.Details.DM`
37 changes: 30 additions & 7 deletions DelphiBuildDPROJ.ps1
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# =============================================================================
# DelphiBuildDPROJ.ps1 - Universal Delphi Project Builder
# =============================================================================
# Copyright (c) 2025 Olaf Monien - The MIT License (MIT)
# https://github.com/omonien/DelphiStandards
# =============================================================================
# Builds any Delphi project file (.dproj) with MSBuild
# Can be used in any Delphi project - no dependencies to specific projects
#
Expand Down Expand Up @@ -33,9 +36,14 @@ param(
[string]$Config = "",
[string]$Platform = "",
[string]$DelphiVersion = "",
[switch]$VerboseOutput
[switch]$VerboseOutput,
[switch]$LinuxMap
)

Write-Host "============================================="
Write-Host "| Universal Delphi Project Builder - v1.1 |"
Write-Host "============================================="

# =============================================================================
# CONFIGURATION - Edit these defaults as needed
# =============================================================================
Expand Down Expand Up @@ -188,16 +196,19 @@ function Build-DPROJProject {
[string]$Config,
[string]$Platform,
[string]$MSBuild,
[bool]$VerboseOutput
[bool]$VerboseOutput,
[bool]$LinuxMap
)

if (-not (Test-Path $ProjectFile)) {
if (-not (Test-Path -LiteralPath $ProjectFile)) {
Write-Err "Project file not found: $ProjectFile"
exit 1
}

$ProjectPath = Resolve-Path $ProjectFile
$ProjectName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectFile)
$ProjectItem = Get-Item -LiteralPath $ProjectFile
$ProjectPath = $ProjectItem.FullName

$ProjectName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectPath)

Write-Warn "Building: $ProjectName"
Write-Detail " File: $ProjectPath"
Expand All @@ -209,7 +220,19 @@ function Build-DPROJProject {
$ProjectPath,
"/t:Build",
"/p:Config=$Config",
"/p:Platform=$Platform",
"/p:Platform=$Platform"
)

if ($LinuxMap) {
$MSBuildArgs += "/p:DCC_MapFile=3"
$MSBuildArgs += "/p:DCC_DebugInfo=3"
$MSBuildArgs += "/p:DCC_LocalSymbols=true"
$MSBuildArgs += "/p:DCC_LocalDebugSymbols=true"
$MSBuildArgs += "/p:DCC_DebugInformation=2"
$MSBuildArgs += "/p:DCC_DebugInfoInExe=false"
}

$MSBuildArgs += @(
"/nologo",
"/m"
)
Expand Down Expand Up @@ -284,7 +307,7 @@ try {
Write-Host ""

# Build the project
$BuildSuccess = Build-DPROJProject -ProjectFile $ProjectFile -Config $Config -Platform $Platform -MSBuild $MSBuild -VerboseOutput $VerboseOutput
$BuildSuccess = Build-DPROJProject -ProjectFile $ProjectFile -Config $Config -Platform $Platform -MSBuild $MSBuild -VerboseOutput $VerboseOutput -LinuxMap $LinuxMap

# Normalize boolean result
$BuildResult = ($BuildSuccess -eq $true)
Expand Down
160 changes: 160 additions & 0 deletions DelphiBuildDPROJ.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#!/bin/bash

# =============================================================================
# DelphiBuildDPROJ.sh - Universal Delphi Project Builder for WSL
# =============================================================================
# Copyright (c) 2025 Olaf Monien - The MIT License (MIT)
# https://github.com/omonien/DelphiStandards
# =============================================================================
# Bridges WSL to the Windows Delphi environment via PowerShell.
# This script wraps DelphiBuildDPROJ.ps1 for use within WSL.
# =============================================================================

# Colors for output
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PS_SCRIPT_PATH="${SCRIPT_DIR}/DelphiBuildDPROJ.ps1"

function show_usage() {
echo -e "${CYAN}Usage:${NC}"
echo " $0 -ProjectFile <path_to_dproj> [options]"
echo ""
echo -e "${CYAN}Options:${NC}"
echo " -Config <name> Build configuration (default: Debug)"
echo " -Platform <name> Target platform (default: Win32)"
echo " -DelphiVersion <ver> Specific Delphi version (e.g., 22.0)"
echo " -VerboseOutput Enable verbose MSBuild output"
echo " -LinuxMap Enable Linux debug symbols and map file"
echo " -h, --help Show this help message"
echo ""
echo -e "${CYAN}Example:${NC}"
echo " $0 -ProjectFile ./MyProject.dproj -Config Release -Platform Win64"
}

# 1. WSL Check
if ! grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
echo -e "${RED}Error: This script must be run from within WSL (Windows Subsystem for Linux).${NC}"
exit 1
fi

# 2. Check for powershell.exe
if ! command -v powershell.exe &> /dev/null; then
echo -e "${RED}Error: powershell.exe not found in PATH.${NC}"
echo "Ensure Windows PowerShell is accessible from your WSL environment."
exit 1
fi

# 3. Check for Delphi installation on the Windows host
# We perform a quick registry check for Embarcadero BDS keys
DELPHI_REG_CHECK=$(powershell.exe -NoProfile -Command "Get-Item -Path 'HKLM:\SOFTWARE\Embarcadero\BDS', 'HKLM:\SOFTWARE\WOW6432Node\Embarcadero\BDS' -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count" 2>/dev/null | tr -d '\r\n')

if [[ -z "$DELPHI_REG_CHECK" || "$DELPHI_REG_CHECK" -eq "0" ]]; then
echo -e "${RED}Error: Delphi installation not detected on the Windows host.${NC}"
echo "This script requires Embarcadero Delphi to be installed on Windows."
exit 1
fi

# 4. Check if the PowerShell script exists
if [[ ! -f "$PS_SCRIPT_PATH" ]]; then
echo -e "${RED}Error: Companion script not found: ${PS_SCRIPT_PATH}${NC}"
exit 1
fi

# 5. Parse Arguments
PROJECT_FILE=""
CONFIG=""
PLATFORM=""
DELPHI_VERSION=""
VERBOSE=false
LINUX_MAP=false

while [[ $# -gt 0 ]]; do
case $1 in
-ProjectFile)
PROJECT_FILE="$2"
shift 2
;;
-Config)
CONFIG="$2"
shift 2
;;
-Platform)
PLATFORM="$2"
shift 2
;;
-DelphiVersion)
DELPHI_VERSION="$2"
shift 2
;;
-VerboseOutput)
VERBOSE=true
shift
;;
-LinuxMap)
LINUX_MAP=true
shift
;;
-h|--help)
show_usage
exit 0
;;
*)
echo -e "${RED}Unknown argument: $1${NC}"
show_usage
exit 1
;;
esac
done

if [[ -z "$PROJECT_FILE" ]]; then
echo -e "${RED}Error: -ProjectFile is mandatory.${NC}"
show_usage
exit 1
fi

# 6. Convert Paths
# Check if project file exists in WSL
if [[ ! -f "$PROJECT_FILE" ]]; then
echo -e "${RED}Error: Project file not found at: ${PROJECT_FILE}${NC}"
exit 1
fi

# Convert WSL path to Windows path for the PowerShell script
WIN_PROJECT_FILE=$(wslpath -w "$PROJECT_FILE")
WIN_PS_SCRIPT_PATH=$(wslpath -w "$PS_SCRIPT_PATH")

# 7. Construct and Run PowerShell command
# We use an array to handle arguments safely and avoid literal quote issues
# -InputFormat None prevents PowerShell from trying to read from stdin, which can cause hangs
PS_CMD_ARGS=("-NoProfile" "-NonInteractive" "-InputFormat" "None" "-ExecutionPolicy" "Bypass")

# Using -Command with & is more robust for UNC paths from WSL than -File
# We wrap the call in a try/catch in PowerShell to ensure we see errors if initialization fails
COMMAND="try { & '$WIN_PS_SCRIPT_PATH' -ProjectFile '$WIN_PROJECT_FILE'"

[[ -n "$CONFIG" ]] && COMMAND="$COMMAND -Config '$CONFIG'"
[[ -n "$PLATFORM" ]] && COMMAND="$COMMAND -Platform '$PLATFORM'"
[[ -n "$DELPHI_VERSION" ]] && COMMAND="$COMMAND -DelphiVersion '$DELPHI_VERSION'"
[[ "$VERBOSE" = true ]] && COMMAND="$COMMAND -VerboseOutput"
[[ "$LINUX_MAP" = true ]] && COMMAND="$COMMAND -LinuxMap"

COMMAND="$COMMAND } catch { Write-Error \$_.Exception.Message; exit 1 }"

echo -e "${CYAN}Bridging build to Windows host...${NC}"
# Note: we use -Command because it handles UNC paths better than -File in some PS versions
powershell.exe "${PS_CMD_ARGS[@]}" -Command "$COMMAND"
EXIT_CODE=$?

if [[ $EXIT_CODE -eq 0 ]]; then
echo -e "${GREEN}WSL Bridge: Build finished successfully.${NC}"
else
echo -e "${RED}WSL Bridge: Build failed with exit code $EXIT_CODE.${NC}"
fi

exit $EXIT_CODE
Loading
Loading