From 4ea9c69c5f512bc7e0c48942bcb11e90b0f311ef Mon Sep 17 00:00:00 2001 From: Darian Miller Date: Mon, 16 Mar 2026 22:46:40 -0500 Subject: [PATCH] Add ability to set namespace For Ticket #4 All 76 tests pass --- CHANGELOG.md | 9 +++- README.md | 28 +++++++++++ source/delphi-dccbuild.ps1 | 12 +++++ tests/pwsh/delphi-dccbuild.Tests.ps1 | 74 ++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6cd76c..e6f2bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,14 @@ All notable changes to this project will be documented in this file. ## [0.3.0] - Unreleased -- Add support for passing compiler defines to DCC -[#2](https://github.com/continuous-delphi/delphi-dccbuild/issues/2) +- Add `-Namespace` parameter to specify unit scope names for unqualified unit + resolution via the `-NS` flag; required for modern Delphi projects using + namespaced RTL units (e.g. `System.SysUtils`, `Vcl.Forms`) when building + outside the IDE without a project `.cfg` file + [#4](https://github.com/continuous-delphi/delphi-dccbuild/issues/4) +- Add support for passing compiler defines to DCC + [#2](https://github.com/continuous-delphi/delphi-dccbuild/issues/2) ## [0.1.0] - 2026-03-16 diff --git a/README.md b/README.md index df5f337..ff4c1d1 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,34 @@ Example: -IncludePath @('C:\Inc\Headers') ``` +## -Namespace + +```text +-Namespace +``` + +Unit scope names (namespace prefixes) the compiler searches when resolving +unqualified unit names. Accepts an array of scope name strings. Multiple +names are joined with semicolons and passed as a single `-NS` argument: + +```text +-NSSystem;Vcl;Vcl.Imaging +``` + +This is important for modern Delphi (XE2+) projects that use namespaced RTL +units such as `System.SysUtils` or `Vcl.Forms`. When building outside the IDE +without the project's `.cfg` file, the compiler cannot resolve `uses Forms` +unless the `Vcl` scope is listed here. + +When omitted (or an empty array), no `-NS` argument is added. The result +object's `.namespace` is `$null` when no names are supplied. + +Example: + +```powershell +-Namespace @('System', 'Vcl', 'Vcl.Imaging', 'Data') +``` + ## -Define ```text diff --git a/source/delphi-dccbuild.ps1 b/source/delphi-dccbuild.ps1 index 445bd8a..c99729f 100644 --- a/source/delphi-dccbuild.ps1 +++ b/source/delphi-dccbuild.ps1 @@ -108,6 +108,12 @@ param( # joined with semicolons. [string[]]$IncludePath = @(), + # Unit scope names searched when resolving unqualified unit names (-NS flag). + # Multiple names are joined with semicolons and passed as a single -NS argument. + # Required for modern Delphi projects that use namespaced RTL units (e.g. System.SysUtils) + # when building outside the IDE without a project .cfg file. + [string[]]$Namespace = @(), + # Additional conditional defines (-D flag). Multiple defines are joined # with semicolons and passed as a single -D argument. [string[]]$Define = @(), @@ -262,6 +268,7 @@ function Invoke-DccProject { [string]$DcuOutputDir, [string[]]$UnitSearchPath = @(), [string[]]$IncludePath = @(), + [string[]]$Namespace = @(), [string[]]$Define = @(), [switch]$ShowOutput ) @@ -286,6 +293,9 @@ function Invoke-DccProject { if ($UnitSearchPath.Count -gt 0) { $dccArgs += "-U$($UnitSearchPath -join ';')" } if ($IncludePath.Count -gt 0) { $dccArgs += "-I$($IncludePath -join ';')" } + # Unit scope names: multiple entries joined with semicolons into a single -NS flag + if ($Namespace.Count -gt 0) { $dccArgs += "-NS$($Namespace -join ';')" } + # Additional defines: multiple entries joined with semicolons into a single -D flag if ($Define.Count -gt 0) { $dccArgs += "-D$($Define -join ';')" } @@ -343,6 +353,7 @@ try { -DcuOutputDir $DcuOutputDir ` -UnitSearchPath $UnitSearchPath ` -IncludePath $IncludePath ` + -Namespace $Namespace ` -Define $Define ` -ShowOutput:$ShowOutput @@ -359,6 +370,7 @@ try { dcuOutputDir = if ([string]::IsNullOrWhiteSpace($DcuOutputDir)) { $null } else { $DcuOutputDir } unitSearchPath = if ($UnitSearchPath.Count -eq 0) { $null } else { $UnitSearchPath } includePath = if ($IncludePath.Count -eq 0) { $null } else { $IncludePath } + namespace = if ($Namespace.Count -eq 0) { $null } else { $Namespace } exitCode = $buildResult.ExitCode success = ($buildResult.ExitCode -eq 0) output = $buildResult.Output diff --git a/tests/pwsh/delphi-dccbuild.Tests.ps1 b/tests/pwsh/delphi-dccbuild.Tests.ps1 index f37fc8a..fe1cee2 100644 --- a/tests/pwsh/delphi-dccbuild.Tests.ps1 +++ b/tests/pwsh/delphi-dccbuild.Tests.ps1 @@ -45,6 +45,9 @@ DcuOutputDir adds -N0 flag. UnitSearchPath single entry adds -U flag; multiple joined with semicolons. IncludePath single entry adds -I flag; multiple joined with semicolons. + Namespace single entry adds a -NS flag with that value. + Namespace multiple entries are joined with semicolons into a single -NS flag. + Namespace omitted adds no -NS argument. Define omitted adds no extra -D argument beyond the config define. Define single entry adds a -D flag with that value. Define multiple entries are joined with semicolons into a single -D flag. @@ -670,6 +673,77 @@ Describe 'Invoke-DccProject' { } + Context 'Namespace single entry adds a -NS flag with that value' { + + BeforeAll { + $script:capturedArgs = $null + Mock Invoke-DccExe { + $script:capturedArgs = $Arguments + return [pscustomobject]@{ ExitCode = 0; Output = '' } + } + + Invoke-DccProject ` + -CompilerPath 'C:\RAD\Studio\23.0\bin\dcc32.exe' ` + -ProjectFile 'C:\Projects\MyApp.dpr' ` + -Config 'Debug' ` + -Target 'Build' ` + -Verbosity 'normal' ` + -Namespace @('System') + } + + It 'includes -NSSystem' { + $script:capturedArgs | Should -Contain '-NSSystem' + } + + } + + Context 'Namespace multiple entries are joined with semicolons into a single -NS flag' { + + BeforeAll { + $script:capturedArgs = $null + Mock Invoke-DccExe { + $script:capturedArgs = $Arguments + return [pscustomobject]@{ ExitCode = 0; Output = '' } + } + + Invoke-DccProject ` + -CompilerPath 'C:\RAD\Studio\23.0\bin\dcc32.exe' ` + -ProjectFile 'C:\Projects\MyApp.dpr' ` + -Config 'Debug' ` + -Target 'Build' ` + -Verbosity 'normal' ` + -Namespace @('System', 'Vcl', 'Vcl.Imaging') + } + + It 'includes -NSSystem;Vcl;Vcl.Imaging as a single argument' { + $script:capturedArgs | Should -Contain '-NSSystem;Vcl;Vcl.Imaging' + } + + } + + Context 'Namespace omitted adds no -NS argument' { + + BeforeAll { + $script:capturedArgs = $null + Mock Invoke-DccExe { + $script:capturedArgs = $Arguments + return [pscustomobject]@{ ExitCode = 0; Output = '' } + } + + Invoke-DccProject ` + -CompilerPath 'C:\RAD\Studio\23.0\bin\dcc32.exe' ` + -ProjectFile 'C:\Projects\MyApp.dpr' ` + -Config 'Debug' ` + -Target 'Build' ` + -Verbosity 'normal' + } + + It 'no argument starts with -NS' { + ($script:capturedArgs | Where-Object { $_ -like '-NS*' }) | Should -BeNullOrEmpty + } + + } + Context 'Define omitted adds no extra -D argument beyond the config define' { BeforeAll {