AndroidではRPATH、RUNPATHともに無効
下記URLにもある通り、AndroidではRPATH、RUNPATHともに無効なようです。
実行バイナリからshared objectを利用したい場合、LD_LIBRARY_PATHでパスを指定するしかない。libc.soさえも同じ扱いのようですね。
bionic libcの手抜きってことなんでしょうか。面白いけどつらい。
Android Studioのアップデート時の作業メモ
Android StudioとAndroid SDKをアップデートしたら既存プロジェクトをあれこれ直す必要があって、どれが必要だったのか自分でも整理できてないけどメモ
- Android SDKを入れ直したので、「Project Structure」「Platform Aettings」「Android SDK」の「Android SDK location」を修正
- 「Tools」「Android」「SDK Manager」から「Android Suport Library」をインストール
- build.gradleを修正
- gradle のバージョン指定(?)を「0.7.+」に(参照:http://tools.android.com/recent/androidstudio040released)
- compileSdkVersionとbuildToolsVersionとtargetSdkVersionを19(Android 4.4)に
- gradle-wrapper.propertiesのdistributionUrlをgradle-1.9-bin.zipに
- 「Sync Project with Gradle Files」
Expat 2.1.0をAndroid NDKでクロスコンパイルする
ExpatはXMLパーサーライブラリです。
http://sourceforge.net/projects/expat/files/ から expat-2.1.0.tar.gz をダウンロードします。
$ tar xvzf expat-2.1.0.tar.gz $ cd expat-2.1.0 $ CFLAGS=-O2 LDFLAGS=-s ./configure --host=arm-linux-androideabi --prefix=$ANDROID_APP_ROOT/expat-2.1.0 $ make $ make install
特に罠もなくビルドできます。
installed files
bin/xmlwf include/*.h lib/libexpat.a lib/libexpat.la lib/libexpat.so lib/libexpat.so.1 lib/libexpat.so.1.6.0 lib/pkgconfig/expat.pc share/man/man1/xmlwf.1
zsh 5.0.2をAndroid NDKでクロスコンパイルする
まずhttp://zsh.sourceforge.net/Arc/source.html から zsh-5.0.2.tar.bz2 をダウンロードします。
ビルドには ncurses, PCRE, libiconv の各ライブラリが必要です。以前の記事「ncurses 5.9をAndroid NDKでクロスコンパイルする」「PCRE 8.33をAndroid NDKでクロスコンパイルする」および「libiconv 1.14をAndroid NDKでクロスコンパイルする」を参照してください。
zshに含まれるconfig.subはAndroidのクロスコンパイル環境に対応していない古いものなので、libtoolのファイルをコピーしてからconfigureします。
また、_mktemp(3)を使わないようにするためconfigureに対して環境変数をセットします(理由は後述)。
さらに、Android 4.3時点ではttyname(3)は未実装であり、下記のようなエラーメッセージを出してNULLを返します。
char* ttyname(int)(3) is not implemented on Android
zshは内部的にttyname(3) を利用しているので、これを利用しないよう、パッチを当てた上でttyname(3)を使わないよう環境変数をセットします。
configure中で利用しているpcre-config(シェルスクリプト)にパスを通す必要もあります。
以上を反映したものが下記の実行例です。
$ tar xvjf zsh-5.0.2.tar.bz2 $ cd zsh-5.0.2 $ for i in `find . -name config.guess` ; do cp /usr/local/share/libtool/config/config.guess $i ; done $ for i in `find . -name config.sub` ; do cp /usr/local/share/libtool/config/config.sub $i ; done $ curl https://gist.github.com/hnw/6751590/raw/0297fdc1987130f67d3cde11dc76fa18276da3c8/zsh-5.0.2-android-patch.txt | patch -p1 $ autoreconf $ PATH=$ANDROID_APP_ROOT/pcre-8.33/bin:$PATH CFLAGS="-O2 -I$ANDROID_APP_ROOT/ncurses-5.9/include -I$ANDROID_APP_ROOT/pcre-8.33/include -I$ANDROID_APP_ROOT/libiconv-1.14/include" LDFLAGS="-s -L$ANDROID_APP_ROOT/ncurses-5.9/lib -L$ANDROID_APP_ROOT/pcre-8.33/lib -L$ANDROID_APP_ROOT/libiconv-1.14/lib" ac_cv_func__mktemp=no ac_cv_func_ttyname=no ./configure --host=arm-linux-androideabi --prefix=$ANDROID_APP_ROOT/zsh-5.0.2 --with-term-lib=ncurses --disable-locale --disable-multibyte --enable-pcre $ make $ make install
Androidの_mktemp(3)について
Android NDK r9時点では、toolkitに含まれるlibcは_mktempという関数を含んでいるようで、configure中のチェックビルドでは_mktempシンボルを解決できてしまいます。
しかし、実際に_mktempを利用しているバイナリを実機で実行しようとすると下記のようなエラーが出てしまいます。
CANNOT LINK EXECUTABLE: cannot locate symbol "_mktemp" referenced by "/data/local/tmp/a.out"...
このように、AndroidのlibcとAndroid NDKのlibcとが異なっていることがあるようです。この手のトラブルは実機やエミュレータで動かしてみるまでわからないので、なかなか厄介です。
installed files
bin/zsh bin/zsh-5.0.2 share/man/man1/*.1 share/zsh/5.0.2/functions/*
ncurses 5.9をAndroid NDKでクロスコンパイルする
http://ftp.gnu.org/pub/gnu/ncurses/ から ncurses-5.9.tar.gz をダウンロードします。
Androidでビルドするため、locale.hが存在しないかのようにconfigureに対して環境変数をセットする必要があります(理由は後述)。
それ以外は特に気をつける点はありません。下記の実行例の場合、C++バインディングを外す指示と*.soを作る指示を追加しています。
$ tar xvzf ncurses-5.9.tar.gz $ cd ncurses-5.9 $ CFLAGS=-O2 LDFLAGS=-s ac_cv_header_locale_h=no ./configure --host=arm-linux-androideabi --prefix=$ANDROID_APP_ROOT/ncurses-5.9 --with-shared --without-cxx-binding $ make $ make install
Android NDKのロケールについて
Android NDK r9時点ではロケールの実装はスタブ実装になっています。ロケールが必要ならSDK使ってねという発想でしょうから、今後もNDKレベルで実装されることは無いでしょう。
それはそれでいいのですが、ロケール周りが下記のように中途半端なスタブ実装になっているため各種OSSのconfigureが混乱しがちです。
- locale.h:ある
- setloacle(3):ある、特に仕事はしない
- LC_CTYPEなどのenum定数:ある
- localeconv(3):ヘッダファイルでは定義されてるけど実体がないのでリンクに失敗する
- lconv構造体:定義されてるけどメンバ数がゼロ
実際、ncursesはlocale.hが存在したらロケール周りがフル実装されていると判断するものの、localeconvが無いのでビルドが通りません。
Androidでのビルドということを考えると、一般論としては「configure --disable-locale」するのが正解だと言えます。ただし、ncursesのconfigureでは--disable-localeが提供されていないため、今回はlocale.hが存在しないかのようにautoconfのcache variableを環境変数として渡したというわけです。
installed files
bin/captoinfo bin/clear bin/infocmp bin/infotocap bin/ncurses5-config bin/reset bin/tabs bin/tic bin/toe bin/tput bin/tset include/ncurses/*.h lib/libform.a lib/libform.so lib/libform.so.5 lib/libform.so.5.9 lib/libform_g.a lib/libmenu.a lib/libmenu.so lib/libmenu.so.5 lib/libmenu.so.5.9 lib/libmenu_g.a lib/libncurses.a lib/libncurses.so lib/libncurses.so.5 lib/libncurses.so.5.9 lib/libncurses_g.a lib/libpanel.a lib/libpanel.so lib/libpanel.so.5 lib/libpanel.so.5.9 lib/libpanel_g.a lib/terminfo/ man/man?/*.? share/tabset/* share/terminfo/??/*
libiconv 1.14をAndroid NDKでクロスコンパイルする
http://ftp.gnu.org/gnu/libiconv/ から libiconv-1.14.tar.gz をダウンロードします。
config.subが古いので、libtoolのファイルをコピーしてからconfigureします。
$ tar xvzf libiconv-1.14.tar.gz $ cd libiconv-1.14 $ for i in `find . -name config.guess` ; do cp /usr/local/share/libtool/config/config.guess $i ; done $ for i in `find . -name config.sub` ; do cp /usr/local/share/libtool/config/config.sub $i ; done $ CFLAGS=-O2 LDFLAGS=-s ./configure --host=arm-linux-androideabi --prefix=$ANDROID_APP_ROOT/libiconv-1.14 $ make $ make install
installed files
bin/iconv include/*.h lib/charset.alias lib/libcharset.a lib/libcharset.la lib/libcharset.so lib/libcharset.so.1 lib/libcharset.so.1.0.0 lib/libiconv.la lib/libiconv.so lib/libiconv.so.2 lib/libiconv.so.2.5.1 lib/preloadable_libiconv.so share/doc/libiconv/*.html share/man/man?/*.?
PCRE 8.33をAndroid NDKでクロスコンパイルする
http://sourceforge.net/projects/pcre/files/pcre/ から pcre-8.33.tar.bz2 をダウンロードします。
$ tar xvjf pcre-8.33.tar.bz2 $ cd pcre-8.33 $ CFLAGS=-O2 LDFLAGS=-s ./configure --host=arm-linux-androideabi --prefix=$ANDROID_APP_ROOT/pcre-8.33 --enable-jit --enable-utf $ make $ make install
installed files
bin/pcre-config bin/pcregrep bin/pcretest include/*.h lib/libpcre.a lib/libpcre.la lib/libpcre.so lib/libpcre.so.1 lib/libpcre.so.1.2.1 lib/libpcrecpp.a lib/libpcrecpp.la lib/libpcrecpp.so lib/libpcrecpp.so.0 lib/libpcrecpp.so.0.0.0 lib/libpcreposix.a lib/libpcreposix.la lib/libpcreposix.so lib/libpcreposix.so.0 lib/libpcreposix.so.0.0.2 lib/pkgconfig/libpcre.pc lib/pkgconfig/libpcrecpp.pc lib/pkgconfig/libpcreposix.pc share/doc/pcre/* share/doc/pcre/html/* share/man/man1/pcre-config.1 share/man/man1/pcregrep.1 share/man/man1/pcretest.1 share/man/man3/*.3