@@ -205,12 +205,136 @@ jobs:
205205 New-Item -ItemType Directory -Path $OutputPath | Out-Null
206206 Copy-Item $OutputLibrary $(Join-Path $OutputPath $RenamedLibraryName)
207207
208+ # Export variables for symbol collection step
209+ echo "RUST_TARGET=$RustTarget" >> $Env:GITHUB_ENV
210+ echo "TARGET_FOLDER=$TargetFolder" >> $Env:GITHUB_ENV
211+ echo "LIB_PREFIX=$LibPrefix" >> $Env:GITHUB_ENV
212+ echo "DOTNET_OS=$DotNetOs" >> $Env:GITHUB_ENV
213+ echo "DOTNET_RID=$DotNetRid" >> $Env:GITHUB_ENV
214+
215+ - name : Collect debug symbols
216+ if : matrix.build == 'release'
217+ shell : pwsh
218+ run : |
219+ Set-PSDebug -Trace 1
220+
221+ $DotNetOs = $Env:DOTNET_OS
222+ $DotNetRid = $Env:DOTNET_RID
223+ $RustTarget = $Env:RUST_TARGET
224+ $TargetFolder = $Env:TARGET_FOLDER
225+ $LibPrefix = $Env:LIB_PREFIX
226+
227+ $SymbolsPath = Join-Path "symbols" $DotNetRid
228+ New-Item -ItemType Directory -Path $SymbolsPath -Force | Out-Null
229+
230+ $TargetDir = Join-Path "target" $RustTarget $TargetFolder
231+
232+ if ($DotNetOs -eq 'win') {
233+ # Windows: Copy PDB file
234+ $PdbFile = Join-Path $TargetDir "sspi.pdb"
235+ if (Test-Path $PdbFile) {
236+ Copy-Item $PdbFile (Join-Path $SymbolsPath "DevolutionsSspi.pdb")
237+ Write-Host "Copied PDB: $PdbFile"
238+ } else {
239+ Write-Warning "PDB file not found: $PdbFile"
240+ Get-ChildItem $TargetDir -Filter "*.pdb" | ForEach-Object { Write-Host "Found PDB: $($_.FullName)" }
241+ }
242+ } elseif ($DotNetOs -eq 'osx' -or $DotNetOs -eq 'ios') {
243+ # macOS/iOS: Generate dSYM bundle using dsymutil
244+ $DylibFile = Join-Path $TargetDir "${LibPrefix}sspi.dylib"
245+ $DsymOutput = Join-Path $SymbolsPath "libDevolutionsSspi.dylib.dSYM"
246+ if (Test-Path $DylibFile) {
247+ & dsymutil $DylibFile -o $DsymOutput
248+ Write-Host "Generated dSYM: $DsymOutput"
249+ } else {
250+ Write-Warning "Dylib file not found: $DylibFile"
251+ }
252+ } elseif ($DotNetOs -eq 'linux' -or $DotNetOs -eq 'android') {
253+ # Linux/Android: Extract debug info into a separate file
254+ $DwpFile = Join-Path $TargetDir "${LibPrefix}sspi.dwp"
255+ $SoFile = Join-Path $TargetDir "${LibPrefix}sspi.so"
256+ $DebugOutput = Join-Path $SymbolsPath "libDevolutionsSspi.so.debug"
257+ if (Test-Path $DwpFile) {
258+ # split-debuginfo=packed may produce a .dwp file
259+ Copy-Item $DwpFile (Join-Path $SymbolsPath "libDevolutionsSspi.so.dwp")
260+ Write-Host "Copied DWP: $DwpFile"
261+ } elseif (Test-Path $SoFile) {
262+ # Extract debug sections from the binary using objcopy
263+ if ($DotNetOs -eq 'android') {
264+ $ObjCopy = Join-Path $Env:ANDROID_NDK_HOME "toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy"
265+ if (-not (Test-Path $ObjCopy)) {
266+ throw "llvm-objcopy not found at $ObjCopy"
267+ }
268+ } else {
269+ $ObjCopy = 'llvm-objcopy'
270+ $ObjCopyCmd = Get-Command $ObjCopy -ErrorAction SilentlyContinue
271+ if (-not $ObjCopyCmd) {
272+ throw "llvm-objcopy not found on PATH"
273+ }
274+ }
275+ Write-Host "Extracting debug info with: $ObjCopy --only-keep-debug"
276+ & $ObjCopy --only-keep-debug $SoFile $DebugOutput 2>&1 | Write-Host
277+ Write-Host "Extracted debug info: $DebugOutput"
278+ $SizeMB = [math]::Round((Get-Item $DebugOutput).Length / 1MB, 2)
279+ Write-Host "Debug file size: $SizeMB MB"
280+ } else {
281+ Write-Warning "No debug symbols found for Linux/Android"
282+ }
283+ }
284+
285+ # List collected symbols
286+ Write-Host "Collected symbols:"
287+ Get-ChildItem -Recurse $SymbolsPath | ForEach-Object { Write-Host $_.FullName }
288+
289+ - name : Strip release binaries
290+ if : matrix.build == 'release'
291+ shell : pwsh
292+ run : |
293+ $DotNetOs = $Env:DOTNET_OS
294+ $DotNetRid = $Env:DOTNET_RID
295+ $LibPrefix = $Env:LIB_PREFIX
296+ $RuntimePath = Join-Path "dependencies" "runtimes" "$DotNetRid" "native"
297+
298+ if ($DotNetOs -eq 'win') {
299+ # Windows: DLL is already separate from PDB, no stripping needed
300+ Write-Host "Windows binaries are already compact (PDB is separate)"
301+ } elseif ($DotNetOs -eq 'osx' -or $DotNetOs -eq 'ios') {
302+ $DylibFile = Join-Path $RuntimePath "${LibPrefix}DevolutionsSspi.dylib"
303+ if (Test-Path $DylibFile) {
304+ & strip -Sx $DylibFile
305+ Write-Host "Stripped dylib: $DylibFile"
306+ $SizeMB = [math]::Round((Get-Item $DylibFile).Length / 1MB, 2)
307+ Write-Host "Size after stripping: $SizeMB MB"
308+ }
309+ } elseif ($DotNetOs -eq 'android' -or $DotNetOs -eq 'linux') {
310+ $SoFile = Join-Path $RuntimePath "${LibPrefix}DevolutionsSspi.so"
311+ if (Test-Path $SoFile) {
312+ if ($DotNetOs -eq 'android') {
313+ $StripTool = Join-Path $Env:ANDROID_NDK_HOME "toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip"
314+ } else {
315+ $StripTool = 'llvm-strip'
316+ }
317+ Write-Host "Using strip tool: $StripTool"
318+ & $StripTool --strip-unneeded $SoFile 2>&1 | Write-Host
319+ Write-Host "Stripped .so ($DotNetOs): $SoFile"
320+ $SizeMB = [math]::Round((Get-Item $SoFile).Length / 1MB, 2)
321+ Write-Host "Size after stripping: $SizeMB MB"
322+ }
323+ }
324+
208325 - name : Upload native components
209326 uses : actions/upload-artifact@v4
210327 with :
211328 name : sspi-${{matrix.os}}-${{matrix.arch}}-${{matrix.build}}
212329 path : dependencies/runtimes/${{matrix.os}}-${{matrix.arch}}
213330
331+ - name : Upload debug symbols
332+ if : matrix.build == 'release'
333+ uses : actions/upload-artifact@v4
334+ with :
335+ name : sspi-${{matrix.os}}-${{matrix.arch}}-${{matrix.build}}-symbols
336+ path : symbols/${{matrix.os}}-${{matrix.arch}}
337+
214338 build-universal :
215339 name : Universal Build
216340 runs-on : ubuntu-24.04
@@ -228,6 +352,29 @@ jobs:
228352 - name : Setup CCTools
229353 uses : Devolutions/actions-public/setup-cctools@v1
230354
355+ - name : Install Apple strip (cctools)
356+ if : matrix.build == 'release'
357+ shell : pwsh
358+ run : |
359+ $DownloadVersion = "v2025.2.0"
360+ $HostPlatform = "ubuntu-$(lsb_release -rs)"
361+ $HostArch = @{'X64'='x86_64';'ARM64'='aarch64'}['${{ runner.arch }}']
362+ $PackageBaseName = "cctools-$HostArch-$HostPlatform"
363+ $DownloadFile = "${PackageBaseName}.tar.xz"
364+ $BaseDownloadUrl = "https://github.com/awakecoding/llvm-prebuilt/releases/download/$DownloadVersion"
365+
366+ curl -L -o $DownloadFile "${BaseDownloadUrl}/${DownloadFile}"
367+ tar -xf $DownloadFile -C /tmp
368+ sudo mv "/tmp/${PackageBaseName}/bin/strip" /usr/bin/apple-strip
369+ sudo chmod +x /usr/bin/apple-strip
370+ Remove-Item $DownloadFile -Force | Out-Null
371+
372+ - name : Setup LLVM
373+ uses : Devolutions/actions-public/setup-llvm@v1
374+ if : matrix.build == 'release'
375+ with :
376+ version : " 18.1.8"
377+
231378 - name : Download native components
232379 uses : actions/download-artifact@v4
233380 with :
@@ -290,8 +437,64 @@ jobs:
290437 # It's perfectly valid XML, but we're dealing with plists here and dyld will not be able to read the file
291438 ((Get-Content -Path (Join-Path $FrameworkDir "Info.plist") -Raw) -Replace 'PropertyList-1.0.dtd"\[\]', 'PropertyList-1.0.dtd"') | Set-Content -Path (Join-Path $FrameworkDir "Info.plist")
292439
440+ # Strip the framework executable (debug symbols will be in dSYM)
441+ if ('${{ matrix.build }}' -eq 'release') {
442+ if (-not (Test-Path "/usr/bin/apple-strip")) {
443+ throw "apple-strip not found at /usr/bin/apple-strip"
444+ }
445+ & /usr/bin/apple-strip -Sx $FrameworkExecutable
446+ Write-Host "Stripped framework executable with: /usr/bin/apple-strip -Sx"
447+ $SizeMB = [math]::Round((Get-Item $FrameworkExecutable).Length / 1MB, 2)
448+ Write-Host "Size after stripping: $SizeMB MB"
449+ }
450+
451+ - name : Generate universal dSYM
452+ if : matrix.build == 'release'
453+ shell : pwsh
454+ run : |
455+ Set-PSDebug -Trace 1
456+
457+ $SymbolsPath = Join-Path "symbols" "${{ matrix.os }}-universal"
458+ New-Item -ItemType Directory -Path $SymbolsPath -Force | Out-Null
459+
460+ $DylibFile = Join-Path "dependencies" "runtimes" "${{ matrix.os }}-universal" "native" "libDevolutionsSspi.dylib"
461+ $DsymOutput = Join-Path $SymbolsPath "libDevolutionsSspi.dylib.dSYM"
462+
463+ if (Test-Path $DylibFile) {
464+ & dsymutil $DylibFile -o $DsymOutput
465+ Write-Host "Generated universal dSYM: $DsymOutput"
466+ } else {
467+ Write-Warning "Universal dylib not found: $DylibFile"
468+ }
469+
470+ # List collected symbols
471+ Write-Host "Collected symbols:"
472+ Get-ChildItem -Recurse $SymbolsPath | ForEach-Object { Write-Host $_.FullName }
473+
474+ - name : Strip universal binary
475+ if : matrix.build == 'release'
476+ shell : pwsh
477+ run : |
478+ $DylibFile = Join-Path "dependencies" "runtimes" "${{ matrix.os }}-universal" "native" "libDevolutionsSspi.dylib"
479+ if (Test-Path $DylibFile) {
480+ if (-not (Test-Path "/usr/bin/apple-strip")) {
481+ throw "apple-strip not found at /usr/bin/apple-strip"
482+ }
483+ & /usr/bin/apple-strip -Sx $DylibFile
484+ Write-Host "Stripped universal dylib with: /usr/bin/apple-strip -Sx"
485+ $SizeMB = [math]::Round((Get-Item $DylibFile).Length / 1MB, 2)
486+ Write-Host "Size after stripping: $SizeMB MB"
487+ }
488+
293489 - name : Upload native components
294490 uses : actions/upload-artifact@v4
295491 with :
296492 name : sspi-${{ matrix.os }}-universal-${{ matrix.build }}
297493 path : dependencies/runtimes/${{ matrix.os }}-universal
494+
495+ - name : Upload universal debug symbols
496+ if : matrix.build == 'release'
497+ uses : actions/upload-artifact@v4
498+ with :
499+ name : sspi-${{ matrix.os }}-universal-${{ matrix.build }}-symbols
500+ path : symbols/${{ matrix.os }}-universal
0 commit comments