Files

120 lines
4.6 KiB
Markdown

# Monero native library for iOS
The wallet runs monero-project `wallet2` (plus monero-cpp as the C++ API) on
device. Everything is compiled into a single static archive that the app links.
## Artifacts
| File | Architecture | Platform |
|---|---|---|
| `libs/libkoins_monero_merged.a` | arm64 | iOS simulator |
| `libs/libkoins_monero_device.a` | arm64 | iOS device |
Both are needed: they are the same CPU architecture but different platforms, so
they cannot be merged into one fat archive. `project.yml` selects the right one
per SDK.
## Prerequisites
- Xcode with the iOS device and simulator SDKs
- CMake 3.2x (monero 0.18 is not tested with CMake 4)
- GNU make (the builds use the "Unix Makefiles" generator)
- Roughly 10 GB of disk and a long coffee break
## Sources
- monero-project v0.18.5.1
- monero-cpp (woodser), which keeps monero-project at `external/monero-project`
## Toolchain customisations
The files under `depends/` are the ones modified from upstream, kept here so the
archive can be regenerated:
| File | Change |
|---|---|
| `depends/hosts/ios.mk` | new host; `IOS_PLATFORM=SIMULATOR` (default) or `DEVICE` selects the SDK and the target triple (`aarch64-apple-ios[-simulator]`) |
| `depends/packages/packages.mk` | `ios_packages := boost openssl zeromq expat unbound sodium` (no libiconv) |
| `depends/packages/boost.mk` | boost for the `ios` toolset: darwin toolset, libtool archiver, c++11, no b2 python |
| `depends/packages/zeromq.mk` | ios config opts (`--host=aarch64-apple-darwin`), no libsodium, no curve |
| `depends/packages/unbound.mk` | drops the autoconf dependency |
| `depends/packages/sodium.mk` | drops the autoconf dependency |
| `depends/funcs.mk` | create the prefix `lib` directory before extracting dependency archives |
One source change is also required, in monero-project:
- `src/cryptonote_basic/miner.cpp` — wrap the IOKit includes and the related
code with `defined(TARGET_OS_OSX) && TARGET_OS_OSX`; IOKit is unavailable on
iOS. Two locations, around lines 51 and 986.
Two more steps are needed when targeting a device:
- Copy monero's patched boost serialisation headers into the dependency prefix,
because monero's build otherwise only finds them for the platform it was
installed for:
```sh
cp external/boost/archive/portable_binary_*.hpp \
contrib/depends/$HOST/include/boost/archive/
```
- randomx's AArch64 JIT references `__clear_cache`, which libSystem exports on
macOS and the simulator but not on iOS. The app supplies it in
`Koins/Support/ClearCache.c`.
## Build
Set `PLATFORM` to `SIMULATOR` or `DEVICE`; the only differences are the depends
host flag and the output archive name.
```sh
MONERO=/path/to/monero-project
PLATFORM=SIMULATOR # or DEVICE
HOST=aarch64-apple-ios
# 1. Cross-compiled dependencies (boost, openssl, zeromq, expat, unbound, sodium)
cd "$MONERO/contrib/depends"
make HOST=$HOST IOS_PLATFORM=$PLATFORM -j"$(sysctl -n hw.ncpu)"
# 2. monero-project, static wallet library
cd "$MONERO"
mkdir -p build/ios-$PLATFORM && cd build/ios-$PLATFORM
cmake -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE="$MONERO/contrib/depends/$HOST/share/toolchain.cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DSTATIC=ON -DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTS=OFF -DBUILD_DOCUMENTATION=OFF -DUSE_DEVICE_TREZOR=OFF \
../..
make -j"$(sysctl -n hw.ncpu)" wallet # produces lib/libwallet.a
# 3. monero-cpp
cd /path/to/monero-cpp
mkdir -p build-ios-$PLATFORM && cd build-ios-$PLATFORM
cmake -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE="$MONERO/contrib/depends/$HOST/share/toolchain.cmake" \
../..
make -j"$(sysctl -n hw.ncpu)" # produces libmonero-cpp.a
# 4. Merge into one archive for the app
libtool -static -o libkoins_monero_merged.a \
libmonero-cpp.a \
"$MONERO/build/ios-$PLATFORM/lib/libwallet.a" \
"$MONERO/build/ios-$PLATFORM"/src/*/lib*.a \
"$MONERO/build/ios-$PLATFORM"/external/*/lib*.a \
"$MONERO/build/ios-$PLATFORM"/contrib/epee/src/libepee.a \
"$MONERO/contrib/depends/$HOST"/lib/lib*.a
```
Copy the result to `libs/`, using `libkoins_monero_merged.a` for the simulator
and `libkoins_monero_device.a` for the device.
## Notes
- Only the simulator archive is needed to run in the simulator; the device
archive is needed for a real iPhone, and Xcode requires the matching one at
link time.
- Building the device slice after a simulator build requires moving the
simulator depends prefix aside first, since depends installs into
`contrib/depends/<host>` and both platforms share the host name.
- The app also links the OpenSSL that is embedded in this archive, which is how
the XRP wallet gets secp256k1 without an extra dependency.