• スポンサードリンク

Android StudioでNDKのビルド

Android Android Studio NDK

新年明けましておめでとうございますm(_ _)m

去年からほったらかしの動画再生の記事とバックグラウンド録画の記事とかはまだまだほっといて(^_^;) Android StudioでNDKのビルドをする記事を書きます。
貧弱とか役に立たないと言われるAndroid StudioでのNDK対応ですが、色々試した結果、従来通りのAndroid.mkとApplication.mkを使ってAndroid Studioからコンパイルが出来ました。
と言っても昨日インストールし直したばかりでAndroid Studio/Gradleの達人ではありませんので過信はしないようにお願いします。コロコロ仕様が変わるので将来のバージョンで動くかどうかは判りませんが、それでも今ネット上にあふれている古い情報よりかはましだと思います。

前試した時は・・・

以前Android Studioをインストールして試した際には

  1. 色んなとこがとろくさい
  2. NDKのビルドが出来ない
  3. 直ぐクラッシュする

の三重苦に耐え切れず即効でアンインストールしてしまいましたが、バージョンも1.0台にあがり、去年の12月に今後公式にサポートするのはAndroid Studioだぁ〜との宣言もされてしまったので、再びインストールしてみました。

ファーストインプレッション

とりあえずの感想は・・・操作感についてまだもっさり感は色々あるし、Eclipseでいつも使って機能でないのもあるけどまぁまぁ大丈夫。あとは慣れの問題ですかね。
追記:logCatがちゃんと取れないことが多いです。起動・新たに接続した直後は大丈夫みたいですが。まだ暫くはEclipse生活になりそうです。

で、NDKはどないなってんねん?

一番の問題はNDKです。これだけは別のエディタやEclipseにするってのもなぁ(゜レ゜)

Android Studio自体にはNDKに関する設定は一切ありません。ただし、自分のインストールしたAndroidStudio1.0.2では、

  • ビルドシステムのGradleはverion0.7からNDKのビルドに対応している。らしい。
  • NDKを使ったプロジェクトをインポートするとNDKを使ってビルドできるプロジェクトとして構成してくれる。

と言う事で、一応はNDKも使えそうでした。

でもでも一杯問題があるんだよぉ(T_T)

ただし、色々問題が有ります。

  1. モノリシックな共有ライブラリ1個しか生成できない
    複数のモジュールを作ってモジュール毎に1つづつ生成することはできるけど、他のモジュール内のヘッダーとかを参照出来ないので、複数の共有ライブラリを連携させてってのが出来ない(シンボリックリンク使うとか同じディレクトリ配下にコピーするとか方法はなくもないけど)。
  2. 依存する複数の共有ライブラリを生成出来ない
    スタティックリンクで1つにするってのが大人の事情で出来ないって時あるじゃん。
    上と一緒だけど、小さなサンプルプロジェクトならともかくこれじゃ役に立たないと言われるよね。
  3. スタティックライブラリをリンクできない
    元のソースが手元に無い時だってあるじゃん。
  4. ソースファイルを個別に指定できない(フォルダ単位は可能)
    オープンソースとして公開されているようなライブラリは特にそうですが、テスト用やサンプルコードを含んでいることが多々あります。ディレクトリで分かれていればまだいいんですけど一緒くたになっているのは・・・例えばlibjpegとか・・・は関係ないソースまでビルドしてしまいます。そこにコンパイルが通らないWindows用のソースとか含まれていたら撃沈です。削除する以外ないですね。
  5. $(call import-module,xxx)に相当する機能がない。
    自分はよく使うんだよぉ〜(T_T)libjpegとかlibpngとかrapidjonsonみたいな外部ライブラリを各プロジェクト内にコピーして取り込んだり、マニュアルで共有ライブラリをコピーなんてしたくないです。
  6. Current NDK support is deprecated. Alternative will be provided in the future.って表示される。
    なっなんと・・・今はAndroid Studioを使うなと言うことかな?

結局のところは、Android.mkの自動生成がまだまだ全然だめって事が原因のようです。と言うか問答無用で含まれるファイル全部をコンパイルしようとするのはあかんっしょ。

と言う事で、元々のAndroid.mkやApplication.mkを使ってビルドしたぁ〜い(^o^)/と、新年早々長〜い前ふりでした。

元々のAndroid.mkやApplication.mkを使ってビルドしたぁ〜い(^o^)/

半日以上かかってしまいましたが、Android Studioから元々のAndroid.mkやApplication.mkを変更せずそのまま使ってビルドできるようになりました\(^o^)/。
なお、今回の記事はAndroid Studio1.0.2での内容ですので、過去バージョンや将来のバージョンでは動かなくないかもしれません。プロジェクトの新規作成&ディレクトリ生成やインポートは終わった所からスタートです。

local.properties

まずはじめはlocal.propertiesというファイルです。このファイルにはSDK/NDKのインストール先を設定する必要があります。

新規にプロジェクトを生成した時にはSDKのインストール先しか設定されていません。既存のNDKを使うEclpseのプロジェクトまたはAndroidLibraryプロジェクトをインポートすれば自動で設定してくれますが、そうでなければ自分で設定が必要です。

自分の場合はこんな感じになりました。

build.gradle

これが一番の問題ですね。2つ程大事な所があります。
ちなみにbuild.gradleというファイルはプロジェクト直下とモジュール毎にありますが、ここで編集するのはモジュール毎のbuild.gradleファイルの方です。

自動で共有ライブラリをビルドするのを止めさせる

まずは、Gradleが勝手にする共有ライブラリのビルドをやめさせることです。
ネットでウロウロすると

というおまじないを書くといいそうです。具体的にはこんな感じにします。

ネット上ではビルドのスピードアップの為に、Gradleが自動で行う共有ライブラリのビルドを1回だけにするためにこの設定をしているようで、自分の目的にはこれだけでは不十分でした。上のままだと実行した時にjava.lang.UnsatisfiedLinkErrorと怒られてしまいます。
具体的には、生成した共有ライブラリの場所がndk-buildの標準とGradle様が思い込んでいる場所が違うのです。幾つか対応方法が有るみたいですが、Gradle様にここにあるねんでと教えてあげることにします。jniLibs.srcDirの指定を追加しました。

いよいよndk-buildの呼び出しです

Gradleでいうところのtaskを作らないといけないらしいです。しかもAndroid Studio内からGradleを実行する際にはndk-buildはフルパスを指定して実行しないといけないらしいです。(参考:stackoverflow)
と言う事でこんな風にしました。


2015/03/05追記:
今日新しく作成したプロジェクトで本記事と同じようにしてndk-buildを走らそうと試みたところ、うまく動きませんでした。本記事の方法がそのままで有効なのは”Project Structure”の”Project”painのAndroid Pluginが1.0.0の時です。残念なことに、Android Pluginが1.1.0では#getNdkFolderが存在しないためにNDKのパスを取得できなくなっています。なので、本記事のようにGradle内の処理だけでndk-buildをgradleから自動的に呼び出してビルドするためには、

  1. Android Pluginを1.0.0にする
  2. #getNdkFolderを使わずに手動でフルパスを設定する

のどちらかの対応が必要です。と書こうと思ったんですがそれはなんか悔しいので調べてみました。

stackoverflowで話題になってました。ここ
それを元に自分なりに書き換えてみました。#getNdkFolderメソッドを自前で定義して元々のBaseProperty#getNdkFolderの代わりに呼び出すようにします。

-Cオプションでjniフォルダの存在するディレクトリの親ディレクトリ(ここではsrc/main)を指定してndk-buildを実行しています。(-j4は並列コンパイルの設定なのでよしなにはからってください)。
たぶんWindowsでも実行できるように実行環境に応じてコマンド名を設定していますが、このOs.isFamilyを使うには、「import org.apache.tools.ant.taskdefs.condition.Os」としてインポートしておかなければなりません。これもstackoverflowからの受け売りです(^_^;)

16行目はネット上の情報によるとtasks.withType(Compile)と書いてあるんですが、これだとそんなプロパティはしりまへん(●`ε´●)と怒られてしまうので、tasks.withType(JavaCompile) としてみました。Compileプロパティはだいぶ前からdeprecatedだったみたいですが、Gradle2.0でとうとう削除されてしまったみたいです。

これで完璧〜\(^o^)/と思ったら、実は1つだけまだダメでした。では質問です。一体なにがだめだったんでしょう?当たった人は・・・お年玉ください(笑)

答え

外部モジュールのインポートでこけてしまいました。これは必ずしもAndroid Studio/Gradleのせいではないかもしれないので環境依存ですかね。解決方法は簡単で、NDK_MODULE_PATH環境変数をセットするか、外部モジュールをフルパス指定するかですね。
フルパス指定なんて有りえないので、自分はNDK_MODULE_PATH環境変数を設定しました。
.bashrcと.profileに

を追加です。

これでEclipseやコマンドラインからndk-buildを実行するのとまったく同じになりました。ばんざ~い万歳〜バンザーイ\(^o^)/最初にあげた自動ビルドの問題点も全て解決です。
まぁAndroid.mkやApplication.mkを作らないといけないのなら最初からコマンドラインでndk-build叩けばいいんやないの?ってのは言わない約束です(^_^)今までEclipseで出来てた事をAndroid Studioからでも出来るようになったってとこだけ見といて下さい。これでAndroid Studioへの移行する障壁が1つ減ったかな?

おまけ

と言う事でAndroid Studio1.0.2からでも従来通りのAndroid.mkとApplication.mkを使ってビルドできるようになりました、おしまい・・・なんですが、せっかく調べたついでなのでAndroidStudio1.0.2でAndroid.mk/Application.mk相当の機能を設定する方法もちょこっと載せておきます。
基本的にはbuild.gradle内で、ndkで囲ったブロック内で指定します。例えばこんな感じ

  • Application.mkのAPP_STL => stl
  • Application.mkのAPP_CFLAGS(またはAndroid.mkのLOCAL_CFLAGS) => cFlags
  • Android.mkのLOCAL_LDLIBS => ldLibs
  • Android.mkのLOCAL_SRC_FILES => sourceSets.main.jni.srcDirs

とう言う風に対応しています。
ちなみに、ndk{}は、常に有効にしたいのであればandroid.defaultConfig内に書くのが良さそうです。

また、リリース版とデバッグ版で違うのであれば、

という風にすれば良い様です。署名の設定とかもここに入れることになります。手で入力してもいいですが、Android Studio 1.0.2だとダイアログで設定した署名の設定がbuild.gradleに反映されていました。

CPUアーキテクチャでソースが異なる時やコンパイルオプションが異なる時は、ProductFlavorsとabiFilterを使うみたいです。また、共通のソースはsrc/main内に入れて、個別のソースはbuildTypes名(releaseやdebug)、あるいはProductFlavorsで指定したFlavors名またはbuildTypes名とFlavors名を組み合わせた名前のディレクトリ内に入れてsrcDirsとかに設定するといいみたいです。
でもAndroid.mkとApplication.mkを使ってビルドできるようになったので、そっちですりゃいいやってことでちゃんと確認してませんm(_ _)m
だって「Current NDK support is deprecated. Alternative will be provided in the future.」なんだよ?いつどんな風に変わるかわかんないのに一生懸命調べてもしょうがないやん。

と言う事で、ようやくおしまいです。
お疲れ様でした。

« »

  • スポンサードリンク

コメント

  • Noble より:

    I was recommended this blog by my cousin. I am not sure whether
    this post is written by him as no one else know such detailed about my
    difficulty. You're incredible! Thanks!

  • Frank より:

    It's apropriate time too mzke a ffew plans forr thhe lonhger term aand it's time to
    bbe happy. I have lsarn tuis puut up annd if I mmay jjust I
    desire to counse yoou few fascinating isses orr tips.
    Maybe youu ccould wfite nnext articles relating tto this article.
    I want to learn evrn ore ssues approximately it! I could not refrain from commenting.
    Exceptionally wsll written! Hell would yoou mind strating whhich blpog platorm you're worfking with?
    I'm plaqnning tto start my own blog iin thhe nwar
    future butt I'm hacing a difficult tiume selrcting betwren BlogEngine/Wordpress/B2evolution andd Drupal.
    Thee reqson I aask iss because youyr dessign andd stylee seems different thwn molst blogs aand I'm looking forr somthing completely unique.
    P.S Apologvies foor being off-topic bbut I haad to ask! http://foxnews.org/

  • […] Android Studio 1.3になっても前の記事のままでも動きますが、ちょっとだけ違う方法も書いてみま〜す。大して変わらないけど。 […]

  • […] Android StudioでNDKのビルド – 車輪の再発見みたいな? […]

%d人のブロガーが「いいね」をつけました。