# 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/` 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.