@@ -26,41 +26,11 @@ Set-Location $ProjectRoot
2626# Step 1: Check prerequisites
2727Write-Host " 🔍 Checking prerequisites..." - ForegroundColor Yellow
2828
29- # Check for Git
3029if (-not (Get-Command git - ErrorAction SilentlyContinue)) {
31- Write-Error " Git is required but not found in PATH"
32- exit 1
30+ Write-Error " Git is required but not found in PATH" ; exit 1
3331}
34-
35- # Check for .NET SDK
3632if (-not (Get-Command dotnet - ErrorAction SilentlyContinue)) {
37- Write-Error " .NET SDK is required but not found in PATH"
38- exit 1
39- }
40-
41- # Check for Visual Studio Build Tools
42- $MSBuildPaths = @ (
43- " ${env: ProgramFiles} \Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" ,
44- " ${env: ProgramFiles} \Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe" ,
45- " ${env: ProgramFiles} \Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" ,
46- " ${env: ProgramFiles} \Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\MSBuild.exe" ,
47- " ${env: ProgramFiles(x86)} \Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe" ,
48- " ${env: ProgramFiles(x86)} \Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" ,
49- " ${env: ProgramFiles(x86)} \Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" ,
50- " ${env: ProgramFiles(x86)} \Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe"
51- )
52-
53- $MSBuild = $null
54- foreach ($path in $MSBuildPaths ) {
55- if (Test-Path $path ) {
56- $MSBuild = $path
57- break
58- }
59- }
60-
61- if (-not $MSBuild ) {
62- Write-Warning " ⚠️ MSBuild not found. Native library compilation may fail."
63- Write-Host " Please install Visual Studio Build Tools 2019 or later"
33+ Write-Error " .NET SDK is required but not found in PATH" ; exit 1
6434}
6535
6636# Step 2: Clone and prepare libpg_query
@@ -81,281 +51,150 @@ if (-not $SkipNative) {
8151 Set-Location ..
8252 }
8353
84- # Build libpg_query using Windows Makefile
8554 Write-Host " 🔨 Building libpg_query for Windows..." - ForegroundColor Yellow
8655 Set-Location libpg_query
8756
88- if ($MSBuild ) {
89- # Try to build with Visual Studio
90- if (Test-Path " Makefile.msvc" ) {
91- Write-Host " Using Visual Studio tools..."
92- & nmake / F Makefile.msvc clean
93- & nmake / F Makefile.msvc
94- }
95- else {
96- Write-Warning " Makefile.msvc not found, trying alternative approach..."
97- # Fallback: try to use make with WSL or similar
98- if (Get-Command make - ErrorAction SilentlyContinue) {
99- & make clean
100- & make
101- }
102- else {
103- Write-Error " Cannot build libpg_query. Please install Visual Studio Build Tools or WSL."
104- exit 1
105- }
106- }
57+ if (Test-Path " Makefile.msvc" ) {
58+ Write-Host " Using Visual Studio tools (nmake)..."
59+ & nmake / F Makefile.msvc clean
60+ & nmake / F Makefile.msvc
61+ }
62+ else {
63+ Write-Error " Makefile.msvc not found in libpg_query. Cannot proceed with Windows build."
64+ exit 1
10765 }
10866
10967 Set-Location $ProjectRoot
11068
111- # Step 2b: Build wrapper library (FINAL FIX)
69+ # Step 2b: Build wrapper library
11270 Write-Host " 🔧 Building wrapper library..." - ForegroundColor Yellow
11371
114- # --- ADD CLEANUP STEP ---
11572 Write-Host " 🧹 Cleaning up old build artifacts..."
11673 Remove-Item - Path " wrapper.c" , " wrapper.def" , " libpgquery_wrapper.dll" - ErrorAction SilentlyContinue
11774
11875 $WrapperPath = Join-Path $ProjectRoot " wrapper.c"
11976 $DefPath = Join-Path $ProjectRoot " wrapper.def"
12077
121- # Create the wrapper.c file, forcing __stdcall calling convention to match .NET's P/Invoke default
12278 Write-Host " Creating wrapper.c with __stdcall calling convention..."
12379 @"
12480#include "libpg_query/pg_query.h"
125-
126- // Forcing __stdcall is crucial for default .NET P/Invoke on Windows
12781#define STDCALL __stdcall
12882
129- PgQueryProtobufParseResult STDCALL pg_query_parse_protobuf_wrapper(const char* input) {
130- return pg_query_parse_protobuf(input);
131- }
132-
133- PgQueryProtobufParseResult STDCALL pg_query_parse_protobuf_opts_wrapper(const char* input, int parser_options) {
134- return pg_query_parse_protobuf_opts(input, parser_options);
135- }
136-
137- void STDCALL pg_query_free_protobuf_parse_result_wrapper(PgQueryProtobufParseResult result) {
138- pg_query_free_protobuf_parse_result(result);
139- }
140-
141- PgQueryDeparseResult STDCALL pg_query_deparse_protobuf_wrapper(PgQueryProtobuf parse_tree) {
142- return pg_query_deparse_protobuf(parse_tree);
143- }
144-
145- PgQueryParseResult STDCALL pg_query_parse_wrapper(const char* input) {
146- return pg_query_parse(input);
147- }
148-
149- void STDCALL pg_query_free_parse_result_wrapper(PgQueryParseResult result) {
150- pg_query_free_parse_result(result);
151- }
152-
153- PgQueryNormalizeResult STDCALL pg_query_normalize_wrapper(const char* input) {
154- return pg_query_normalize(input);
155- }
156-
157- void STDCALL pg_query_free_normalize_result_wrapper(PgQueryNormalizeResult result) {
158- pg_query_free_normalize_result(result);
159- }
83+ PgQueryProtobufParseResult STDCALL pg_query_parse_protobuf_wrapper(const char* input) { return pg_query_parse_protobuf(input); }
84+ void STDCALL pg_query_free_protobuf_parse_result_wrapper(PgQueryProtobufParseResult result) { pg_query_free_protobuf_parse_result(result); }
85+ PgQueryParseResult STDCALL pg_query_parse_wrapper(const char* input) { return pg_query_parse(input); }
86+ void STDCALL pg_query_free_parse_result_wrapper(PgQueryParseResult result) { pg_query_free_parse_result(result); }
87+ PgQueryNormalizeResult STDCALL pg_query_normalize_wrapper(const char* input) { return pg_query_normalize(input); }
88+ void STDCALL pg_query_free_normalize_result_wrapper(PgQueryNormalizeResult result) { pg_query_free_normalize_result(result); }
16089"@ | Set-Content - Path $WrapperPath - Encoding Ascii
16190
162- # Create the .def file to export the wrapper functions with undecorated names
16391 Write-Host " Creating wrapper.def to export functions..."
16492 @"
16593EXPORTS
16694 pg_query_parse_protobuf_wrapper
167- pg_query_parse_protobuf_opts_wrapper
16895 pg_query_free_protobuf_parse_result_wrapper
169- pg_query_deparse_protobuf_wrapper
17096 pg_query_parse_wrapper
17197 pg_query_free_parse_result_wrapper
17298 pg_query_normalize_wrapper
17399 pg_query_free_normalize_result_wrapper
174100"@ | Set-Content - Path $DefPath - Encoding Ascii
175101
176102 $ClPath = Get-Command cl.exe - ErrorAction SilentlyContinue
177- if (-not $ClPath ) {
178- Write-Error " cl.exe not found. Ensure Visual Studio Build Tools are installed and vcvars are loaded."
179- exit 1
180- }
103+ if (-not $ClPath ) { Write-Error " cl.exe not found. Ensure Visual Studio Build Tools are installed and vcvars are loaded." ; exit 1 }
181104
182- # Compile the wrapper, linking the real library and using the .def file for exports.
183105 & $ClPath / nologo / LD / I " libpg_query" $WrapperPath " libpg_query\pg_query.lib" / DEF:$DefPath / link / OUT:libpgquery_wrapper.dll
184- if ($LASTEXITCODE -ne 0 ) {
185- Write-Error " ❌ Failed to compile wrapper library"
186- exit $LASTEXITCODE
187- }
106+ if ($LASTEXITCODE -ne 0 ) { Write-Error " ❌ Failed to compile wrapper library" ; exit $LASTEXITCODE }
188107}
189108
190109# Step 3: Create runtime directories and copy libraries
191110if (-not $SkipNative ) {
192111 Write-Host " 📁 Setting up runtime directories..." - ForegroundColor Yellow
193-
194112 $RuntimeDir = " runtimes\$TargetRid \native"
195113 New-Item - Path $RuntimeDir - ItemType Directory - Force | Out-Null
196114
197- # Define source locations for libraries
198115 $LibraryMappings = @ {
199- " libpg_query.dll" = @ (" libpg_query\libpg_query.dll" , " libpg_query\pg_query.dll" )
200- " libpg_query.lib" = @ (" libpg_query\libpg_query.lib" , " libpg_query\pg_query.lib" )
201- " libpgquery_wrapper.dll" = @ (" libpgquery_wrapper.dll" , " libpg_query\libpgquery_wrapper.dll" )
202- " pg_query.dll" = @ (" libpg_query\pg_query.dll" )
116+ " libpgquery_wrapper.dll" = @ (" libpgquery_wrapper.dll" )
203117 }
204118
205119 foreach ($targetLib in $LibraryMappings.Keys ) {
206- $copied = $false
207- foreach ($sourcePath in $LibraryMappings [$targetLib ]) {
208- if (Test-Path $sourcePath ) {
209- Write-Host " Copying $sourcePath to $RuntimeDir \$targetLib "
210- Copy-Item $sourcePath " $RuntimeDir \$targetLib " - Force
211- $copied = $true
212- break
213- }
120+ $sourcePath = $LibraryMappings [$targetLib ][0 ]
121+ if (Test-Path $sourcePath ) {
122+ Write-Host " Copying $sourcePath to $RuntimeDir \$targetLib "
123+ Copy-Item $sourcePath " $RuntimeDir \$targetLib " - Force
214124 }
215- if (-not $copied ) {
216- # This is expected for libpg_query.dll on Windows, as only the .lib is built. The wrapper serves as the DLL.
217- if ($targetLib -ne " libpg_query.dll" -and $targetLib -ne " pg_query.dll" ) {
218- Write-Warning " ⚠️ Could not find source for $targetLib "
219- }
125+ else {
126+ Write-Warning " ⚠️ Could not find source for $targetLib "
220127 }
221128 }
222129
223- # Also copy to project runtimes directory
224130 $ProjectRuntimeDir = " src\GrepSQL\runtimes\$TargetRid \native"
225131 New-Item - Path $ProjectRuntimeDir - ItemType Directory - Force | Out-Null
226-
227- # Copy from the main runtime directory to project directory
228132 Get-ChildItem $RuntimeDir - File | ForEach-Object {
229133 Write-Host " Copying $ ( $_.Name ) to $ProjectRuntimeDir "
230134 Copy-Item $_.FullName $ProjectRuntimeDir - Force
231135 }
232136
233- # Verify critical files exist
234- $CriticalFiles = @ (" libpgquery_wrapper.dll" )
235- foreach ($file in $CriticalFiles ) {
236- $projectPath = Join-Path $ProjectRuntimeDir $file
237- if (-not (Test-Path $projectPath )) {
238- Write-Error " ❌ Critical file $file not found in $ProjectRuntimeDir "
239- exit 1
240- }
241- else {
242- Write-Host " ✅ Verified $file exists in $ProjectRuntimeDir " - ForegroundColor Green
243- }
244- }
137+ $criticalFile = Join-Path $ProjectRuntimeDir " libpgquery_wrapper.dll"
138+ if (-not (Test-Path $criticalFile )) { Write-Error " ❌ Critical file libpgquery_wrapper.dll not found in $ProjectRuntimeDir " ; exit 1 }
139+ else { Write-Host " ✅ Verified libpgquery_wrapper.dll exists in $ProjectRuntimeDir " - ForegroundColor Green }
245140}
246141
247142# Step 4: Generate protobuf files
248143if (-not $SkipProtobuf ) {
249144 Write-Host " 🔧 Generating protobuf files..." - ForegroundColor Yellow
250-
251- # Check for protoc
252- $ProtocPath = Get-Command protoc - ErrorAction SilentlyContinue
253- if (-not $ProtocPath ) {
254- Write-Warning " ⚠️ protoc not found. Attempting to install via dotnet tool..."
255- & dotnet tool install -- global protobuf- net.Protogen -- version 3.2 .26
256-
257- # Try again
258- $ProtocPath = Get-Command protoc - ErrorAction SilentlyContinue
259- if (-not $ProtocPath ) {
260- Write-Error " ❌ Could not find or install protoc. Please install Protocol Buffers compiler manually."
261- exit 1
262- }
263- }
264-
265- # Add Grpc.Tools if not present
266- $GrpcToolsPath = " $env: USERPROFILE \.nuget\packages\grpc.tools"
267- if (-not (Test-Path $GrpcToolsPath )) {
268- Write-Host " Installing Grpc.Tools..."
269- & dotnet add " src\GrepSQL" package Grpc.Tools -- version 2.72 .0
145+ if (-not (Get-Command protoc - ErrorAction SilentlyContinue)) {
146+ Write-Warning " ⚠️ protoc not found. Please ensure it's installed and in the PATH."
270147 }
271-
272- # Find the latest version and appropriate platform tools
273- $LatestVersion = Get-ChildItem $GrpcToolsPath | Sort-Object Name - Descending | Select-Object - First 1
274- $PluginPath = " $ ( $LatestVersion.FullName ) \tools\windows_x64"
275-
276- if (-not (Test-Path $PluginPath )) {
277- $PluginPath = " $ ( $LatestVersion.FullName ) \tools\windows_x86"
148+ if (-not (Test-Path " $env: USERPROFILE \.nuget\packages\grpc.tools" )) {
149+ Write-Host " Installing Grpc.Tools NuGet package..."
150+ & dotnet add " src\GrepSQL" package Grpc.Tools
278151 }
279152
280- $env: PATH = " $env: PATH ;$PluginPath "
281-
282- # Generate protobuf files
283153 $ProtoSrc = " libpg_query\protobuf"
284154 $ProtoOut = " src\GrepSQL\AST\Generated"
285-
286155 New-Item - Path $ProtoOut - ItemType Directory - Force | Out-Null
287156
288- # Clean previous files
289- Get-ChildItem " $ProtoOut \*.cs" - ErrorAction SilentlyContinue | Remove-Item - Force
290-
291157 Write-Host " Generating C# protobuf classes..."
292158 & protoc -- proto_path= " $ProtoSrc " -- csharp_out= " $ProtoOut " -- csharp_opt= file_extension= .g.cs " $ProtoSrc \pg_query.proto"
293-
294- if ($LASTEXITCODE -ne 0 ) {
295- Write-Error " ❌ Protobuf generation failed"
296- exit $LASTEXITCODE
297- }
298-
299- # Verify generated files
300- if (-not (Test-Path " $ProtoOut \PgQuery.g.cs" )) {
301- Write-Error " ❌ Expected protobuf files not generated"
302- exit 1
303- }
304-
159+ if ($LASTEXITCODE -ne 0 ) { Write-Error " ❌ Protobuf generation failed" ; exit $LASTEXITCODE }
160+ if (-not (Test-Path " $ProtoOut \PgQuery.g.cs" )) { Write-Error " ❌ Expected protobuf files not generated" ; exit 1 }
305161 Write-Host " ✅ Protobuf generation completed" - ForegroundColor Green
306162}
307163
308- # Step 5: Build .NET project
164+ # Step 5: Build and Test .NET project
309165if (-not $SkipBuild ) {
310- Write-Host " 🔨 Building .NET project..." - ForegroundColor Yellow
166+ Write-Host " 🔨 Building .NET project for runtime $TargetRid ..." - ForegroundColor Yellow
311167
312- & dotnet build " src\GrepSQL\GrepSQL.csproj" `
168+ # Build the solution specifying the runtime. This ensures all projects are built
169+ # with the correct context for finding native dependencies.
170+ & dotnet build `
313171 -- configuration $Configuration `
314- -- verbosity minimal `
315- - p:Platform= " Any CPU"
316- if ($LASTEXITCODE -ne 0 ) {
317- Write-Error " ❌ Build failed"
318- exit $LASTEXITCODE
319- }
172+ -- runtime $TargetRid
173+ if ($LASTEXITCODE -ne 0 ) { Write-Error " ❌ Build failed" ; exit $LASTEXITCODE }
320174
321175 Write-Host " ✅ Build completed successfully" - ForegroundColor Green
322176
323- # Run tests if they exist
324177 if (Test-Path " tests\GrepSQL.Tests.csproj" ) {
325- Write-Host " 🧪 Running tests..." - ForegroundColor Yellow
326- & dotnet test -- configuration $Configuration -- verbosity minimal
178+ Write-Host " 🧪 Running tests for runtime $TargetRid ..." - ForegroundColor Yellow
179+ # The --runtime flag is the critical fix.
180+ # --no-build is a best practice to ensure we test what was just built.
181+ & dotnet test " tests\GrepSQL.Tests.csproj" `
182+ -- configuration $Configuration `
183+ -- runtime $TargetRid `
184+ -- no- build `
185+ -- verbosity normal
327186 if ($LASTEXITCODE -ne 0 ) {
328- Write-Warning " ⚠️ Tests failed"
187+ Write-Warning " ⚠️ Tests failed. Please review the output."
188+ exit $LASTEXITCODE # Exit on test failure to fail the CI job
329189 }
330190 }
331191
332- # Create NuGet package
333192 Write-Host " 📦 Creating NuGet package..." - ForegroundColor Yellow
334193 New-Item - Path " artifacts" - ItemType Directory - Force | Out-Null
335194 & dotnet pack " src\GrepSQL\GrepSQL.csproj" `
336195 -- configuration $Configuration `
337- -- output " artifacts" `
338- - p:Platform= " Any CPU"
196+ -- output " artifacts"
339197}
340198
341199Write-Host " "
342- Write-Host " 🎉 Build completed successfully!" - ForegroundColor Green
343- Write-Host " "
344- Write-Host " 📊 Build Summary:" - ForegroundColor Cyan
345- Write-Host " Target RID: $TargetRid "
346- Write-Host " Configuration: $Configuration "
347-
348- if (Test-Path " runtimes\$TargetRid \native" ) {
349- Write-Host " Generated Libraries:"
350- Get-ChildItem " runtimes\$TargetRid \native" | ForEach-Object { Write-Host " $ ( $_.Name ) " }
351- }
352-
353- if (Test-Path " src\GrepSQL\AST\Generated" ) {
354- Write-Host " Generated Protobuf Files:"
355- Get-ChildItem " src\GrepSQL\AST\Generated\*.cs" | ForEach-Object { Write-Host " $ ( $_.Name ) " }
356- }
357-
358- if (Test-Path " artifacts" ) {
359- Write-Host " NuGet Packages:"
360- Get-ChildItem " artifacts\*.nupkg" | ForEach-Object { Write-Host " $ ( $_.Name ) " }
361- }
200+ Write-Host " 🎉 Build process completed successfully!" - ForegroundColor Green
0 commit comments