XcodeでAppRTCDemoをビルドできるようにしてみる

  • 39
    Like
  • 0
    Comment
More than 1 year has passed since last update.

この記事は更新されていません

あ、pythonは2.x系じゃないとダメです。3.x系だとfetchでエラーが出ます。

$ fetch --nohooks webrtc_ios
$ gclient sync
$ cd src/
$ webrtc/build/ios/build_ios_libs.sh

でインポート可能なframeworkが生成されるようになっているので、
ゆるりとどうぞ。

はじめに

※洒落です。聞き流してください。

やぁ。(´・ω・`)ようこそ、バーボンハウスへ。
この前置きはいつものことだから、まず落ちついて見て欲しい。

うん、「有料カンファレンスの資料ネタ」なんだ。済まない。
謝るつもりもないし、許してもらう謂れもないと思ってる。

資料も公開されているが話者が話した内容にこそ価値があるわけで、
資料はその補足でしかない。話者が時間を割き強調したことに、
話者は価値を見いだしてるんじゃないかな。

実際ここではサンプルアプリのビルド方法以外については触れてない。
WebRTCの情報は鮮度が大事なんだ。そこのところをわかってほしい。

それでは先月末に作った資料がすでにゴミになってるという
恐ろしいWebRTCネタを始めようではないか。

まじめに

WebRTC Conference Japanで某通信会社の人がしゃべった内容です。
http://www.slideshare.net/minamotot/webrtc-44772839
配布された印刷資料にXcodeでAppRTCDemoをビルドできるようにする手段が記載されていましたが、
ごく最近AppRTCDemoが更新されていたことと、
記載内容に不足があったので筆者の許可を得て(ぇ)ここに改めて記載することにしました。

鮮度が重要です。2015/02/19現在はこの方法で動くものがビルドできます。
trunkが動く。これはすばらしいこと。いつまでこの手順で動くものができるかは謎です。

ビルド環境について

Macのことはよくわからないので(ぁ)解りませんが、
最新版のXcodeが動く環境ならいけると思います。

Android版の記事
http://qiita.com/tonofo/items/c60088e9829e9881d981
を参考にするなら、メモリ2G,HDD30GBあれば良いようです。
ちなみに筆者は10GB超使ったのでまぁ20GBもあればいい気がします。

参考までに、これを書いたときのMacは

MacBook Pro (Retina, 13-inch, Mid 2014)
2.6 GHz Intel Core i5, 8 GB 1600 MHz DDR3

というのを使いました。この検証のためだけにボーナスで買って
ホコリをかぶってるそうです。(サラリーマンがこんなお金の使い方をしては…

おおっと。XcodeはVersion 6.1.1 (6A2008a)を使っていました。
あとiOS Developer Programには加入していて、Xcodeに登録済みという前提で進めてます。
まぁ、でも。こんな情報が役に立つ頃にはこの記事はごm(ry

AppRTCDemoのビルド

まずは砂場を作って
$ mkdir libbuild
砂場に入ります
$ cd libbuild/
なんとなく、ライブラリはビルド環境ごと残しておきたい筆者です。

ビルドツールのインストール

インストールって言うほど大層なものではないです。Gitで引っ張ってきて、
$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
PATHに追加するだけ
$ export PATH=`pwd`/depot_tools:$PATH

あ、見りゃわかるよ。って言われそうですがexportにpwdコマンド使ってます。
gitで引っ張ってきたdepot_toolsの置き場所で実行してください。

後述のfetch,gclientやninjaコマンドを使うときには必要になります。
コンソールを開くたびにexportを実行するか~/.bashrcに書いちゃうかは好みですが、
実行頻度は低いので筆者は都度実行しています。

ソースコードのダウンロード

$ export GYP_DEFINES="OS=ios"
GYP_DEFINESにiosを指定して
$ fetch webrtc_ios
これだけ!あ、一回しか実行できません。
chromiumのソースコードDLです1-2時間は間違いなくかかります。お茶しに出かけましょう。
新橋でお茶する際は呼んでください。つきあいます。

なんかエラー出てるーor通信切れちゃったーと言うときは
$ gclient syncというコマンドで再開できます。

ビルド

正常終了するとsrcディレクトリができているので入ります。
$ cd src/

ついでなんでおもむろに環境変数を追記します。
$ export GYP_CROSSCOMPILE=1
$ export GYP_GENERATORS=ninja
ニンジャ!って好きだねぇ…(TAXI2っていう映画がありまして…

32bitのとき

さらに環境変数を追記します。64bitとは違います。
$ export GYP_DEFINES="OS=ios target_arch=armv7"
【2015/05/08更新】armv7→arm変更しないとビルドエラーが起こる
$ export GYP_DEFINES="OS=ios target_arch=arm"
$ export GYP_GENERATOR_FLAGS="output_dir=out_ios"

おまじないです。srcディレクトリ内でやらないとこけます。
GYP_ではじまる環境変数を変更した際には必ず実行します。
$ webrtc/build/gyp_webrtc
筆者はビルドスクリプトを生成してるんじゃないかと思っています。

ニンジャコマンドでビルドします。もちろん、どちらか片方でも良いです。
Debugビルド
$ ninja -C out_ios/Debug-iphoneos AppRTCDemo
Releaseビルド
$ ninja -C out_ios/Release-iphoneos AppRTCDemo
動画の速度などが目に見えて違う&ライブラリの中など触らないという理由で、
Releaseビルドしか筆者はしないです。

Debugビルドは動くのにReleaseビルドは動かないなんていう話がついこないだまでありました。

64bitのとき

だいたい32bitと同じですが、ちょっと違います。
$ export GYP_DEFINES="OS=ios target_arch=arm64 target_subarch=arm64"
$ export GYP_GENERATOR_FLAGS="output_dir=out_ios64"

GYP_ではじまる環境変数を変更した際には必ず実行
$ webrtc/build/gyp_webrtc

Debugビルド
$ ninja -C out_ios64/Debug-iphoneos AppRTCDemo
Releaseビルド
$ ninja -C out_ios64/Release-iphoneos AppRTCDemo

ビルドQ&A

Q:どっちがいいの?
A:たぶん64bit

Q:32bit版動かないんだけどなう(2015/02)
A:後述

Q:32/64bit両対応ライブラリは?
A:https://code.google.com/p/webrtc/issues/detail?id=4119
【2015/05/08に後述済み】

Q:最後の処理でこけるんだけど
A:iOS Developer Programに加入してるならたぶんAppIDの問題。
AppRTCDemoのAppIDはcom.google.AppRTCDemoライブラリのビルドには影響ないから無視してもOK
でも、不便なので一番下に解決法を書きました。

AppRTCDemoを動かしてみる

XCodeを起動して
メニューバー→Window→Devices
下記のような画面が出たら、赤枠の+をクリックして、
ビルドされたAppRTCDemoを選択すればインストールできる。
スクリーンショット 2015-02-19 2.01.50.png
ビルドされたAppRTCDemoの場所は、たとえば64bit版Releaseビルドなら
src/out_ios64/Release-iphoneos/AppRTCDemo

あとは
https://apprtc.appspot.com/
で表示されたRoom名を入力して入る。iOSどうしで同じRoom名を入力しても接続できるはず。
fullって出たときにはおとなしくRoom名を変えよう!
ちなみにAppRTCDemoはいまのところ1:1でしか通信できないよ!

Xcodeに登録

記事書くの疲れてきました。。。Xcodeでビルドできるようにすることが目的でしたようね。そうですね。。。
ここからはXcodeがある程度使えることを前提にさせてください

■Xcodeを起動して、おもむろに
Create a New Xcode project

■ウィザードは
iOS→Application→Single View Application
と進めていき
Objective-C/Universalで適当なプロジェクトを作成

■どうせなのでライブラリビルド環境は汚染しないよう注意してやってみましょう。
Project Navigaterの<Project名>フォルダ直下はinfo.plistを除き一掃する

■info.plistだけが残っているはずの
<Project名>.xcodeprojのあるフォルダ/<Project名>/
に対し

talk/examples/objc/AppRTCDemo直下
talk/examples/objc/AppRTCDemo/iosの中身(*.plistを除く)
talk/examples/objc/AppRTCDemo/third_party丸ごと

をコピって
Project Navigaterのフォルダ直下に登録する

■折角なので
必要なファイルは$(SRCROOT)以下に集約したい
というわけで、*.xcodeprojのあるフォルダにlibsとincludesフォルダを作る

■libsには
out_ios/Debug-iphoneos/*.aをすべてコピーして
XcodeのProject Navigater、Project直下にlibsフォルダごと入れ登録
※筆者も多すぎると思ってる。必要最低限があるはずだけど、今はてきとー

■includesには
talk/app/webrtc/objc/publicをすべてコピー

■ライブラリの追加
General => Linked Frameworks and Librariesには
最下部の+を押して出てくる一覧から
スクリーンショット 2015-02-19 2.27.44.png

  • GLKit.framework
  • CFNetwork.framework
  • Security.framework
  • libicucore.dylib
  • libsqlite3.dylib
  • libc++.dylib

を選択して追加

■アーキテクチャの選択
Build Settings => ArchitecturesのArchitectureは手元の端末に合わせる。
僕の場合はarm64なので、Otherを選んで入力
Build Active ArchitectureはNo
Valid Architectureもarm64に絞る
スクリーンショット 2015-01-29 2.17.34.png

■ヘッダー検索パスの追加
Build Settings => Search Paths => Header Search Pathsに
$(SRCROOT)/includesを追記
スクリーンショット 2015-01-29 2.18.01.png

■info.plistを開いて
Main story board file based nameを項目ごと削除

★ビルド対象には実機を選択

■ちなみにProject Navigaterは下記のようになってるはず。
筆者はProject名をrtcdemoにした
スクリーンショット 2015-02-19 2.35.43.png
===中略===
スクリーンショット 2015-02-19 2.36.01.png
===中略===
スクリーンショット 2015-02-19 2.36.19.png

フォルダ構造はこんな感じ
スクリーンショット 2015-01-29 2.25.06.png

★この状態でRunすると、晴れてビルドできるはず。

Tips系

ひぃ。。。ひぃ。。。。(疲れてる
誰だよ、元ネタ作ったの。(とりあえず、コマンドだけ列挙して解説後付け

ブランチをビルドする

書いておいてなんだけど、AppRTCDemoは仕様が変わっていて動かない
ライブラリは確かに経験上安定していると思う

ちょっと飛ばして
$ export GYP_DEFINES="OS=ios"
ここは全然ちがう。ブランチ一覧はこちら
http://webrtc.googlecode.com/svn/branches/
番号が二桁に突然なっているのは命名規則が変わってChromiumのバージョンに対応するようになった。
$ gclient config http://webrtc.googlecode.com/svn/branches/40
このコマンドの場合はChrome40に対応している…たぶん…

上記のコマンドで生成された隠しファイルを編集する
$ vi .gclient
エディタはなんでも。

.gclient
solutions = [
  { "name"        : "src",
    "url"         : "http://webrtc.googlecode.com/svn/branches/40",
    "deps_file"   : "DEPS",
    "managed"     : True,
    "custom_deps" : {
    },
    "safesync_url": "",
  },
]
cache_dir = None
target_os = ['ios', 'mac']

こんな感じ、具体的にはnameを変更して、target_osを追記している

そして、依存関係の解決。この場合はchromiumのソースコードダウンロードはここ
$ gclient sync
まぁ、例によって時間がかかるのでお茶でもしにいく。

あとはビルドの項に同じ

ninjaコマンド実行時のAppID問題解決

会社によってはワイルドカードがないですよね。そうですよね。
$ vi ./talk/examples/objc/AppRTCDemo/ios/Info.plist
でXMLの

Info.plist
        <key>CFBundleIdentifier</key>
        <string>com.google.AppRTCDemo</string>

com.google.AppRTCDemoを任意のものに書き換えるとninjaが正常終了して実行可能になる

Cleanしたい!

わかる、わかる。
$ ninja -C out_ios/Release-iphoneos -t clean

最新版に更新したい

srcディレクトリ内で
$ git fetch
$ git merge origin/master
で最新版になるので、

念のため
$ export GYP_DEFINES="OS=ios"
してから

$ gclient sync
で依存関係解決。chromiumとか表示された、お茶に行く
あとはビルドの項に同じ

armv7で落ちるんだけど

おけ。2015/02/19現在、下記の問題がある
https://code.google.com/p/webrtc/issues/detail?id=4190
リンク先に示されている
https://gerrit.chromium.org/gerrit/#/c/73650/2/vp8/common/arm/neon/vp8_subpixelvariance_neon.c
にならって、同じファイルを書き換える
$ vi ./chromium/src/third_party/libvpx/source/libvpx/vp8/common/arm/neon/vp8_subpixelvariance_neon.c

ってか、成功したリビジョンさらせやー

おk。おk。
1c3e728aa9b886fd3ee008a5aed956759bc3f82d
【2015/06/09追記】5/7のだけど、これはAndroid/iOSで動いたよ
d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1

32bit 64bit 両対応の Universalバイナリは作れないの?

【2015/05/08追記】
できるっぽい
適当なディレクトリ内にarm,arm64というディレクトリを作る
arm には out_ios/Release-iphoneos/*.a
arm64 には out_ios64/Release-iphoneos/*.a
をそれぞれコピーして
$ talk/build/merge_ios_libs 適当なディレクトリ※最後に/を入れるとエラーで止まる
で単純に結合されたバイナリが適当なディレクトリ/fatにできあがる

H.264に対応したってきいたけど?

【2015/06/30追記】
耳が早いっすね。。。
https://code.google.com/p/webrtc/issues/detail?id=4081
こんな感じで、まだチューニングが必要らしいですよ。
僕が試した限りだと確かにノイジーな感じでした。H.264らしいノイズがでます。
GYP_DEFINESにuse_objc_h264=1を追記すると使えます。

こんな感じ、(64bitなら)
$ export GYP_DEFINES="OS=ios target_arch=arm64 target_subarch=arm64 use_objc_h264=1"

GYP_DEFINES変更後はgyp_webrtcをお忘れなく。
H.264の動作確認をしたリビジョンは↓(たぶん。。。確証はない。。。
1adbacb19dbe6f4c537c9cc9d04242b61735a2b8

なんかWiFiなのにWiFi切っても繋がってるんだけど。。。

【2015/07/14追記】
そこに気づいてしまったか。。。実はWiFi接続時でもLTEで繋がっていてissueに上がってます。
https://code.google.com/p/webrtc/issues/detail?id=4325

最新版使うと解決ですね!って、そういう問題でもなくて、

host-LTE > host-WiFi > srflx-LTE > srflx-WiFi > turn-LTE > turn-WiFi

の優先順位が

host-WiFi > host-LTE > srflx-WiFi > srflx-LTE > turn-WiFi > turn-LTE

っていう優先順位に変わるだけなんですよね。host-LTEで繋がることがあるのかは謎だけど、ユーザからするとWiFiで繋いでるんだからLTEで繋がらないでほしい…
いやARPUに影響あるから嬉しいかもだけど。(ってか、LTEでWebRTCとかパケ死する…

というわけで、Candidateをpurseしてメッセージングに流さないよう潰すのがオススメです。

え、Candidateを流さなくてもLTEでつながっちゃうって?
そんなのは超特殊ユーザでしょ。MCUやSFUなら起こるだろうけど…対処法?あるよ。普通要らないけどね

【2015/07/14追記】
ちょっとまって。factoryにnetworkIgnoreMaskがあってここで指定すればいい気がする。↓の処理なんかいらない。(動作確認してないけど

$ vi webrtc/base/network.cc

BasicNetworkManager::ConvertIfAddrsを変更します。

network.cc
void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
                                         bool include_ignored,
                                         NetworkList* networks) >const {
#if defined(WEBRTC_IOS)  //追加分
  bool use_eth = false;
  for (struct ifaddrs* cursor = interfaces;
       cursor != NULL; cursor = cursor->ifa_next) {
    if (!cursor->ifa_addr || !cursor->ifa_netmask)
      continue;

    if (strncmp(cursor->ifa_name, "en", 2) == 0) {
      use_eth = true;
      break;
    }
  }
#endif

  NetworkMap current_networks;
  for (struct ifaddrs* cursor = interfaces;
       cursor != NULL; cursor = cursor->ifa_next) {
//...中略...
      network->set_ignored(IsIgnoredNetwork(*network));

#if defined(WEBRTC_IOS)  //追加分
      if ((strncmp(cursor->ifa_name, "pdp_ip", 6) == 0) && use_eth) {
        network->set_ignored(true);
      }
#endif

      if (include_ignored || !network->ignored()) {
        networks->push_back(network.release());
      }
    } else {
      (*existing_network).second->AddIP(ip);
    }
  }
}

ちょっと冗長なのは見逃してちょ…LTEとWiFiが繋がっていて、WiFiがインターネットに抜けてない時の考慮?そんなのないよ…
もう、この記事。誰得…ってか、分けるか共同編集可能なところに置きたい…
まぁ、皆さんWebRTC楽しみましょ…ほんと…_| ̄|○

まとめ

つかれた。寝る。

WebRTC盛り上がるといいねぇ。

リアルタイムでビルドする方法こんなに書いたの。折角だからコメント欄で、こうした方がいいよーとか。僕のバージョンだとこうだったよー。とか意見交換できると良いなーって思いますです。

ぼくも、気が向いたらまたこうしんします。おやすみ。

This post is the No.11 article of WebRTC Advent Calendar 2014