日別アーカイブ: 2014年3月15日

Android NDK r9d の armeabi-v7a-hard と ABI

Android NDK r9d では、新しく APP_ABI に armeabi-v7a-hard が追加されました。
とはいえ端末側の ABI の種類が増えたわけではなく、hard-float を指定した
バイナリのビルドがより簡単に行えるようになります。

Android NDK

r9b/r9c では hard-float を使うために jni/Android.mk に直接オプションを
記述していました。

# android-ndk-r9b/r9c
# jni/Android.mk
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS+= -mhard-float -D_NDK_MATH_NO_SOFTFP=1
LOCAL_LDLAGS+= -lm_hard -Wl,--no-warn-mismatch
endif

r9d からは上記のような Android.mk の修正が不要になります。
APP_ABI に armeabi-v7a-hard を指定するだけで hard-float に対応します。
例えば ndk-build コマンドの引数で与えるなら下記の通り。

ndk-build APP_ABI=armeabi-v7a-hard

jni/Application.mk に書いておくなら下記の通り。

# jni/Application.mk
APP_ABI:= armeabi-v7a-hard armeabi x86 mips

APP_ABI:=all ではデフォルトの armeabi-v7a とみなされるので、
hard-float を使う場合は上記のように全部列挙しておく必要があります。

Android OS 側は softfp のままなので、hard-float が有効なのはあくまで
アプリケーション内の関数呼び出しに限定されます。
例えば OpenGL ES のような浮動小数点パラメータを持つ System API の
呼び出しは、これまでどおり softfp が用いられます。
hard-float といいつつ厳密には softfp も混在していることになります。

そのため OS から見れば従来のアプリケーションと全く同じなので、
バイナリを区別する必要がありません。

armeabi-v7a-hard でビルドしたバイナリも libs/armaebi-v7a に入ります。
他の APP_ABI と違い、armeabi-v7a と armeabi-v7a-hard の 2種類生成する
わけではないのでご注意ください。
どちら片方を選択します。

互換性が問題になるケースはおそらく外部ライブラリ利用時でしょう。
リンクするライブラリも下記いずれかの方法で hard-float に対応している
必要があります。

ライブラリの hard-float 対応手段は二通りあります。

 (1) ライブラリも hard-float でビルドする
 (2) ヘッダファイルに softfp 指定 __NDK_FPABI__ を追加する

(1) の場合は spftfp 版と hard-float 版ライブラリの両方を用意しておく
必要があります。

(2) はヘッダの関数宣言時に softfp 呼び出しを意味する __NDK_FPABI__ を
記述しておきます。(中身は __attribute__((pcs(“aapcs”))) )
この場合ライブラリは softfp 一種類だけです。

float fpfunc( float a, float b ) __NDK_FPABI__;

NDK の hard-float について詳しくは下記も参照してください。

Android NDK r9b と ARMv7A の hard-float

Android NDK で使用可能な ABI 指定のまとめ。

armeabi           ARMv5TE   FPU 無し        soft-float
armeabi-v7a       ARMv7A    VFPv3-D16       softfp
armeabi-v7a-hard  ARMv7A    VFPv3-D16       hard-float (softfp混在)
x86               x86       SSSE3           hard-float
mips              MIPS32R1  FPU             hard-float

ARM 以外は最初から FPU 必須で hard-float 相当です。
ちなみに ios は下記の通り。

armv6             ARMv6     VFPv2-D16       softfp
armv7             ARMv7A    VFPv3-D32 NEON  softfp
armv7s            ARMv7A    VFPv4-D32 NEON  spftfp
arm64             ARMv8     AArch64 NEON    hard-float

soft-float, softfp, hard-float の違い。

             FPU       浮動小数点演算          関数パラメータ
---------------------------------------------------------------------
soft-float   FPU無し   soft/ライブラリ呼び出し 整数レジスタ経由
softfp       FPUあり   hard/FPU が行う         整数レジスタ経由
hard-float   FPUあり   hard/FPU が行う         浮動小数点レジスタ直接

関連エントリ
Android NDK r9b と ARMv7A の hard-float
iPhone 5s A7 64bit CPU と AArch64 (arm64)
Nexus 7 の Ubuntu で ARM の abi softfp と hard-float を比べる