LoginSignup
58
58

More than 5 years have passed since last update.

iOSネイティブアプリでwebRTCを使うために、ライブラリのビルドをしやすくした

Posted at

WebRTCはウェブサイト用、ブラウザ用のAPIですが、
P2P通信による動画、音声通信APIですから、
ウェブサイト上に限らず、原理上ネイティブアプリからも使用できます。

ありがたいことに、WebRTC本家がネイティブアプリ向けのC++のライブラリを提供してくれています。

クロスプラットフォームで提供されているのですが、
iOSでの利用という意味では、若干の不便が残る状態になっています。

ほしいもの

簡単な手順でiOSアプリプロジェクトに、WebRTCライブラリを入れられるようにしたい。

現状の問題点

ビルド結果として、iOS実機用のarmv7、arm64、シミュレーター用のi386、x86_64向けのスタティックライブラリがバラバラに生成される。
Xcode開発では、複数アーキテクチャのライブラリをひとまとめにしたfatバイナリ形式のほうが取り扱いやすい。

armv7だけ出力されるライブラリや、i386だけ出力されるライブラリなどがあり、
一貫して4つアーキテクチャ入りのfatバイナリにできない。
アーキテクチャのかけたfatバイナリをXcodeに突っ込むと、ビルド時に警告が出てしまう。

ヘッダーのツリーが整理されておらず、アプリのプロジェクトに突っ込みにくい。

Bitcode Embeddingに対応していない。
AppleはBitcode対応を推奨しており、iOSアプリでも今後必須化される可能性があるので、
ライブラリもできるだけBitcode対応のものを使いたい。

やったこと

ヘッダーを含むincludeディレクトリと、
スタティックライブラリを含むlibディレクトリを生成するスクリプトをRubyで作った。

スタティックライブラリは、もしもともと特定アーキテクチャ専用であっても、
必ず4つのアーキテクチャを含むfatバイナリを生成するようにした。

Bitcode Embeddingの有効、無効どちらかを選択してビルドできるようにした。

使い方

まず、WebRTCのソースを、こちらの手順にしたがってダウンロードします。

以降では、~/webrtc-iosにダウンロードしたという仮定で説明します。

次に、僕のスクリプトをgithubから取得します。

以降では、~/webrtc-ios-buildにダウンロードしたという仮定で説明します。

スクリプトのリポジトリに移動します。

cd ~/webrtc-ios-build

スクリプトを実行します。

./webrtc-ios-build.rb --webrtc ~/webrtc-ios

~/webrtc-ios-build/includeにヘッダが出力されます。
~/webrtc-ios-build/libにライブラリが出力されます。

Xcodeプロジェクトに突っ込むときは、
includeはXcodeのプロジェクトに入れる必要はありません。
Build Settings > Header Search Pathsincludeを追加します。
Objective-Cのライブラリも使いたいときはinclude/talk/app/webrtc/objc/publicも追加します。

ライブラリは、libディレクトリごとプロジェクトに追加し、
General > Linked Frameworks And Librariesおよび、
Build Phases > Link Binary With Librariesに登録します。
加えて、Build Settings > Librari Search Pathslibを追加します。

あとは普通にアプリを作ります。

Bitcode

bitcodeを無効化する場合、スクリプトに--disable-bitcodeを指定します。

サンプル

サンプルとして、GoogleのAppRTCDemoのソースと、
このツールで生成したライブラリを突っ込んで、
ビルドできるようにしたものを、
examples/AppRTCDemoに入れてあります。

iPhoneとPC(PCはウェブ版)でビデオチャットできます。

やったこと詳細

ビルドスクリプトはRubyで実装しました。

おおまかな流れは、WebRTCのビルドを、4つのアーキテクチャで実行した後、
それを結合するというものです。

その他いくつかの手間がかかりました。

特定アーキテクチャ用のライブラリのfat化

arm専用のコードや、intel CPU専用のコードは、
そのアーキテクチャのスタティックライブラリしか生成されません。
しかし、アーキテクチャに欠けがあるfatバイナリを使うと、
Xcodeで警告が出てしまいます。

そこで、アーキテクチャに欠けがある場合は、
ダミーのスタティックライブラリを生成するようにしました。

例えば、libvpx_intrinsics_sse2.aであれば、
下記のようなC言語のソースを生成します。

int libvpx_intrinsics_sse2_dummy_symbol() { return 0; }

Bitcodeの対応

WebRTCはchromiumプロジェクトの一部になっているのですが、
chromiumプロジェクトで、Bitcode対応が見送られているようでした。

以下のスレッドで、オープンソース版のclangがBitcodeに対応するまでは、
無効にしておこう、と言っています。

Disable ENABLE_BITCODE for iOS 9.

WebRTCのビルド設定は、src/build/common.gypiに書かれているのですが、
ここにあるENABLE_BITCODEYESにするだけでは、
残念ながら生成されるビルドスクリプトには反映されませんでした。

WebRTCは、クロスプラットフォームにするために、
ninjaスクリプトや、
Visual Studioプロジェクト、
Xcodeプロジェクトを生成するために、
gypというツールを使っています。(gyp公式はこちら)
gyp向けの"プロジェクトのソース"を書くと、
gypによって様々な種類のプロジェクトを生成する事ができます。

WebRTCのiOSビルドは、ninjaスクリプトを生成するのが標準とされているのですが、
gypのninjaスクリプトの生成箇所を追っかけてみると、
gyp/pylib/gyp/xcode_emulation.pyにロジックを追加すれば対応できそうでした。

xcode_emulation.pyでは、GetCflags関数で、
xcode向けの設定を、Cコンパイラに渡すオプションに変換しています。

例えば下記のような感じです。

    if 'SDKROOT' in self._Settings() and sdk_root:
      cflags.append('-isysroot %s' % sdk_root)
    if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'):
      cflags.append('-Wconstant-conversion')    

そこで、このスクリプトではこのあたりに以下のようなコードを挿入します。

    if self._Test('ENABLE_BITCODE', 'YES', default='YES'):
      cflags.append('-fembed-bitcode')

幸い、gypはユーザのマシンにインストールされるものではなく、
webrtcのソースと一緒に、webrtcのビルドに使う用のgypが含まれています。
なので、これを変更しても副作用はwebrtcのビルドに限られます。

このようにして、bitcode対応モードで実行された時は、
必要であればgypにパッチを当てて、
その上でcommon.gypiの該当箇所をYESにする、
という動作を実装することができました。

参考

58
58
12

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
58
58