モチベーション
Rust で作った静的ライブラリ(*.a)を, Xcode でビルドしている iOS(/Mac) アプリにリンクして使用したい.
それぞれのプラットフォーム/アーキテクチャ向けにビルドした複数の *.a (とヘッダファイル) を,
1つの xcframework にバンドルする.
ポイント
iOS シミュレータ(や Mac) については, 動作ターゲットが
- x86_64 な Intel Mac
- aarch64(ARM64) な M1/M2 Mac
のどちらでも使えるように, x86_64 と aarch64 向けの両方を用意したい.
Rust ? 🤔
Apple の複数プラットフォーム, アーキテクチャについてビルド済みの静的ライブラリ(*.a)をバンドルしたい, といった需要があるならば, Rust に限った議論ではない.
Rust ビルドターゲットの整理
Apple の各プラットフォーム, アーキテクチャについて, Rust の target triple をまとめておく.
Target Tier は 2022/11 現在の nightly のもの.
プラットフォーム, アーキテクチャ | Rust target triple | Rust Target Tier |
---|---|---|
iOS | aarch64-apple-ios | 2 |
iOS シミュレータ (x86_64) | x86_64-apple-ios ⚠️ | 2 |
iOS シミュレータ (aarch64) | aarch64-apple-ios-sim | 2 |
Mac (x86_64) | x86_64-apple-darwin | 1 with Host Tools |
Mac (aarch64) | aarch64-apple-darwin | 2 with Host Tools |
iOS シミュレータの target triple について, x86_64 には接尾辞 -sim が付かないことに注意.
(x86 の iOS デバイスはないので自明ということか)
手順
crate-type=["staticlib"]
な crate を通常の手順で iOS と iOS シミュレータ向けにビルドする:
cargo build --target aarch64-apple-ios
cargo build --target x86_64-apple-ios
cargo build --target aarch64-apple-ios-sim
単純にこれらの静的ライブラリから xcframework の生成を試みると:
# aarch64-apple-ios
# x86_64-apple-ios
# aarch64-apple-ios-sim
xcodebuild -create-xcframework \
-library target/aarch64-apple-ios/debug/libxxx.a \
-headers path/to/headers \
-library target/x86_64-apple-ios/debug/libxxx.a \
-headers path/to/headers \
-library target/aarch64-apple-ios-sim/debug/libxxx.a \
-headers path/to/headers \
-output libxxx.xcframework
以下のエラーメッセージが出力される:
Both ios-arm64-simulator and ios-x86_64-simulator represent two equivalent library definitions.
iOS シミュレータについて, arm64 と x86_64 のバイナリが重複している旨.
"library definition" は "target platform" くらいに読み替えてよいらしく,
1つのプラットフォーム(ここでは iOS シミュレータ) には1つの -library
指定しかあってはならないらしい.
解決策
同一プラットフォームの異なるアーキテクチャについては, fatバイナリにまとめておく必要がある.
ここでは iOS シミュレータ用の2つのアーキテクチャ(x86_64-apple-ios, aarch64-apple-ios-sim)について行う:
# libxxx_iossim.a := x86_64-apple-ios + aarch64-apple-ios-sim
lipo -create \
-output libxxx_iossim.a \
target/x86_64-apple-ios/debug/libxxx.a \
target/aarch64-apple-ios-sim/debug/libxxx.a
fatバイナリを用いてもう1度 xcframework の生成を行うと成功するはず:
# Thin: aarch64-apple-ios
# Fat: libxxx_iossim.a (= x86_64-apple-ios + aarch64-apple-ios-sim)
xcodebuild -create-xcframework \
-library target/aarch64-apple-ios/debug/libxxx.a \
-headers path/to/headers \
-library libxxx_iossim.a \
-headers path/to/headers \
-output libxxx.xcframework
もちろん Mac 用にもビルドしている際にはその x86_64 と aarch64 もまとめてfatバイナリにする必要があるはず.
(x86_64-apple-darwin + aarch64-apple-darwin)
さもなくば次のようなエラーメッセージに繋がると思われる:
Both ios-arm64-maccatalyst and ios-x86_64-maccatalyst represent two equivalent library definitions.
参考