ndk-buildを使わないでプログラムをビルドする
普段は、ndk-buildでビルドをしているのが楽だし、便利なんですが、時に、外部のライブラリがconfigureとか使ってて、自前でAndroid.mkとかを作るのが面倒なことがあります。というか、試しに自前で作ってみようとしたけど、新旧の情報が錯綜しており、また、C++を使った場合のリンク方法がさっぱりとか、とりあえず、root化した端末でコマンドラインベースのコードを動かしてみたいけど・・・な場合にどうやれば良いのか全く分かりませんでした。
結局、当たり前ながら、じゃぁ、ndk-buildは何をやってるんでございましょうということになるんですが、これを見てみるために凄く簡単なサンプルを作ってみます。
sample/
jni/
Application.mk
Android.mk
sample.cpp
というディレクトリ構造で、
# Application.mk APP_ABI := armeabi-v7a # RTTI、例外を使うためにstatic GNU STLを利用する APP_STL := gnustl_static
# Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := sample LOCAL_CFLAGS := LOCAL_SRC_FILES += sample.cpp LOCAL_STATIC_LIBRARIES += gnustl_static include $(BUILD_EXECUTABLE)
// sample.cpp #include <iostream> #include <vector> int main(int argc, char* argv[]) { // 単にSTLが使えているかどうかをチェックしたい std::vector<int> v(256); std::cout << "Hello, world." << v.size() << std::endl; }
っていうのを作って、jni/ディレクトリで
ndk-build -n
とやると(ちなみに、/opt/android-ndk-r7にAndroid NDK r7をインストールしている)、
rm -f /somewhere/sample/libs/armeabi/lib*.so /somewhere/sample/libs/armeabi-v7a/lib*.so /somewhere/sample/libs/x86/lib*.so rm -f /somewhere/sample/libs/armeabi/gdbserver /somewhere/sample/libs/armeabi-v7a/gdbserver /somewhere/sample/libs/x86/gdbserver rm -f /somewhere/sample/libs/armeabi/gdb.setup /somewhere/sample/libs/armeabi-v7a/gdb.setup /somewhere/sample/libs/x86/gdb.setup mkdir -p /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/ echo """Compile++ thumb"" : helloworld <= sample.cpp" ccache /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ -MMD -MP -MF /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/sample.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -fno-exceptions -fno-rtti -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -I/opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include -I/opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include -I/opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include -I/opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include -I/somewhere/sample/jni -DANDROID -Wa,--noexecstack -fexceptions -frtti -fexceptions -frtti -O2 -DNDEBUG -g -fexceptions -frtti -I/opt/android-ndk-r7/platforms/android-3/arch-arm/usr/include -c /somewhere/sample/jni/sample.cpp -o /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/sample.o mkdir -p /somewhere/sample/obj/local/armeabi-v7a/ echo "Prebuilt : libgnustl_static.a <= <NDK>/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/" cp -f /opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_static.a /somewhere/sample/obj/local/armeabi-v7a/libgnustl_static.a mkdir -p /somewhere/sample/obj/local/armeabi-v7a/ echo "Executable : helloworld" /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ -Wl,--gc-sections -Wl,-z,nocopyreloc --sysroot=/opt/android-ndk-r7/platforms/android-3/arch-arm /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/sample.o /somewhere/sample/obj/local/armeabi-v7a/libgnustl_static.a /somewhere/sample/obj/local/armeabi-v7a/libgnustl_static.a /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-z,noexecstack -lc -lm -o /somewhere/sample/obj/local/armeabi-v7a/helloworld echo "Install : helloworld => libs/armeabi-v7a/helloworld" mkdir -p /somewhere/sample/libs/armeabi-v7a install -p /somewhere/sample/obj/local/armeabi-v7a/helloworld /somewhere/sample/libs/armeabi-v7a/helloworld /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-strip --strip-unneeded /somewhere/sample/libs/armeabi-v7a/helloworld
という感じのことをやっている事が分かる。
つまり、まとめると、コンパイル、リンク、リンク後処理として、
# コンパイル /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ \ -MMD -MP -MF \ /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/sample.o.d \ -fpic \ -ffunction-sections -funwind-tables -fstack-protector \ -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ \ -Wno-psabi \ -march=armv7-a -mfloat-abi=softfp -mfpu=vfp \ -fno-exceptions -fno-rtti \ -mthumb \ -Os \ -fomit-frame-pointer \ -fno-strict-aliasing \ -finline-limit=64 \ -I/opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include \ -I/opt/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include \ -I/somewhere/sample/jni \ -DANDROID \ -Wa,--noexecstack \ -O2 -DNDEBUG -g \ -I/opt/android-ndk-r7/platforms/android-3/arch-arm/usr/include \ -c /somewhere/sample/jni/sample.cpp \ -o /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/sample.o
# リンク /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ \ -Wl,--gc-sections \ -Wl,-z,nocopyreloc \ --sysroot=/opt/android-ndk-r7/platforms/android-3/arch-arm \ /somewhere/sample/obj/local/armeabi-v7a/objs/helloworld/sample.o \ /somewhere/sample/obj/local/armeabi-v7a/libgnustl_static.a \ /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a \ -Wl,--fix-cortex-a8 \ -Wl,--no-undefined \ -Wl,-z,noexecstack \ -lc -lm \ -o /somewhere/sample/obj/local/armeabi-v7a/helloworld
# デバッグ情報の除去 /opt/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-strip \ --strip-unneeded \ /somewhere/sample/libs/armeabi-v7a/helloworld
ということが分かる(一部、重複など簡略化済み)。
あとは、この辺を配慮した上でconfigure様に、CC/CXX/LD/CFLAGS/LDFLAGSなどを設定してあげれば良い感じみたいだ。