LoginSignup
0
0

More than 1 year has passed since last update.

複数アーキテクチャ用の xcframework; Rust などで作った静的ライブラリ (*.a) から

Posted at

モチベーション

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.

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0