diff --git a/bindings/ergo-lib-ios/README.md b/bindings/ergo-lib-ios/README.md index fde525c45..b31658e18 100644 --- a/bindings/ergo-lib-ios/README.md +++ b/bindings/ergo-lib-ios/README.md @@ -1,84 +1,105 @@ -# Swift wrapper for [C bindings](../ergo-lib-c) of ergo-lib. +# Swift wrapper for [C bindings](../ergo-lib-c) of ergo‑lib +## Prerequisites + +- **Xcode 15+** – install via the Mac App Store. +- **Homebrew** – used to install dependencies such as cbindgen. +- **Rust** via [rustup](https://rustup.rs). Use rustup to manage toolchains. ## Build instructions -First build `ergo-lib-c`: +### 1 Build the C library + +First build the base C library, `ergo‑lib‑c`: + ```shell -cargo build --release --features rest --features mnemonic_gen -p ergo-lib-c +# from the project root +cargo build --release --features mnemonic_gen -p ergo-lib-c ``` -adding: -- `--target x86_64-apple-ios` for iPhone simulator on Intel macs, -- `--target aarch64-apple-ios` for iPhone on Apple silicon macs, -- `--target aarch64-apple-ios-sim` for iPhone simulator on Apple silicon macs. -To install a target run `rustup target add ` using triple for target from the list above. +This command produces a static library in `target/release/`. You will need the nightly toolchain for this step because we rely on macros to generate portions of the C bindings; a nightly `rustc` can see through the macros so the compiler is able to expand them before `cbindgen` runs. -This creates a static library under `/target/release`. Next we use `cbindgen` -to generate C-headers. -**Important:** we need a nightly version of `rustc` for this step, as we use macros to generate -*portions of the C-bindings. `cbindgen` can't 'see' through the macros so the nightly compiler is -used to expand the macros before `cbindgen` passes over the code. +Next generate C headers using cbindgen (install it via Homebrew if needed): ```shell -cd bindings/ergo-lib-c +# generate header file for Swift bindings rustup override set nightly cbindgen --config cbindgen.toml --crate ergo-lib-c --output h/ergo_lib.h -rustup override set stable +rustup override unset ``` +### 2 Build the Swift wrapper + +Change into the iOS binding directory and build the Swift wrapper, pointing the linker at the C library: -To build this project we need to point `swift` to this directory for linking. ```shell -cd ../ergo-lib-ios +cd bindings/ergo-lib-ios +# link against the C library built above swift build -Xlinker -L../../target/release/ ``` -To run tests we must also pass in the library directory: +To run the tests you need to pass additional linker flags: + ```shell swift test -Xlinker -L../../target/release/ --skip RestNodeApiTests --skip RestNodeApiIntegrationTests ``` -The `RestNodeApiTests` assume you have an ergo node running on localhost. - -### Building Xcode 13 project for `iPhoneSimulator` +The `RestNodeApiTests` assume that you have an Ergo node running on localhost; skip them if that is not the case. -Make sure `ergo-lib-c` is built as described above. +## Rust iOS targets & build steps -Starting at the root of the `sigma-rust` repository, type: +Before building for iOS, update your toolchain and add the appropriate iOS targets: ```shell -cd bindings/ergo-lib-ios -swift package generate-xcodeproj -xcodebuild -project ./ErgoLib.xcodeproj -xcconfig ./Config/iPhoneSimulator_{arm|intel}.xcconfig -sdk iphonesimulator +rustup update +rustup target add aarch64-apple-ios aarch64-apple-ios-sim ``` -choosing either `arm` or `intel` in the last line depending on your mac's architecture. +Build the library for both the device and the simulator: -Then double click `ErgoLib.xcodeproj` which opens Xcode. You need to manually point the linker towards the directory where the `ergo-lib` static library resides. Refer to the following image: - -![image](xcode_linker_settings.png) +```shell +cargo build --target aarch64-apple-ios --release +cargo build --target aarch64-apple-ios-sim --release +``` -Set `Other Linker Flags` to be `-L/absolute/path/to/sigma-rust/target/release` for x86_64 and ` -L/absolute/path/to/sigma-rust/target/aarch64-apple-ios-sim/release` for simulator on Apple silicon macs. The project can now be built. +These commands will produce `libergo_lib_ios.a` libraries under `target/aarch64-apple-ios/release/` and `target/aarch64-apple-ios-sim/release/`. -### Building Xcode 13 project for `iPhone(iOS)` +## Building an Xcode 15 project for iOS (iPhone & Simulator) -First we need to build an ARM64 target for `ergo-lib-c`: +Make sure `ergo‑lib‑c` and the Swift wrapper are built as described above. Then, from the root of the `sigma‑rust` repository, generate an Xcode project and build it for your desired SDK: ```shell -rustup target add aarch64-apple-ios -cargo build --release --target=aarch64-apple-ios -p ergo-lib-c +# generate the Xcode project +swift package generate-xcodeproj + +# build for the iOS Simulator (choose arm or intel based on your Mac) +xcodebuild -project ./ErgoLib.xcodeproj \ + -xcconfig ./Config/iPhoneSimulator_{arm|intel}.xcconfig \ + -sdk iphonesimulator + +# build for physical devices +xcodebuild -project ./ErgoLib.xcodeproj \ + -xcconfig ./Config/iPhoneOS.xcconfig \ + -sdk iphoneos ``` -Next starting at the root of the `sigma-rust` repository, type: +Open `ErgoLib.xcodeproj` in Xcode. In **Build Settings** set the fields **Base SDK**, **Excluded Architecture** and **Supported Platforms** to the values shown in the accompanying screenshots. Next set **Other Linker Flags** to `-L/absolute/path/to/sigma-rust/target/release` for simulator builds and `-L/absolute/path/to/sigma-rust/aarch64-apple-ios/release` for device builds. + +## Creating an XCFramework & integrating with Swift + +Once both device and simulator libraries are built, you can create an XCFramework that bundles them together. Run the following in the project root (adjust paths as needed): ```shell -cd bindings/ergo-lib-ios -swift package generate-xcodeproj -xcodebuild -project ./ErgoLib.xcodeproj -xcconfig ./Config/iPhoneOS.xcconfig -sdk iphoneos +xcodebuild -create-xcframework \ + -library target/aarch64-apple-ios/release/libergo_lib_ios.a \ + -library target/aarch64-apple-ios-sim/release/libergo_lib_ios.a \ + -output ErgoLib.xcframework ``` -Next navigate in Xcode to `Build Settings` as indicated by 1 and 2 in the picture below. Set the fields `Base SDK`, `Excluded Architecture` and `Supported Platforms` **exactly** as pictured by 3 and 4. -![image](xcode_ios_settings.png) +Drag the generated `ErgoLib.xcframework` into your Xcode project. In your target’s **Frameworks, Libraries, and Embedded Content** section, change the framework’s embed option to **Always Embed**. + +## Troubleshooting -Then set `Other Linker Flags` to be `-L/absolute/path/to/sigma-rust/aarch64-apple-ios/release`. Finally we can build the project. \ No newline at end of file +- **Target not found** – make sure you’ve added the targets using `rustup target add aarch64-apple-ios aarch64-apple-ios-sim`. +- **Linker errors** – verify that the `-L` flags passed to `swift build`, `swift test` or Xcode point to the correct `target/release` directories for the compiled Rust libraries. +- **Missing symbols at runtime** – confirm that you’re embedding the XCFramework in your iOS app target and that the framework is signed correctly.