モチベーション

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 tripleRust Target TieriOSaarch64-apple-ios2iOS シミュレータ (x86_64)x86_64-apple-ios ⚠️2iOS シミュレータ (aarch64)aarch64-apple-ios-sim2Mac (x86_64)x86_64-apple-darwin1 with Host ToolsMac (aarch64)aarch64-apple-darwin2 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.

参考

 

广告
将在 10 秒后关闭
bannerAds