8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

静的ライブラリをiosアプリとリンクする

Posted at

##はじめに

この記事は「完全に理解したTalk Advent Calendar 2020」17日目の投稿記事です。

これまで、静的ライブラリ、動的ライブラリの説明をし、
動的ライブラリの動的ロードについて説明しました。

このままだと動的ライブラリ万々歳な感じの説明になってしまいますので、
静的ライブラリのもう少し具体的な使い方の説明をしようと思います。

##静的ライブラリ

静的ライブラリについては、こちらで説明をしています。

ふと思いますが、ビルドしたら結局合体して同じバイナリになるから、静的ライブラリはいらないんじゃない?って思いますよね。

ですが、違います。

##静的ライブラリの使い道とは

静的ライブラリは、バイナリですので中身を見てもどんなコードかわかりません。
ですが、リンクすればその機能は使えます。
これがポイントとなります。

ですので、よくある使われ方というのは、
提供されたライブラリを自分で使うとき
ビルドした静的ライブラリを他者に提供するとき
です。

どこかの会社と契約して、「うちのSDKを使っていいよ」と言われて
ようやく提供してもらえるのが静的ライブラリです。(または動的ライブラリの場合もある)

その逆もあり得るわけです。
自分たちが作ったプログラムを他者に使ってもらうために静的ライブラリを提供する。
ソースコードを見せると自分たちのコアな技術も提供することになるため、
ライブラリにして渡すわけです。オープンソースとは違うわけです。

その静的ライブラリというのは、コンパイラに依存します。
x86_64対応のコンパイラでビルドすれば、x86_64でしか使えませんし、
armv7対応のコンパイラでビルドすれば、armv7でしか使えません。

これらのコンパイラを切り替えてビルドすることをクロスコンパイラと言ったりします。

##本題

c++で書いたプログラムを静的ライブラリにして、
xcodeのswiftから呼び出したいと思います。

まずはシミュレータから使えるようにし、
実機からも呼び出せるようにしたいと思います。

静的ライブラリを生成

cmakeの準備

ios用のcmakeビルドツールチェインがこちらにあります。
それを使って、ios用の静的ライブラリを作っていきます。

ファイル配置

├── library.cpp
├── library.hpp
└── CMakeLists.txt
CMakeLists.txt}
project(swiftCallStaticLib)
set(CMAKE_CXX_STANDARD 14)
add_library(swiftCallStaticLib library.cpp library.h)
$mkdir build && cd build
$cmake -G Xcode .. -DCMAKE_TOOLCHAIN_FILE=ios.toolchain.cmake

これを行うと、Xcodeプロジェクトが生成されます。
名前は、cmake記載されたprojectと同じ名前になります。
ここでは、
swiftCallStaticLib.xcodeproj
という名前になります。

Xcodeからライブラリを生成する

それでは、生成されたxcodeprojを開いてみます。
スクリーンショット 2020-12-15 20.42.13(2).png

開くとこんな感じです。
スクリーンショット 2020-12-15 20.42.29(2).png

次にアーキテクチャを追加します。
スクリーンショット 2020-12-15 20.47.26(2).png
ajWZe.png

初期値は、
armv7 armv7s arm64が入っています。
自分のパソコンはx86_64ですので、x86_64を追加します。

スクリーンショット 2020-12-15 20.56.13(2).png

それぞれビルドしたい環境をスキーム、ターゲットを設定してビルドします。
debugにし、simulatorでビルドすると、Debug-iphonesimulatorが出来ます。
また、
debugにし、Any iOS Deviceでビルドすると、Debug-iphoneosが出来ます。

lipoコマンドでそれぞれのライブラリを合体させることが出来ますが、
今回は無しでそのままそのライブラリを使ってみます。

##静的ライブラリをリンクしてみる。

今回は呼び出すところではなく、ビルドが通るところまで確認します。

いつものようにプロジェクトを作ります。
プロジェクトに、先ほど作った
Debug-iphonesimulator内の.aファイルをドラッグドロップします。
これで、リンクされます。

プロジェクトのスキームをシミュレーターにし、ビルドします。
そうすると、ビルドが通るはずです!

では、次に、
Debug-iphoneos内の.aファイルをドラッグドロップします。
このままですと、二つともリンクしていますので、
Debug-iphoneosのライブラリを使うように選択します。
スクリーンショット 2020-12-15 21.54.29.png

写真では、二つのライブラリの名前が同じなので、わかりやすいように名前を分けています。
リンクしないライブラリを選んで、-ボタンを押します。

ビルドすると、x86_64とそのライブラリが合わないのでリンクエラーになると思います。

なので、次はターゲットをAny iOS Deviceにしてみます。
ビルドすると、通るはずです。

以上がc++で作った静的ライブラリのリンク方法となります。

実際にswiftからライブラリを呼び出すには、
.hppファイルをbridgeすることで呼び出せます。

終わりに

c++で作ったライブラリをiOSアプリとリンクができたでしょうか。
コンパイルされてできたバイナリは、そのコンパイラに寄ります。

arm64で最適化されたプログラムは、x86_64では動きませんし、
その逆もそうです。

罠が一つ

iphonesimulator内の.aファイルは、c++のプログラムとリンクできるかを試します。

CMakeLists.txt}
target_link_libraries(testStaticLink swiftCallStaticLib_simulator)

結果は不可です。

cmake error}
libswiftCallStaticLib_simulator.a(library.o), building for macOS, but linking 
in object file built for iOS Simulator, for architecture x86_64

訳すと、

macOS用にビルドしていますが、アーキテクチャx86_64用のiOSシミュレータ用にビルドされたオブジェクトファイルにリンクしています

シミュレータ用のビルドになっているので、リンクが不可ということになります。
c++で使いたい場合は、

CMakeLists.txt}
add_library()

で作るしかありません。

参考URL

8
10
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
8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?