Skip to content

Commit ca2cf93

Browse files
committed
Release v2.1.0: Merge branch 'master' into release
2 parents 83187a2 + fe8a900 commit ca2cf93

File tree

7 files changed

+137
-36
lines changed

7 files changed

+137
-36
lines changed

src/Compile-SourceScript/Public/Compile-SourceScript.ps1

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ function Compile-SourceScript {
6161

6262
# Initialize variables
6363
$MOD = @{
64+
# The sourcemod compiler returns exits code correctly.
65+
# The sourcemod compiler wrapper returns the exit code of the lastmost executed shell statement. This is particularly bad when the compiler exits with '0' from a successful finalmost shell statement, even when one or more prior shell statements exited with non-zero exit codes.
66+
# Hence, knowing that exit codes are not a reliable way to determine whether one or more compilation statements failed, we are going to use a regex on the stdout as a more reliable way to detect compilation errors, regardless of whether compilation was performed via the compiler binary or via the compiler wrapper.
6467
sourcemod = @{
6568
script_ext = '.sp'
6669
plugin_ext = '.smx'
@@ -70,13 +73,18 @@ function Compile-SourceScript {
7073
windows = @{
7174
wrapper = 'compile.exe'
7275
bin = 'spcomp.exe'
76+
error_regex = '^Compilation aborted|^\d+\s+Errors?|.*\.sp\(\d+\)\s*:\s*(?:fatal)? error (\d+)'
7377
}
7478
others = @{
7579
wrapper = 'compile.sh'
7680
bin = 'spcomp'
81+
error_regex = '^Compilation aborted|^\d+\s+Errors?|.*\.sp\(\d+\)\s*:\s*(?:fatal)? error (\d+)'
7782
}
7883
}
7984
}
85+
# The amxmodx compiler binary always exits with exit code 0.
86+
# The amxmodx compiler wrapper always exits with exit code 0.
87+
# Hence, knowing that exit codes are not a reliable way to determine whether one or more compilation statements failed, we are going to use a regex on the stdout as a more reliable way to detect compilation errors, regardless of whether compilation was performed via the compiler binary or via the compiler wrapper.
8088
amxmodx = @{
8189
script_ext = '.sma'
8290
plugin_ext = '.amxx'
@@ -86,21 +94,18 @@ function Compile-SourceScript {
8694
windows = @{
8795
wrapper = 'compile.exe'
8896
bin = 'amxxpc.exe'
97+
error_regex = '^\d+\s+Errors?|compile failed|^.*\.sma\(\d+\)\s*:\s*error (\d+)'
8998
}
9099
others = @{
91100
wrapper = 'compile.sh'
92101
bin = 'amxxpc'
102+
error_regex = '^\d+\s+Errors?|compile failed|^.*\.sma\(\d+\)\s*:\s*error (\d+)'
93103
}
94104
}
95105
}
96106
}
97-
$COMPILER_NAME = if ($env:OS -eq 'Windows_NT') {
98-
if ($PSBoundParameters['SkipWrapper']) { $MOD[$MOD_NAME]['compiler']['windows']['bin'] }
99-
else { $MOD[$MOD_NAME]['compiler']['windows']['wrapper'] }
100-
}else {
101-
if ($PSBoundParameters['SkipWrapper']) { $MOD[$MOD_NAME]['compiler']['others']['bin'] }
102-
else { $MOD[$MOD_NAME]['compiler']['others']['wrapper'] }
103-
}
107+
$OS = if ($env:OS -eq 'Windows_NT') { 'windows' } else { 'others' }
108+
$COMPILER_NAME = if ($PSBoundParameters['SkipWrapper']) { $MOD[$MOD_NAME]['compiler'][$OS]['bin'] } else { $MOD[$MOD_NAME]['compiler'][$OS]['wrapper'] }
104109
$SCRIPTING_DIR = $sourceFile.DirectoryName
105110
$COMPILED_DIR = Join-Path $SCRIPTING_DIR $MOD[$MOD_NAME]['compiled_dir_name']
106111
$COMPILER_PATH = Join-Path $SCRIPTING_DIR $COMPILER_NAME
@@ -123,33 +128,65 @@ function Compile-SourceScript {
123128
# Get all items in compiled directory before compilation by hash
124129
$compiledDirItemsPre = Get-ChildItem -Path $COMPILED_DIR -File -Recurse -Force | ? { $_.Extension -eq $MOD[$MOD_NAME]['plugin_ext'] } | Select-Object *, @{name='md5'; expression={(Get-FileHash -Path $_.Fullname -Algorithm MD5).Hash}}
125130

126-
# Prepare for compilation
127-
"Compiling..." | Write-Host -ForegroundColor Cyan
131+
# Generate command line arguments
128132
$epoch = [Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s"))
129-
$stdInFile = New-Item -Path (Join-Path $SCRIPTING_DIR ".$epoch") -ItemType File -Force
130-
'1' | Out-File -FilePath $stdInFile.FullName -Force -Encoding utf8
133+
$stdInFile = Join-Path $SCRIPTING_DIR ".$epoch"
134+
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) (New-Guid).Guid
135+
$stdoutFile = Join-Path $tempDir 'stdout'
136+
$stderrFile = Join-Path $tempDir 'stderr'
131137
$processArgs = @{
132138
FilePath = $compiler.FullName
139+
ArgumentList = @(
140+
if ($PSBoundParameters['SkipWrapper']) {
141+
$sourceFile.Name
142+
"-o$($MOD[$MOD_NAME]['compiled_dir_name'])/$($sourceFile.Basename)$($MOD[$MOD_NAME]['plugin_ext'])"
143+
}else {
144+
$sourceFile.Name
145+
}
146+
)
133147
WorkingDirectory = $SCRIPTING_DIR
134-
RedirectStandardInput = $stdInFile.FullName
148+
RedirectStandardInput = $stdInFile
149+
RedirectStandardOutput = $stdoutFile
150+
RedirectStandardError = $stderrFile
135151
Wait = $true
136152
NoNewWindow = $true
153+
PassThru = $true
137154
}
138-
if ($PSBoundParameters['SkipWrapper']) {
139-
$processArgs['ArgumentList'] = @(
140-
$sourceFile.Name
141-
"-o$($MOD[$MOD_NAME]['compiled_dir_name'])/$($sourceFile.Basename)$($MOD[$MOD_NAME]['plugin_ext'])"
142-
)
143-
}else {
144-
$processArgs['ArgumentList'] = @(
145-
$sourceFile.Name
146-
)
155+
156+
try {
157+
# Prepare compilation environment
158+
if ($item = New-Item -Path $stdInFile -ItemType File -Force) {
159+
# This dummy input bypasses the 'Press any key to continue' prompt of the compiler
160+
'1' | Out-File -FilePath $item.FullName -Force -Encoding utf8
161+
}
162+
New-Item $tempDir -ItemType Directory -Force > $null
163+
New-Item -Path $COMPILED_DIR -ItemType Directory -Force | Out-Null
164+
165+
# Begin compilation
166+
"Compiling..." | Write-Host -ForegroundColor Cyan
167+
if ($PSBoundParameters['SkipWrapper']) { "Compiling $($sourceFile.Name)..." | Write-Host -ForegroundColor Yellow }
168+
169+
# Compile
170+
$global:LASTEXITCODE = 0
171+
$p = Start-Process @processArgs
172+
$stdout = Get-Content $stdoutFile
173+
$stdout | Write-Host
174+
$stderr = Get-Content $stderrFile
175+
$stderr | Write-Host
176+
foreach ($line in $stdout) {
177+
if ($line -match $MOD[$MOD_NAME]['compiler'][$OS]['error_regex']) {
178+
$global:LASTEXITCODE = 1
179+
break
180+
}
181+
}
182+
}catch {
183+
throw
184+
}finally {
185+
# Cleanup
186+
Remove-Item $stdInFile -Force
187+
Remove-Item $tempDir -Recurse -Force
147188
}
148-
New-Item -Path $COMPILED_DIR -ItemType Directory -Force | Out-Null
149189

150-
# Begin compilation
151-
if ($PSBoundParameters['SkipWrapper']) { "Compiling $($sourceFile.Name)..." | Write-Host -ForegroundColor Yellow }
152-
Start-Process @processArgs
153190
if ($PSBoundParameters['SkipWrapper']) { "End of compilation." | Write-Host -ForegroundColor Yellow }
154191

155192
# Get all items in compiled directory after compilation by hash
@@ -231,10 +268,6 @@ function Compile-SourceScript {
231268
}catch {
232269
Write-Error -Exception $_.Exception -Message $_.Exception.Message -Category $_.CategoryInfo.Category -TargetObject $_.TargetObject
233270
}finally {
234-
# Cleanup
235-
if ($stdInFile) {
236-
Remove-Item -Path $stdInFile -Force
237-
}
238271
"End of Compile-SourceScript." | Write-Host -ForegroundColor Cyan
239272
}
240273
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <amxmodx>
2+
3+
public plugin_init() {
4+
log_message("Hello from amxmodx.");
5+
}
6+
i am junk
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <amxmodx>
2+
3+
public plugin_init() {
4+
log_message("Hello from amxmodx.");
5+
}
6+
i am junk
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <sourcemod>
2+
3+
public void OnPluginStart() {
4+
LogMessage("Hello from sourcemod.");
5+
}
6+
i am junk
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <sourcemod>
2+
3+
public void OnPluginStart() {
4+
LogMessage("Hello from sourcemod.");
5+
}
6+
i am junk

test/scripts/dep/Install-TestDependencies.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ try {
99
# Install Pester if needed
1010
"Checking Pester version" | Write-Host
1111
$pesterMinimumVersion = [version]'4.0.0'
12+
$pesterMaximumVersion = [version]'4.10.1'
1213
$pester = Get-Module 'Pester' -ListAvailable -ErrorAction SilentlyContinue
13-
if (!$pester -or !($pester.Version -gt $pesterMinimumVersion)) {
14+
if (!$pester -or !($pester | ? { $_.Version -ge $pesterMinimumVersion -and $_.Version -le $pesterMaximumVersion })) {
1415
"Installing Pester" | Write-Host
15-
Install-Module -Name 'Pester' -Repository 'PSGallery' -MinimumVersion $pesterMinimumVersion -Scope CurrentUser -Force
16+
Install-Module -Name 'Pester' -Repository 'PSGallery' -MinimumVersion $pesterMinimumVersion -MaximumVersion $pesterMaximumVersion -Scope CurrentUser -Force
1617
}
17-
Get-Module Pester -ListAvailable
18+
Get-Module Pester -ListAvailable | Out-String | Write-Verbose
1819

1920
if ($env:OS -ne 'Windows_NT') {
2021
if ($IsLinux) {

test/scripts/integration/Run-IntegrationTests.ps1

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ $functionTestScriptBlock = {
1414
for ($i=0; $i -le $iterations-1; $i++) {
1515
"Iteration: $($i+1)" | Write-Host
1616
& $script:cmd @cmdArgs
17+
if ($global:LASTEXITCODE -ne $expectedExitCode) {
18+
throw "Expected exit code $expectedExitCode but got exit code $global:LASTEXITCODE"
19+
}
20+
"Expected exit code: $expectedExitCode, Exit code: $global:LASTEXITCODE" | Write-Host -ForegroundColor Yellow
1721
}
1822
}catch {
1923
$_ | Write-Error
@@ -28,30 +32,49 @@ $cmd = "Compile-SourceScript"
2832
# SourceMod #
2933
#############
3034

31-
"`n[sourcemod] Compile plugin via wrapper" | Write-Host
35+
"`n[sourcemod] Compile plugin via wrapper, good plugin" | Write-Host
3236
$cmdArgs = @{
3337
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin1.sp"
3438
Force = $true
3539
}
3640
$iterations = 2
41+
$expectedExitCode = 0
3742
& $functionTestScriptBlock
3843

44+
"`n[sourcemod] Compile plugin via wrapper, bad plugin" | Write-Host
45+
$cmdArgs = @{
46+
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin1_bad.sp"
47+
Force = $true
48+
}
49+
$iterations = 2
50+
$expectedExitCode = 1
51+
& $functionTestScriptBlock
3952

40-
"`n[sourcemod] Compile plugin via compiler" | Write-Host
53+
"`n[sourcemod] Compile plugin via compiler, good plugin" | Write-Host
4154
$cmdArgs = @{
4255
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin2.sp"
4356
Force = $true
4457
SkipWrapper = $true
4558
}
4659
$iterations = 2
60+
$expectedExitCode = 0
4761
& $functionTestScriptBlock
4862

63+
"`n[sourcemod] Compile plugin via compiler, bad plugin" | Write-Host
64+
$cmdArgs = @{
65+
File = "$PSScriptRoot\..\..\mod\sourcemod\addons\sourcemod\scripting\plugin2_bad.sp"
66+
Force = $true
67+
SkipWrapper = $true
68+
}
69+
$iterations = 2
70+
$expectedExitCode = 1
71+
& $functionTestScriptBlock
4972

5073
#############
5174
# AMX Mod X #
5275
#############
5376

54-
"`n[amxmodx] Compile plugin via wrapper" | Write-Host
77+
"`n[amxmodx] Compile plugin via wrapper, good plugin" | Write-Host
5578
# The following test should be run only for Windows, reason being that the non-Windows version:
5679
# - Does not take in arguments, instead compiles all plugins within the scripting directory
5780
# - Displays all the output using 'less' at the end of the compilation, thus is limited to interactive use
@@ -60,19 +83,39 @@ if ($env:OS -eq 'Windows_NT') {
6083
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin1.sma"
6184
Force = $true
6285
}
86+
$expectedExitCode = 0
87+
$iterations = 2
88+
& $functionTestScriptBlock
89+
90+
"`n[amxmodx] Compile plugin via wrapper, bad plugin" | Write-Host
91+
$cmdArgs = @{
92+
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin1_bad.sma"
93+
Force = $true
94+
}
95+
$expectedExitCode = 1
6396
$iterations = 2
6497
& $functionTestScriptBlock
6598
}else { "Skipping: Test only applicable to Windows." | Write-Host }
6699

67-
"`n[amxmodx] Compile plugin via compiler" | Write-Host
100+
"`n[amxmodx] Compile plugin via compiler, good plugin" | Write-Host
68101
$cmdArgs = @{
69102
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin2.sma"
70103
Force = $true
71104
SkipWrapper = $true
72105
}
106+
$expectedExitCode = 0
73107
$iterations = 2
74108
& $functionTestScriptBlock
75109

110+
"`n[amxmodx] Compile plugin via compiler, bad plugin" | Write-Host
111+
$cmdArgs = @{
112+
File = "$PSScriptRoot\..\..\mod\amxmodx\addons\amxmodx\scripting\plugin2_bad.sma"
113+
Force = $true
114+
SkipWrapper = $true
115+
}
116+
$expectedExitCode = 1
117+
$iterations = 2
118+
& $functionTestScriptBlock
76119

77120
###########
78121
# Results #

0 commit comments

Comments
 (0)