2018/05/13

[android][ndk]MbedTLSをビルドしてみよう (2)

前回の復習から。


NDKでMbedTLSをビルドしようとしたが、それ以外にもビルドしたいライブラリがあるので、まずは複数のC/C++ライブラリをビルドする用意をしておきたい。

Android Studioではcmakeを使えるようだし、MbedTLSもcmakeの設定があるので、取り込めばよさそうだ。

そのサンプルが、hello-libsであった。


hello-libsは、pre-builtされたライブラリを使うサンプルになっているが、2箇所変更するだけでpre-builtされたライブラリをビルドするところもやってくれるようになっている。


で、今回は、どうやればいいのかを調べるところからだ。


Android Studioの左下に「Build Variants」があるが、settings.gradleのコメントアウトを消すと"gen-libs"が出てきた。
設定値は"debug"である。


ツリーはこうなっている。
有効にした"gen-libs"が増えているから、settings.gradleが効いたのだろう。

image

このファイルでincludeしているのは、"app"と"gen-libs"で、両方ともフォルダがあり、中にbuild.gradleがある。
ライブラリたちを、同じように専用のフォルダを作ってまとめてしまうか、あるいはライブラリごとにフォルダを作るかだろう。

アイコンがappとは違っているので、そういうフォルダが作れるようだ。
どうも、Module、というもののようである。

image

ここで+アイコンをクリックしても良いのだろうが、ツリー画面のコンテキストメニューに「New>Module」もある。
出てくるウィザード画面はどちらも同じなので、どっちでもよいのだろう。


ウィザード画面を見たが、どれを選べばよいのだろう?
JNIになるからJava Libraryかと思ったが、違う気がする。

そもそも、最後はJNIになるし、MbedTLSも使いたいのだが、MbedTLSをJNI経由で直接扱いたいわけではなく、JNIで使いたいライブラリが中でMbedTLSを使っているだけなのだ。
gen-libsはJavaを持ってないので、同じようになっているはず。
build.gradleの「apply plugin」が"com.android.library"になっているから、Android Libraryを選べばよさそうだ。

作ってみると、アイコンも同じだったので、大丈夫だろう。
ここでは「build-libs」という名前で作った。
モジュール設定画面を見ていっても、testrunnerが入っているくらいで、gen-libsとあまり違いは無かった。


image


デフォルトで「java」というフォルダと、その中にパッケージのフォルダ階層が作られたが、それだけのようだ。

image

gen-libsの方には、cppの中にCMakeLists.txtがある。
build.gradleの中にCMakeLists.txtへのパスが書かれているので、同じようにやれば良いのだろう。
相対パスで書けるので、このフォルダごと別のプロジェクトに持っていってインポートするようなこともできるのかもしれん。


まず、javaディレクトリを削除して、cppディレクトリを作成。
その中に、const char*を返すだけのCソースとヘッダファイルを追加。
cmake関係は後回しにして、まずはjavaの痕跡を消しておきたかったのだが、syncっぽいことをしても消えないし、cppも出てこない。
testrunnerがあるせいかと思って消したが、効果無し。

だが、コンテキストメニューを出してみると「Link C++ Project with Gradle」が出てきた。
これで「Android Studio UIの使用」に書いてあることができるのだ。

image


では、cmakeの作業をせねばなるまい。
私はcmakeに詳しくないので、gen-libsの中にあるgmathのCMakeLists.txtをコピーして、"gmath"と書いてあるところを適当に置き換えた。
ライブラリやヘッダファイルがあった distributionディレクトリへのコピーもこの中でやるようなので、パスを変更する。

そして、作ったCMakeLists.txtを「Link C++ Project with Gradle」でリンクさせる。
CMakeLists.txtを指定するだけなのだが、相対パスへの変換もちゃんとやってくれる。


取りあえずビルドだ、ビルド。
とボタンを押してみるが、バイナリができないし、includeファイルのコピーもされていない。
ただ、distributionディレクトリの中にはディレクトリが追加されている。


そういえば、gen-libsをビルドできるようにしたとき、appのbuild.gradleにも変更を加えたのだった。
コメントを見ると、native libraryのビルドが行われないというissueが出ているらしく、その対応のように見える(今はv3.1.2だから直ってるかも)。
同じように追加すればビルドされるかと思ったのだが・・・ダメだ。
distributionディレクトリの中にディレクトリが追加されたのも、cmakeが行われたからというよりは、リンクする作業を行ったからやってくれただけのようにも見える。
distributionディレクトリの中を削除してビルドし直しても、gmathとgprefしか生成されないからだ。


設定ファイルを見直していくと、build.gradleに"android.defaultConfig.externalNativeBuild"が無いことに気付いた。
gen-libsだと"targets"にライブラリの名を書いているだけなのか?
appの方は"arguments"で、g++だかclangだかに与えるパラメータを書いているように見える。
よくわからんので、"targets"に今回追加したライブラリ名を書いてみた。
が、変わらず。


ツリーのビューを"Packages"に変更すると、追加したライブラリのパッケージ名が違っていることに気付いた。
AndroidManifest.xmlで変更するようだったので、書き換えた。


ここら辺までやると、distributionディレクトリの中に追加したライブラリとヘッダファイルがコピーされていた。
されていたけど、あれこれやりすぎて、どれが有効だったのかが分からん。。。


新規に、hello-libsに自分のライブラリを追加していこう。


  1. Android Studio v3.1.2を起動して、「Import an Android code sample」の"hello-libs"プロジェクトを選択。
  2. メニュー:File > Project Structure
    1. +アイコンをクリック
    2. "Android Library"を選択してNext
    3. 「Application/Library name」に"mklib"、「Package name」に"com.example.buildlibs"を設定して、Finish
    4. Android Studioがぐりぐり動き出すので、OKでダイアログを閉じて安定するまで待つ。
      1. ダイアログを閉じずに待っていたのだが、10分くらいしてもぐりぐりしたままだった
  3. 安定したら、もう一度Project Structureを開いて、左からmklibを選択し、「Dependencies」タブでjunitとtestrunner関係を削除して、OK
  4. ディレクトリ"mklib/src"にある"androidTest"、"test"、"main/java"を削除
  5. mklib/src/mainの中に"cpp"ディレクトリを作り、ソースファイルとCMakeLists.txtを置く
    1. ライブラリ名は"mklibtest"
  6. mklib/build.gradleの編集
    1. android.externalNativeBuildを追加し、cmake.pathにCMakeLists.txtのパスを追加
    2. android.defaultConfig.externalNativeBuildを追加し、cmake.targetsに"mklibtest"を追加
      1. これは、コンテキストメニューの「Link C++ Project with Gradle」から行ってもよい
    3. testInstrumentationRunnerの行を削除
  7. app/build.gradle(これはやらなくてもよいかもしれん)
    1. tasks.whenTaskAddedに、"gen-libs"のまねをして"mklib"を追加
    2. tasks.whenTaskAddedのコメントアウトを戻す
  8. メニュー:Build > Make Project


これで、distribution/mklibtestにヘッダファイルとライブラリがコピーされた。
ライブラリは今回staticにしていて、libmklibtest.a、という名前になった。

ここまでをgithubに上げておこう。


さて、ここまででライブラリはビルドできた。
アプリで使うには、app/build.gradleに追加したり、JNIを作ったりせんといかんが、今回の目的ではないのでよかろう。

次回はMbedTLSをビルドできるようにしたいが、すごく苦労しそうな気がする。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。