Skip to content

Commit

Permalink
Merge pull request #388 from nerdcash/lib_apple_fixes
Browse files Browse the repository at this point in the history
Get Nerdbank.Zcash working for store submissions of iOS apps
  • Loading branch information
AArnott authored Sep 29, 2024
2 parents 960ec34 + 1a0f7da commit 31eb9d3
Show file tree
Hide file tree
Showing 17 changed files with 3,585 additions and 38 deletions.
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<RoslynVersion>3.11.0-beta1.24104.1</RoslynVersion>
<RoslynVersion>3.11.0-beta1.24415.1</RoslynVersion>
<AspNetWebAssemblyVersion>8.0.7</AspNetWebAssemblyVersion>
</PropertyGroup>
<ItemGroup>
Expand All @@ -22,7 +22,7 @@
<PackageVersion Include="Microsoft.VisualStudio.Threading" Version="17.10.48" />
<PackageVersion Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
<PackageVersion Include="NBitcoin.Secp256k1" Version="3.1.5" />
<PackageVersion Include="Nerdbank.QRCodes" Version="0.2.50-beta" />
<PackageVersion Include="Nerdbank.QRCodes" Version="0.2.61" />
<PackageVersion Include="QRCoder" Version="1.6.0" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
Expand Down
5 changes: 3 additions & 2 deletions azure-pipelines/Get-RustTargets.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ if ($IsLinux) {
elseif ($IsMacOS) {
,'aarch64-apple-darwin'
,'x86_64-apple-darwin'
,'aarch64-apple-ios'
,'x86_64-apple-ios'
,'aarch64-apple-ios' # device
,'x86_64-apple-ios' # simulator
,'aarch64-apple-ios-sim' # simulator
}
else { # Windows
,'aarch64-pc-windows-msvc'
Expand Down
28 changes: 28 additions & 0 deletions azure-pipelines/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>nerdbank_zcash_rust</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>net.nerdbank.zcash</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$version$</string>
<key>CFBundleShortVersionString</key>
<string>$version$</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>MinimumOSVersion</key>
<string>17.5</string>
</dict>
</plist>
14 changes: 14 additions & 0 deletions azure-pipelines/artifacts/ios_framework.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
$BuildConfiguration = $env:BUILDCONFIGURATION
if (!$BuildConfiguration) {
$BuildConfiguration = 'Debug'
}

$BuildConfiguration = $BuildConfiguration.ToLower()
$FrameworkRoot = "$RepoRoot/bin/$BuildConfiguration/nerdbank_zcash_rust.xcframework"

if (!(Test-Path $FrameworkRoot)) { return }

@{
"$FrameworkRoot" = (Get-ChildItem $FrameworkRoot -Recurse)
}
5 changes: 5 additions & 0 deletions azure-pipelines/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ jobs:
parameters:
test_target: x86_64-apple-darwin

- pwsh: |
Write-Host "##[command]./azure-pipelines/build_ios_framework.ps1"
./azure-pipelines/build_ios_framework.ps1
displayName: 📱 iOS Framework
- template: dotnet.yml
parameters:
RunTests: ${{ parameters.RunTests }}
Expand Down
60 changes: 60 additions & 0 deletions azure-pipelines/build_ios_framework.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[CmdletBinding()]
param (
[parameter()]
[string]$Configuration = 'release'
)

$repoRoot = Resolve-Path "$PSScriptRoot/.."
$version = dotnet nbgv get-version -p $repoRoot/src/nerdbank-zcash-rust -v SimpleVersion
$plist = Get-Content $PSScriptRoot/Info.plist
$plist = $plist.Replace('$version$', $version)
$IntermediatePlistPath = "$repoRoot/obj/Info.plist"
Set-Content -Path $IntermediatePlistPath -Value $plist -Encoding utf8NoBOM
if ($IsMacOS) {
plutil -convert binary1 $IntermediatePlistPath
chmod +x $IntermediatePlistPath
}
else {
Write-Warning "Skipped plutil invocation because this is not macOS."
}

# copy Info.plist and the binary into the appropriate .framework directory structure
# so that when NativeBindings.targets references it with ResolvedFileToPublish, it will be treated appropriately.
$RustTargetBaseDir = "$repoRoot/src/nerdbank-zcash-rust/target"
$RustDylibFileName = "libnerdbank_zcash_rust.dylib"
$DeviceRustOutput = "$RustTargetBaseDir/aarch64-apple-ios/$Configuration/$RustDylibFileName"
$SimulatorX64RustOutput = "$RustTargetBaseDir/x86_64-apple-ios/$Configuration/$RustDylibFileName"
$SimulatorArm64RustOutput = "$RustTargetBaseDir/aarch64-apple-ios-sim/$Configuration/$RustDylibFileName"

$DeviceFrameworkDir = "$repoRoot/bin/$Configuration/device/nerdbank_zcash_rust.framework"
$SimulatorFrameworkDir = "$repoRoot/bin/$Configuration/simulator/nerdbank_zcash_rust.framework"
New-Item -Path $DeviceFrameworkDir,$SimulatorFrameworkDir -ItemType Directory -Force | Out-Null

Write-Host "Preparing Apple iOS and iOS-simulator frameworks"

Copy-Item $IntermediatePlistPath "$DeviceFrameworkDir/Info.plist"
Copy-Item $IntermediatePlistPath "$SimulatorFrameworkDir/Info.plist"
Write-Host "Created Info.plist with version $version"

if ($IsMacOS) {
# Rename the binary that contains the arm64 architecture for device.
lipo -create -output $DeviceFrameworkDir/nerdbank_zcash_rust $DeviceRustOutput
install_name_tool -id "@rpath/nerdbank_zcash_rust.framework/nerdbank_zcash_rust" "$DeviceFrameworkDir/nerdbank_zcash_rust"
chmod +x "$DeviceFrameworkDir/nerdbank_zcash_rust"

# Create a universal binary that contains both arm64 and x64 architectures for simulator.
lipo -create -output $SimulatorFrameworkDir/nerdbank_zcash_rust $SimulatorX64RustOutput $SimulatorArm64RustOutput
install_name_tool -id "@rpath/nerdbank_zcash_rust.framework/nerdbank_zcash_rust" "$SimulatorFrameworkDir/nerdbank_zcash_rust"
chmod +x "$SimulatorFrameworkDir/nerdbank_zcash_rust"
}
else {
Copy-Item $SimulatorArm64RustOutput "$SimulatorArm64RustOutput/nerdbank_zcash_rust"
Copy-Item $DeviceRustOutput "$DeviceFrameworkDir/nerdbank_zcash_rust"
Write-Warning "Skipped critical steps because this is not macOS."
}
Write-Host "Copied nerdbank_zcash_rust to framework"

# Build the xcframework
$xcframeworkOutputDir = "$repoRoot/bin/$Configuration/nerdbank_zcash_rust.xcframework"
xcodebuild -create-xcframework -framework $SimulatorFrameworkDir -framework $DeviceFrameworkDir -output $xcframeworkOutputDir
Write-Host "Created nerdbank_zcash_rust.xcframework at $xcframeworkOutputDir"
5 changes: 4 additions & 1 deletion azure-pipelines/cargo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ steps:
# path: $(HOME)/.cargo/registry
# displayName: cache cargo registry

- pwsh: src/nerdbank-zcash-rust/build_all.ps1 -Release
- pwsh: src/nerdbank-zcash-rust/generate_cs_bindings.ps1 -InstallPrerequisites
displayName: 🛠️ generate C# bindings

- pwsh: src/nerdbank-zcash-rust/build_all.ps1 -Release -SkipCsBindings
displayName: 🛠️ cargo build

- pwsh: cargo test -r --target ${{ parameters.test_target }}
Expand Down
12 changes: 12 additions & 0 deletions azure-pipelines/manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<BindingAssembly>
<NativeReference Name="nerdbank_zcash_rust.xcframework">
<ForceLoad></ForceLoad>
<Frameworks></Frameworks>
<IsCxx></IsCxx>
<Kind>Framework</Kind>
<LinkerFlags></LinkerFlags>
<NeedsGccExceptionHandling></NeedsGccExceptionHandling>
<SmartLink></SmartLink>
<WeakFrameworks></WeakFrameworks>
</NativeReference>
</BindingAssembly>
6 changes: 6 additions & 0 deletions azure-pipelines/pack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ steps:
buildType: current
targetPath: src/nerdbank-zcash-rust/target
artifactName: rust-macOS
- task: DownloadPipelineArtifact@2
displayName: 🔻 Download ios_framework binaries
inputs:
buildType: current
targetPath: bin/release/nerdbank_zcash_rust.xcframework
artifactName: ios_framework-macOS

- pwsh: src/nerdbank-zcash-rust/Generate-3rdPartyNotices.ps1
displayName: 🪪 3rd party licenses
Expand Down
9 changes: 0 additions & 9 deletions nuget.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,9 @@
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
</packageSources>
<disabledPackageSources>
<!-- Defend against user or machine level disabling of sources that we list in this file. -->
<clear />
</disabledPackageSources>
<packageSourceMapping>
<packageSource key="nuget">
<package pattern="*" />
</packageSource>
<packageSource key="dotnet9">
<package pattern="Microsoft.CodeAnalysis.*" />
</packageSource>
</packageSourceMapping>
</configuration>
30 changes: 12 additions & 18 deletions src/Nerdbank.Zcash/NativeBindings.targets
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
<RustOutputAndroidArm64>$(RustOutputDirBase)aarch64-linux-android/$(RustConfiguration)/libnerdbank_zcash_rust.so</RustOutputAndroidArm64>
<RustOutputAndroidX64>$(RustOutputDirBase)x86_64-linux-android/$(RustConfiguration)/libnerdbank_zcash_rust.so</RustOutputAndroidX64>

<RustOutputiOSArm64>$(RustOutputDirBase)aarch64-apple-ios/$(RustConfiguration)/libnerdbank_zcash_rust.dylib</RustOutputiOSArm64>
<RustOutputiOSX64>$(RustOutputDirBase)x86_64-apple-ios/$(RustConfiguration)/libnerdbank_zcash_rust.dylib</RustOutputiOSX64>
<iOSFrameworkName>nerdbank_zcash_rust.xcframework</iOSFrameworkName>
<iOSFrameworkPath>$(RepoRootPath)bin/$(RustConfiguration)/$(iOSFrameworkName)</iOSFrameworkPath>
</PropertyGroup>
<PropertyGroup Condition="'$(IsMobileAppProject)'!='true'">
<IncludeWindowsBinaries Condition="$([MSBuild]::IsOsPlatform('Windows'))">true</IncludeWindowsBinaries>
Expand Down Expand Up @@ -76,11 +76,14 @@
</RustBinary>

<!-- iOS -->
<RustBinary Condition="'$(IsPackable)'=='true' or ('$(PlatformTarget)'=='arm64' and '$(IncludeiOSBinaries)'=='true')" Include="$(RustOutputiOSArm64)">
<PackagePath>runtimes/ios-arm64/native/</PackagePath>
<!-- The '$(BuildingInsideVisualStudio)'!='true' condition is a workaround because CPS fails to load the project when this item exists. -->
<RustBinary Condition="'$(BuildingInsideVisualStudio)'!='true' and ('$(IsPackable)'=='true' or '$(IncludeiOSBinaries)'=='true')" Include="$(iOSFrameworkPath)/**">
<PackagePath>lib/net8.0-ios17.0/Nerdbank.Zcash.resources/$(iOSFrameworkName)/</PackagePath>
<Visible>false</Visible>
</RustBinary>
<RustBinary Condition="'$(IsPackable)'=='true' or ('$(PlatformTarget)'=='x64' and '$(IncludeiOSBinaries)'=='true')" Include="$(RustOutputiOSX64)">
<PackagePath>runtimes/ios-x64/native/</PackagePath>
<RustBinary Condition="'$(IsPackable)'=='true' or '$(IncludeiOSBinaries)'=='true'" Include="$(RepoRootPath)/azure-pipelines/manifest">
<PackagePath>lib/net8.0-ios17.0/Nerdbank.Zcash.resources/</PackagePath>
<Visible>false</Visible>
</RustBinary>
</ItemGroup>
<ItemGroup>
Expand All @@ -100,18 +103,9 @@
</None>
</ItemGroup>
<ItemGroup Condition="'$(IncludeiOSBinaries)'=='true'">
<NativeCopyLocalItems Include="@(RustBinary)">
<AssetType>native</AssetType>
</NativeCopyLocalItems>
</ItemGroup>
<!-- We only expect the iOS native library to be present if we're on a Mac or we're in a local dev environment where they were copied locally. -->
<ItemGroup Condition="'$(IncludeiOSBinaries)'=='true' and ('$(CI)'!='true' or $([MSBuild]::IsOsPlatform('OSX')))">
<None Include="$(RustOutputiOSArm64)" Condition="'$(PlatformTarget)'=='arm64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(RustOutputiOSX64)" Condition="'$(PlatformTarget)'=='x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<NativeReference Include="$(iOSFrameworkPath)">
<Kind>Framework</Kind>
</NativeReference>
</ItemGroup>
<ItemGroup Condition="'$(IncludeAndroidBinaries)'=='true'">
<AndroidNativeLibrary Include="$(RustOutputAndroidArm64)" Abi="arm64-v8a" />
Expand Down
5 changes: 5 additions & 0 deletions src/Nerdbank.Zcash/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
/// </summary>
internal static unsafe partial class NativeMethods
{
#if IOS
// https://github.com/xamarin/xamarin-macios/issues/21238
private const string LibraryName = "@rpath/nerdbank_zcash_rust.framework/nerdbank_zcash_rust";
#else
private const string LibraryName = "nerdbank_zcash_rust";
#endif

/// <summary>
/// Passes a byte buffer through the Orchard ToScalar method in the spec.
Expand Down
4 changes: 3 additions & 1 deletion src/Nerdbank.Zcash/Nerdbank.Zcash.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks Condition="!$([MSBuild]::IsOsPlatform('Linux'))">$(TargetFrameworks);net8.0-ios</TargetFrameworks>
<TargetFrameworks Condition="!$([MSBuild]::IsOsPlatform('Linux'))">$(TargetFrameworks);net8.0-ios17.0</TargetFrameworks>
<DefineConstants>$(DefineConstants);ZCASH</DefineConstants>
<Description>A .NET library for Zcash, capable of creating accounts, deriving addresses, interacting with lightwallet servers, syncing, and sending transactions.</Description>
</PropertyGroup>
Expand All @@ -14,6 +14,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedSource\**\*.cs" LinkBase="SharedSource" />
<Compile Remove="RustBindings\LightWallet.cs" Condition="'$(TargetFramework)'=='net8.0-ios17.0'"/>
<Compile Remove="RustBindings\LightWallet.iOS.cs" Condition="'$(TargetFramework)'!='net8.0-ios17.0'"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" PrivateAssets="compile" />
Expand Down
Loading

0 comments on commit 31eb9d3

Please sign in to comment.