9

Android プロジェクトで C++ で記述された exiv2 ライブラリを使用したいと考えています。そのために、Android NDK を使用してライブラリをクロスコンパイルしてみます。

クロスコンパイルについては、以下の手順に従います。

  1. ndk パスを変数 PATH に追加します

    $ PATH="/home/patrycja/android-packages/ndk:${PATH}"
    $ export PATH 
    
  2. Android 用の C/C++ をクロスコンパイルするための標準ツールチェーンをインストールします。

    ./make-standalone-toolchain.sh --platform=android-21 --install-dir=/tmp/my-android-toolchain --ndk-dir='/home/patrycja/android-packages/ndk/' --toolchain=arm-linux-androideabi-4.9 --system=linux-x86_64
    
    Copying prebuilt binaries...
    Copying sysroot headers and libraries...
    Copying c++ runtime headers and libraries...
    Copying files to: /tmp/my-android-toolchain
    Cleaning up...
    Done.
    
  3. 構成とビルド プロセスで適切なコンパイラが使用されるように、いくつかの環境変数を設定します。

    $ export PATH=/tmp/my-android-toolchain/bin:$PATH
    $ export CC="arm-linux-androideabi-gcc"
    $ export CXX="arm-linux-androideabi-g++"
    $ export CFLAGS='-mthumb -O2' 
    $ export CXXFLAGS='-mthumb -O2' 
    $ export LDFLAGS='-Wl,--fix-cortex-a8' 
    $ export LIBS='-lstdc++ -lsupc++' 
    
  4. 静的ライブラリと十分なヘッダーを構築する

    ./configure --prefix=$(pwd)/build --host=arm-linux-androideabi --disable-shared --disable-xmp --disable-nls
    

その結果、「ビルド」カテゴリ ファイルを作成しました。

    ├── bin
    │   └── exiv2
    ├── include
    │   └── exiv2
    │       ├── *.hpp
    │
    ├── lib
    │   ├── libexiv2.a
    │   ├── libexiv2.la
    │   └── pkgconfig
    │       └── exiv2.pc
    └── share
        └── man
            └── man1
                └── exiv2.1

作成した静的ライブラリlibexiv2.aincludeフォルダーを Android プロジェクトにコピーしましたappName/src/main/jni/prebuild

Android.mk次のようになります。

LOCAL_PATH := $(call my-dir)

#static library info
LOCAL_MODULE := exiv2
LOCAL_SRC_FILES := ../prebuild/libexiv2.a
LOCAL_EXPORT_C_INCLUDES := ../prebuild/include/
LOCAL_EXPORT_LDLIBS := -lz
include $(PREBUILT_STATIC_LIBRARY)


#wrapper info
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../prebuild/include/
LOCAL_MODULE    := helloJNI
LOCAL_SRC_FILES := helloJNI.cpp
LOCAL_STATIC_LIBRARIES := exiv2
include $(BUILD_SHARED_LIBRARY)

Android のラッパーで、ライブラリを使用しようとしています。次のようになります。

#include <string.h>
#include <jni.h>
#include <exiv2/exiv2.hpp>

extern "C" {

JNIEXPORT jstring JNICALL Java_com_example_patrycja_testndi2_MyActivity_helloJNI(JNIEnv *env, jobject thiz)
    {
        std::ostringstream os;
        std::string file("/storage/emmc/DCIM/100MEDIA/IMAG0021.jpg");
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
        return env->NewStringUTF("asldjaljd");
    } 
}

ただしndk-build、見つからないことが出力されます。

[arm64-v8a] Compile++      : helloJNI &lt;= helloJNI.cpp
[arm64-v8a] SharedLibrary  : libhelloJNI.so
jni/../prebuild/libexiv2.a: error adding symbols: File in wrong format
collect2: error: ld returned 1 exit status
make: *** [obj/local/arm64-v8a/libhelloJNI.so] Error 1

クロスコンパイルのフラグに何か問題があると思います。いくつかのオプションを試しましたが、まだ何かが間違っています。 私は次の命令に従いました: https://groups.google.com/forum/#!topic/android-ndk/mYh1LzMu_0U

4

1 に答える 1

7

少なくともLollipopを実行しているarmv5+デバイス用に exiv2 をコンパイルしました。ここで ndk-build は、ビルド中の arm64-v8a ライブラリからリンクしようとしているため失敗します。

特に armv5 だけでなく、armv7、x86、x86_64、arm64-v8a などもサポートする必要があるため、ndk-build を使用せずにクロス コンパイルを行うのは Android では困難です。

最初に、--platformオプションを最小 SDK レベルと同じレベルに設定する必要があります。次に、lib を再構築して、下に置きます../prebuild/armeabi。次に、x86 アーキテクチャ用の lib もクロス コンパイルします。

./make-standalone-toolchain.sh --platform=android-9 --install-dir=/tmp/my-android-toolchain-x86 --ndk-dir='/home/patrycja/android-packages/ndk/' --arch=x86 --toolchain=x86-4.8 --system=linux-x86_64

$ export PATH=/tmp/my-android-toolchain-x86/bin:$PATH
$ export CC="i686-linux-android-gcc"
$ export CXX="i686-linux-android-g++"
$ export CFLAGS='-O2 -mtune=atom -mssse3 -mfpmath=sse' 
$ export CXXFLAGS='-O2 -mtune=atom -mssse3 -mfpmath=sse' 
$ export LDFLAGS='' 
$ export LIBS='-lstdc++ -lsupc++' 

./configure --prefix=$(pwd)/build-x86 --host=x86 --disable-shared --disable-xmp --disable-nls

作成した .a を に移動し../prebuild/x86ます。

理想的には、armeabi-v7a、mips、mips64、arm64-v8a についても同じプロセスを繰り返す必要があります。

最後に、次のように、変数を使用してAndroid.mk内に適切な .a を含めることができます。TARGET_ARCH_ABI

LOCAL_PATH := $(call my-dir)

#static library info
LOCAL_MODULE := exiv2
LOCAL_SRC_FILES := ../prebuild/$(TARGET_ARCH_ABI)/libexiv2.a
LOCAL_EXPORT_C_INCLUDES := ../prebuild/include/
LOCAL_EXPORT_LDLIBS := -lz
include $(PREBUILT_STATIC_LIBRARY)

#wrapper info
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../prebuild/include/
LOCAL_MODULE    := helloJNI
LOCAL_SRC_FILES := helloJNI.cpp
LOCAL_STATIC_LIBRARIES := exiv2
include $(BUILD_SHARED_LIBRARY)

Application.mk内(存在しない場合は新しいファイルを作成します) で、サポートするアーキテクチャと対象とする最小プラットフォームを指定します。

APP_ABI := armeabi x86 # ideally, this should be set to "all"
APP_PLATFORM := android-14 # should the same as -platform and your minSdkVersion.
于 2015-06-11T16:13:19.487 に答える