Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 63 additions & 42 deletions bindings/ergo-lib-ios/README.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,105 @@
# Swift wrapper for [C bindings](../ergo-lib-c) of ergo-lib.
# Swift wrapper for [C bindings](../ergo-lib-c) of ergolib

## 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 <target>` 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 `<project_root_directory>/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.
- **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.
Loading