From 043c54f6e0ef051a54689b918d980154b7957205 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Wed, 14 Feb 2024 12:30:20 +0100 Subject: [PATCH] trying to build --- .gitignore | 1 + BuildProcess.md | 23 +++++++++++ Package.resolved | 59 +++++++++++++++++++++++++++ Package.swift | 51 +++++++++++++++++++++++ README.md | 3 +- apple/Sources/UniFFI/.gitkeep | 0 scripts/build-ios.sh | 76 +++++++++++++++++++++++++++++++++++ 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 BuildProcess.md create mode 100644 Package.resolved create mode 100644 Package.swift create mode 100644 apple/Sources/UniFFI/.gitkeep create mode 100755 scripts/build-ios.sh diff --git a/.gitignore b/.gitignore index 2043019b0..c91726190 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ tarpaulin-report.html .vscode .idea +.build build_rs_cov.profraw cobertura.xml jna-*.jar \ No newline at end of file diff --git a/BuildProcess.md b/BuildProcess.md new file mode 100644 index 000000000..65954093d --- /dev/null +++ b/BuildProcess.md @@ -0,0 +1,23 @@ +# Swift + +## Build script +Ah nevermind the build script in [uniffi-starter/../build-ios.sh](https://github.com/ianthetechie/uniffi-starter/blob/main/rust/build-ios.sh) already contained code to update checksum. + +[Blog post about automating checksum update in Package.swift](https://blog.eidinger.info/distribute-binary-frameworks-in-swift-packages-and-how-to-automate-the-process) and here is a [Github Gist which looks nice](https://gist.github.com/litoarias/23bca22bb6161625484b4fb8cd245fe8) + +This would allow for us to use a similar pattern like [`ferrostar`'s `Package.swift`](https://github.com/stadiamaps/ferrostar/blob/main/Package.swift) which has a nice `useLocalFramework` setup, and when NOT local uses SPM's setup: + +```swift +let releaseTag = "0.1.0" +let releaseChecksum = "deadbeefdeadbeef..." +.binaryTarget( + name: "SargonCoreRS", + url: "https://github.com/radixdlt/sargon/releases/download/\(releaseTag)/libsargon-rs.xcframework.zip", + checksum: releaseChecksum +) +``` + +The advantage of this over what we are [doing today in Swift-Engine-Toolkit](https://github.com/radixdlt/swift-engine-toolkit/blob/main/Package.swift#L23C3-L23C78) is that the .xcframework files need not be part of Git! They can be put in Github! This will allow for much much faster git clone! + +# Android +[See `uniffi-starter`](https://github.com/ianthetechie/uniffi-starter) (also contains Swift, but `@IanTheTech` has also created `ferrostar` which contains more advanced Swift setup). \ No newline at end of file diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 000000000..d30c58fe1 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,59 @@ +{ + "pins" : [ + { + "identity" : "maplibre-gl-native-distribution", + "kind" : "remoteSourceControl", + "location" : "https://github.com/maplibre/maplibre-gl-native-distribution.git", + "state" : { + "revision" : "3df876f8f2c6c591b0f66a29b3e216020afc885c", + "version" : "6.0.0" + } + }, + { + "identity" : "maplibre-swift-macros", + "kind" : "remoteSourceControl", + "location" : "https://github.com/stadiamaps/maplibre-swift-macros.git", + "state" : { + "branch" : "main", + "revision" : "b8deecb8adc3b911de311ead5a13b98fbf2d7824" + } + }, + { + "identity" : "maplibre-swiftui-dsl-playground", + "kind" : "remoteSourceControl", + "location" : "https://github.com/stadiamaps/maplibre-swiftui-dsl-playground", + "state" : { + "branch" : "main", + "revision" : "34724f761dc026a73951f3fa29f48ae2b48e9b5d" + } + }, + { + "identity" : "mockable", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kolos65/Mockable.git", + "state" : { + "revision" : "7af00c08880d375f2742ca55705abd69837fe6c3", + "version" : "0.0.2" + } + }, + { + "identity" : "swift-snapshot-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-snapshot-testing", + "state" : { + "revision" : "e7b77228b34057041374ebef00c0fd7739d71a2b", + "version" : "1.15.3" + } + }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-syntax.git", + "state" : { + "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", + "version" : "509.1.1" + } + } + ], + "version" : 2 +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 000000000..66bf075f3 --- /dev/null +++ b/Package.swift @@ -0,0 +1,51 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let binaryTarget: Target +let useLocalFramework = false + +if useLocalFramework { + binaryTarget = .binaryTarget( + name: "SargonCoreRS", + // IMPORTANT: Swift packages importing this locally will not be able to + // import SargonCore unless you specify this as a relative path! + path: "./common/target/ios/libsargon-rs.xcframework" + ) +} else { + let releaseTag = "0.1.0" + let releaseChecksum = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + .binaryTarget( + name: "SargonCoreRS", + url: + "https://github.com/radixdlt/sargon/releases/download/\(releaseTag)/libsargon-rs.xcframework.zip", + checksum: releaseChecksum + ) +} + +let package = Package( + name: "Sargon", + platforms: [ + .iOS(.v15) + ], + products: [ + .library( + name: "Sargon", + targets: ["Sargon"] + ) + ], + targets: [ + binaryTarget, + .target( + name: "FerrostarCore", + dependencies: [.target(name: "UniFFI")], + path: "apple/Sources/FerrostarCore" + ), + .target( + name: "UniFFI", + dependencies: [.target(name: "FerrostarCoreRS")], + path: "apple/Sources/UniFFI" + ), + ] +) diff --git a/README.md b/README.md index 2418ae4b8..10d6a65fb 100644 --- a/README.md +++ b/README.md @@ -214,4 +214,5 @@ cargo tarpaulin --out Html ```sh cargo nextest run -``` \ No newline at end of file +``` + diff --git a/apple/Sources/UniFFI/.gitkeep b/apple/Sources/UniFFI/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh new file mode 100755 index 000000000..60286d980 --- /dev/null +++ b/scripts/build-ios.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env zsh + +set -e +set -u + +# Credits: https://github.com/ianthetechie/uniffi-starter/blob/main/rust/build-ios.sh +# NOTE: You MUST run this every time you make changes to the core. Unfortunately, calling this from Xcode directly +# does not work so well. + +# In release mode, we create a ZIP archive of the xcframework and update Package.swift with the computed checksum. +# This is only needed when cutting a new release, not for local development. +release=false + +for arg in "$@" +do + case $arg in + --release) + release=true + shift # Remove --release from processing + ;; + *) + shift # Ignore other argument from processing + ;; + esac +done + + +# Potential optimizations for the future: +# regularly check: https://github.com/ianthetechie/uniffi-starter/blob/main/rust/build-ios.sh +# for improvements! +# +# * Only build one simulator arch for local development (we build both since many still use Intel Macs) +# * Option to do debug builds instead for local development +fat_simulator_lib_dir="target/ios-simulator-fat/release" + +generate_ffi() { + echo "Generating framework module mapping and FFI bindings" + cargo run -p uniffi-bindgen generate --library target/aarch64-apple-ios/release/lib$1.dylib --language swift --out-dir target/uniffi-xcframework-staging + mkdir -p ../apple/Sources/UniFFI/ + mv target/uniffi-xcframework-staging/*.swift ../apple/Sources/UniFFI/ + mv target/uniffi-xcframework-staging/$1FFI.modulemap target/uniffi-xcframework-staging/module.modulemap # Convention requires this have a specific name +} + +create_fat_simulator_lib() { + echo "Creating a fat library for x86_64 and aarch64 simulators" + mkdir -p $fat_simulator_lib_dir + lipo -create target/x86_64-apple-ios/release/lib$1.a target/aarch64-apple-ios-sim/release/lib$1.a -output $fat_simulator_lib_dir/lib$1.a +} + +build_xcframework() { + # Builds an XCFramework + echo "Generating XCFramework" + rm -rf target/ios # Delete the output folder so we can regenerate it + xcodebuild -create-xcframework \ + -library target/aarch64-apple-ios/release/lib$1.a -headers target/uniffi-xcframework-staging \ + -library target/ios-simulator-fat/release/lib$1.a -headers target/uniffi-xcframework-staging \ + -output target/ios/lib$1-rs.xcframework + + if $release; then + echo "Building xcframework archive" + zip -r target/ios/lib$1-rs.xcframework.zip target/ios/lib$1-rs.xcframework + checksum=$(swift package compute-checksum target/ios/lib$1-rs.xcframework.zip) + version=$(cargo metadata --format-version 1 | jq -r '.packages[] | select(.name=="sargon") .version') + sed -i "" -E "s/(let releaseTag = \")[^\"]+(\")/\1$version\2/g" ../Package.swift + sed -i "" -E "s/(let releaseChecksum = \")[^\"]+(\")/\1$checksum\2/g" ../Package.swift + fi +} + +cargo build --lib --release --target x86_64-apple-ios +cargo build --lib --release --target aarch64-apple-ios-sim +cargo build --lib --release --target aarch64-apple-ios + +basename=sargon +generate_ffi $basename +create_fat_simulator_lib $basename +build_xcframework $basename \ No newline at end of file