|
1 | 1 | <# |
2 | | -build-temp.ps1 |
3 | | -Compile the project inside a temporary directory under $env:TEMP (e.g. C:\Windows\Temp), copy the resulting EXE back into this repo, and remove all temporary artifacts. |
4 | | -Requires: run from a Developer Command Prompt for Visual Studio where `cl.exe` is on PATH. |
| 2 | +build.ps1 |
| 3 | +Compiles the interpreter in a temporary directory and copies the resulting EXE |
| 4 | +back into this repo. Also discovers extension C sources under ext/ and lib/ |
| 5 | +and compiles each one into a dynamic library next to its source file. |
| 6 | +
|
| 7 | +Requires: run from a Developer Command Prompt for Visual Studio where cl.exe is on PATH. |
5 | 8 | Usage (from Prefix-C folder): |
6 | | - powershell -ExecutionPolicy Bypass -File .\build-temp.ps1 |
| 9 | + powershell -ExecutionPolicy Bypass -File .\build.ps1 |
7 | 10 | #> |
8 | 11 |
|
9 | 12 | $script = Split-Path -Parent $MyInvocation.MyCommand.Definition |
10 | 13 | $src = Join-Path $script "src" |
| 14 | +$extRoots = @( |
| 15 | + (Join-Path $script "ext"), |
| 16 | + (Join-Path $script "lib"), |
| 17 | + (Join-Path $script "tests") |
| 18 | +) |
11 | 19 |
|
12 | | -Write-Host "Preparing temp build directory under`$env:TEMP`..." |
| 20 | +Write-Host "Preparing temp build directory under`$env:TEMP..." |
13 | 21 | $stamp = Get-Date -Format "yyyyMMdd-HHmmss" |
14 | 22 | $buildDir = Join-Path $env:TEMP ("prefix-build-$stamp") |
15 | 23 | New-Item -ItemType Directory -Path $buildDir -Force | Out-Null |
16 | | - |
17 | 24 | Write-Host "Build dir: $buildDir" |
18 | 25 |
|
19 | | -# Ensure cl.exe is available |
20 | 26 | $cl = Get-Command cl.exe -ErrorAction SilentlyContinue |
21 | 27 | if (-not $cl) { |
22 | 28 | Write-Error "cl.exe not found. Run this script from a Developer Command Prompt for Visual Studio." |
| 29 | + Remove-Item -Recurse -Force $buildDir -ErrorAction SilentlyContinue |
23 | 30 | exit 1 |
24 | 31 | } |
25 | 32 |
|
26 | | -# Collect .c files |
27 | 33 | $cFiles = Get-ChildItem -Path $src -Filter *.c -File -Recurse | ForEach-Object { $_.FullName } |
28 | 34 | if ($cFiles.Count -eq 0) { |
29 | 35 | Write-Error "No .c files found in '$src'" |
30 | 36 | Remove-Item -Recurse -Force $buildDir -ErrorAction SilentlyContinue |
31 | 37 | exit 1 |
32 | 38 | } |
33 | 39 |
|
34 | | -Push-Location $buildDir |
| 40 | +$platform = [System.Runtime.InteropServices.RuntimeInformation] |
| 41 | +$extSuffix = ".dll" |
| 42 | +if ($platform::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Linux)) { |
| 43 | + $extSuffix = ".so" |
| 44 | +} elseif ($platform::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::OSX)) { |
| 45 | + $extSuffix = ".dylib" |
| 46 | +} |
35 | 47 |
|
| 48 | +Push-Location $buildDir |
36 | 49 | try { |
37 | | - # Build in temp dir; cl will place outputs in the current dir |
38 | | - $fe = "/Fe:prefix.exe" |
39 | | - $args = @("/std:c17", "/Gd", "/O2", "/Gy", "/GF", "/GL", "/W4", "/WX", "/MP", "/nologo", $fe) |
40 | | - $args += $cFiles |
41 | | - |
42 | | - Write-Host "Invoking: cl.exe $($args -join ' ')" |
43 | | - & cl.exe @args |
44 | | - $rc = $LASTEXITCODE |
45 | | - if ($rc -ne 0) { |
46 | | - throw "cl.exe returned exit code $rc" |
| 50 | + $exeArgs = @( |
| 51 | + "/std:c17", "/Gd", "/O2", "/Gy", "/GF", "/GL", "/W4", "/WX", "/MP", "/nologo", |
| 52 | + "/Fe:prefix.exe" |
| 53 | + ) |
| 54 | + $exeArgs += $cFiles |
| 55 | + |
| 56 | + Write-Host "Invoking: cl.exe $($exeArgs -join ' ')" |
| 57 | + & cl.exe @exeArgs |
| 58 | + if ($LASTEXITCODE -ne 0) { |
| 59 | + throw "cl.exe returned exit code $LASTEXITCODE while building interpreter" |
47 | 60 | } |
48 | 61 |
|
49 | | - # Copy EXE back to repo (Prefix-C root) |
50 | | - $outExe = Join-Path $buildDir 'prefix.exe' |
| 62 | + $outExe = Join-Path $buildDir "prefix.exe" |
51 | 63 | if (-not (Test-Path $outExe)) { |
52 | 64 | throw "Expected output EXE not found: $outExe" |
53 | 65 | } |
54 | | - $dest = Join-Path $script 'prefix.exe' |
55 | | - Copy-Item -Path $outExe -Destination $dest -Force |
56 | | - Write-Host "Copied EXE to: $dest" |
57 | 66 |
|
| 67 | + $exeDest = Join-Path $script "prefix.exe" |
| 68 | + Copy-Item -Path $outExe -Destination $exeDest -Force |
| 69 | + Write-Host "Copied EXE to: $exeDest" |
| 70 | + |
| 71 | + $extSources = @() |
| 72 | + foreach ($root in $extRoots) { |
| 73 | + if (Test-Path $root) { |
| 74 | + $extSources += Get-ChildItem -Path $root -Filter *.c -File -Recurse |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + if ($extSources.Count -eq 0) { |
| 79 | + Write-Host "No extension C sources found under ext/ or lib/." |
| 80 | + } else { |
| 81 | + Write-Host "Found $($extSources.Count) extension source file(s)." |
| 82 | + } |
| 83 | + |
| 84 | + foreach ($extSource in $extSources) { |
| 85 | + $extSourcePath = $extSource.FullName |
| 86 | + $extName = [System.IO.Path]::GetFileNameWithoutExtension($extSourcePath) |
| 87 | + $extOutName = "$extName$extSuffix" |
| 88 | + $extDest = Join-Path $extSource.DirectoryName $extOutName |
| 89 | + $extBuildDir = Join-Path $buildDir ("ext-" + [guid]::NewGuid().ToString("N")) |
| 90 | + |
| 91 | + New-Item -ItemType Directory -Path $extBuildDir -Force | Out-Null |
| 92 | + Push-Location $extBuildDir |
| 93 | + try { |
| 94 | + $extArgs = @( |
| 95 | + "/std:c17", "/Gd", "/O2", "/W4", "/WX", "/nologo", "/LD", |
| 96 | + "/I$src", |
| 97 | + "/Fe:$extOutName", |
| 98 | + $extSourcePath |
| 99 | + ) |
| 100 | + |
| 101 | + Write-Host "Invoking: cl.exe $($extArgs -join ' ')" |
| 102 | + & cl.exe @extArgs |
| 103 | + if ($LASTEXITCODE -ne 0) { |
| 104 | + throw "cl.exe returned exit code $LASTEXITCODE while building extension '$extSourcePath'" |
| 105 | + } |
| 106 | + |
| 107 | + $extOutPath = Join-Path $extBuildDir $extOutName |
| 108 | + if (-not (Test-Path $extOutPath)) { |
| 109 | + throw "Expected output extension not found: $extOutPath" |
| 110 | + } |
| 111 | + |
| 112 | + Copy-Item -Path $extOutPath -Destination $extDest -Force |
| 113 | + Write-Host "Copied extension to: $extDest" |
| 114 | + } finally { |
| 115 | + Pop-Location |
| 116 | + Remove-Item -Recurse -Force $extBuildDir -ErrorAction SilentlyContinue |
| 117 | + } |
| 118 | + } |
58 | 119 | } catch { |
59 | 120 | Write-Error "Build failed: $_" |
60 | | - Pop-Location |
61 | | - # Cleanup temp build dir on failure as well |
62 | | - Write-Host "Cleaning up temp build dir: $buildDir" |
63 | | - Remove-Item -Recurse -Force $buildDir -ErrorAction SilentlyContinue |
64 | 121 | exit 1 |
65 | 122 | } finally { |
66 | 123 | Pop-Location |
| 124 | + Write-Host "Cleaning up temp build dir: $buildDir" |
| 125 | + Remove-Item -Recurse -Force $buildDir -ErrorAction SilentlyContinue |
67 | 126 | } |
68 | 127 |
|
69 | | -# Cleanup temp build dir |
70 | | -Write-Host "Cleaning up temp build dir: $buildDir" |
71 | | -Remove-Item -Recurse -Force $buildDir -ErrorAction SilentlyContinue |
72 | | - |
73 | 128 | Write-Host "Build succeeded and exe copied to: $(Join-Path $script 'prefix.exe')" |
74 | 129 | exit 0 |
0 commit comments