diff --git a/.github/workflows/build-native.yml b/.github/workflows/build-native.yml index ae3eb6d7..9bade3ed 100644 --- a/.github/workflows/build-native.yml +++ b/.github/workflows/build-native.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ win, osx, linux, ios, android ] + os: [ win, osx, linux, ios, iossimulator, android ] arch: [ x86, x64, arm, arm64 ] build: [ debug, release ] include: @@ -44,6 +44,8 @@ jobs: runner: ubuntu-22.04 - os: ios runner: macos-14 + - os: iossimulator + runner: macos-14 - os: android runner: ubuntu-22.04 exclude: @@ -63,6 +65,14 @@ jobs: os: linux - arch: x86 os: ios + - arch: x64 + os: ios + - arch: arm + os: iossimulator + - arch: x86 + os: iossimulator + - arch: x64 + os: iossimulator steps: - name: Checkout ${{ github.repository }} @@ -93,7 +103,7 @@ jobs: Install-Module VsDevShell -Force - name: Install dependencies - if: matrix.os == 'ios' + if: matrix.os == 'ios' || matrix.os == 'iossimulator' run: cargo install --force --locked bindgen-cli - name: Setup build environment @@ -103,6 +113,10 @@ jobs: echo "MACOSX_DEPLOYMENT_TARGET=10.10" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append } elseif ('${{ matrix.os }}' -Eq 'ios') { echo "IPHONEOS_DEPLOYMENT_TARGET=12.1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + } elseif ('${{ matrix.os }}' -Eq 'iossimulator') { + echo "IPHONESIMULATOR_DEPLOYMENT_TARGET=12.1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + $SimulatorSdk = xcrun --sdk iphonesimulator --show-sdk-path + echo "SDKROOT=$SimulatorSdk" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append } - name: Setup LLVM @@ -135,11 +149,11 @@ jobs: 'x86'='i386';'arm'='arm'}[$DotNetArch] $MsvcArch = @{'x64'='x64';'arm64'='arm64'}[$DotNetArch] $RustPlatform = @{'win'='pc-windows-msvc'; - 'osx'='apple-darwin';'ios'='apple-ios'; + 'osx'='apple-darwin';'ios'='apple-ios';'iossimulator'='apple-ios-sim'; 'linux'='unknown-linux-gnu';'android'='linux-android'}[$DotNetOs] - $LibPrefix = @{'win'='';'osx'='lib';'ios'='lib'; + $LibPrefix = @{'win'='';'osx'='lib';'ios'='lib';'iossimulator'='lib'; 'linux'='lib';'android'='lib'}[$DotNetOs] - $LibSuffix = @{'win'='.dll';'osx'='.dylib';'ios'='.dylib'; + $LibSuffix = @{'win'='.dll';'osx'='.dylib';'ios'='.dylib';'iossimulator'='.dylib'; 'linux'='.so';'android'='.so'}[$DotNetOs] $RustTarget = "$RustArch-$RustPlatform" $TargetFolder = @{'debug'='debug';'release'='ffi-production'}[$BuildType] @@ -239,7 +253,7 @@ jobs: Write-Warning "PDB file not found: $PdbFile" Get-ChildItem $TargetDir -Filter "*.pdb" | ForEach-Object { Write-Host "Found PDB: $($_.FullName)" } } - } elseif ($DotNetOs -eq 'osx' -or $DotNetOs -eq 'ios') { + } elseif ($DotNetOs -eq 'osx' -or $DotNetOs -eq 'ios' -or $DotNetOs -eq 'iossimulator') { # macOS/iOS: Generate dSYM bundle using dsymutil $DylibFile = Join-Path $TargetDir "${LibPrefix}sspi.dylib" $DsymOutput = Join-Path $SymbolsPath "libDevolutionsSspi.dylib.dSYM" @@ -298,7 +312,7 @@ jobs: if ($DotNetOs -eq 'win') { # Windows: DLL is already separate from PDB, no stripping needed Write-Host "Windows binaries are already compact (PDB is separate)" - } elseif ($DotNetOs -eq 'osx' -or $DotNetOs -eq 'ios') { + } elseif ($DotNetOs -eq 'osx' -or $DotNetOs -eq 'ios' -or $DotNetOs -eq 'iossimulator') { $DylibFile = Join-Path $RuntimePath "${LibPrefix}DevolutionsSspi.dylib" if (Test-Path $DylibFile) { & strip -Sx $DylibFile @@ -322,6 +336,51 @@ jobs: } } + - name: Framework (${{matrix.os}}-${{matrix.arch}}) (${{matrix.build}}) + if: matrix.os == 'ios' || matrix.os == 'iossimulator' + shell: pwsh + run: | + $Version = '${{ needs.preflight.outputs.project-version }}' + $ShortVersion = '${{ needs.preflight.outputs.package-version }}' + $BundleName = "libDevolutionsSspi" + $RuntimesDir = Join-Path "dependencies" "runtimes" "${{ matrix.os }}-${{ matrix.arch }}" "native" + $FrameworkDir = Join-Path "$RuntimesDir" "$BundleName.framework" + New-Item -Path $FrameworkDir -ItemType "directory" -Force + $FrameworkExecutable = Join-Path $FrameworkDir $BundleName + Copy-Item -Path (Join-Path "$RuntimesDir" "$BundleName.dylib") -Destination $FrameworkExecutable -Force + + $RPathCmd = $(@('install_name_tool', '-id', "@rpath/$BundleName.framework/$BundleName", "$FrameworkExecutable")) -Join ' ' + Write-Host $RPathCmd + Invoke-Expression $RPathCmd + + [xml] $InfoPlistXml = Get-Content "Info.plist" + Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleIdentifier']/following-sibling::string[1]" | + %{ + $_.Node.InnerXml = "com.devolutions.sspi" + } + Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleExecutable']/following-sibling::string[1]" | + %{ + $_.Node.InnerXml = $BundleName + } + Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleVersion']/following-sibling::string[1]" | + %{ + $_.Node.InnerXml = $Version + } + Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleShortVersionString']/following-sibling::string[1]" | + %{ + $_.Node.InnerXml = $ShortVersion + } + + # Write the plist *without* a BOM + $Encoding = New-Object System.Text.UTF8Encoding($false) + $Writer = New-Object System.IO.StreamWriter((Join-Path $FrameworkDir "Info.plist"), $false, $Encoding) + $InfoPlistXml.Save($Writer) + $Writer.Close() + + # .NET XML document inserts two square brackets at the end of the DOCTYPE tag + # It's perfectly valid XML, but we're dealing with plists here and dyld will not be able to read the file + ((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") + - name: Upload native components uses: actions/upload-artifact@v7 with: @@ -342,7 +401,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ osx, ios ] + os: [ osx ] build: [ debug, release ] steps: @@ -392,62 +451,6 @@ jobs: Write-Host $LipoCmd Invoke-Expression $LipoCmd - - name: Framework (${{matrix.build}}) - shell: pwsh - if: ${{ matrix.os == 'ios' }} - run: | - $Version = '${{ needs.preflight.outputs.project-version }}' - $ShortVersion = '${{ needs.preflight.outputs.package-version }}' - $BundleName = "libDevolutionsSspi" - $RuntimesDir = Join-Path "dependencies" "runtimes" "ios-universal" "native" - $FrameworkDir = Join-Path "$RuntimesDir" "$BundleName.framework" - New-Item -Path $FrameworkDir -ItemType "directory" -Force - $FrameworkExecutable = Join-Path $FrameworkDir $BundleName - Copy-Item -Path (Join-Path "$RuntimesDir" "$BundleName.dylib") -Destination $FrameworkExecutable -Force - - $RPathCmd = $(@('install_name_tool', '-id', "@rpath/$BundleName.framework/$BundleName", "$FrameworkExecutable")) -Join ' ' - Write-Host $RPathCmd - Invoke-Expression $RPathCmd - - [xml] $InfoPlistXml = Get-Content "Info.plist" - Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleIdentifier']/following-sibling::string[1]" | - %{ - $_.Node.InnerXml = "com.devolutions.sspi" - } - Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleExecutable']/following-sibling::string[1]" | - %{ - $_.Node.InnerXml = $BundleName - } - Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleVersion']/following-sibling::string[1]" | - %{ - $_.Node.InnerXml = $Version - } - Select-Xml -xml $InfoPlistXml -XPath "/plist/dict/key[. = 'CFBundleShortVersionString']/following-sibling::string[1]" | - %{ - $_.Node.InnerXml = $ShortVersion - } - - # Write the plist *without* a BOM - $Encoding = New-Object System.Text.UTF8Encoding($false) - $Writer = New-Object System.IO.StreamWriter((Join-Path $FrameworkDir "Info.plist"), $false, $Encoding) - $InfoPlistXml.Save($Writer) - $Writer.Close() - - # .NET XML document inserts two square brackets at the end of the DOCTYPE tag - # It's perfectly valid XML, but we're dealing with plists here and dyld will not be able to read the file - ((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") - - # Strip the framework executable (debug symbols will be in dSYM) - if ('${{ matrix.build }}' -eq 'release') { - if (-not (Test-Path "/usr/bin/apple-strip")) { - throw "apple-strip not found at /usr/bin/apple-strip" - } - & /usr/bin/apple-strip -Sx $FrameworkExecutable - Write-Host "Stripped framework executable with: /usr/bin/apple-strip -Sx" - $SizeMB = [math]::Round((Get-Item $FrameworkExecutable).Length / 1MB, 2) - Write-Host "Size after stripping: $SizeMB MB" - } - - name: Generate universal dSYM if: matrix.build == 'release' shell: pwsh diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 83cbed4f..f26ff3cf 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -266,7 +266,8 @@ jobs: - Windows (x64, arm64) - macOS (x64, arm64, universal) - Linux (x64, arm64) - - iOS (x64, arm64, universal) + - iOS device (arm64) + - iOS Simulator (arm64) - Android (x86, x64, arm, arm64) ### Debug Symbols diff --git a/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.csproj b/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.csproj index 402c7fb6..0393027d 100644 --- a/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.csproj +++ b/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.csproj @@ -32,7 +32,8 @@ $(RuntimesPath)/android-x64/native/libDevolutionsSspi.so $(RuntimesPath)/android-arm/native/libDevolutionsSspi.so $(RuntimesPath)/android-arm64/native/libDevolutionsSspi.so - $(RuntimesPath)/ios-universal/native/libDevolutionsSspi.framework + $(RuntimesPath)/ios-arm64/native/libDevolutionsSspi.framework + $(RuntimesPath)/iossimulator-arm64/native/libDevolutionsSspi.framework @@ -134,9 +135,17 @@ - - - runtimes/ios-universal/native/ + + + runtimes/ios-arm64/native/ + true + Never + + + + + + runtimes/iossimulator-arm64/native/ true Never diff --git a/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.targets b/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.targets index bb817b3a..450cf732 100644 --- a/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.targets +++ b/ffi/dotnet/Devolutions.Sspi/Devolutions.Sspi.targets @@ -3,13 +3,15 @@ true true - true + true + true true + @@ -92,8 +94,13 @@ False - - + + + Framework + + + + Framework