ndk-build输出错误添加符号。文件格式错误“

时间:2015-06-04 15:09:08

标签: android c++ android-ndk exiv2

我想在我的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
    
  5. 结果我创建了'build'类别文件:

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

    我将创建的静态库libexiv2.ainclude文件夹复制到我appName/src/main/jni/prebuild的Android项目中。

    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

1 个答案:

答案 0 :(得分:4)

你为至少运行 Lollipop armv5 + 设备编译了exiv2。这里ndk-build失败了,因为它试图从它正在构建的arm64-v8a库中链接它。

在不使用ndk-build的情况下进行交叉编译很难在Android上运行,特别是因为你不仅应该支持armv5,还需要支持armv7,x86,x86_64,arm64-v8a ......

您应首先将--platform选项设置为与最低SDK级别相同的级别。然后重建您的lib并将其放在../prebuild/armeabi下。 然后交叉编译你的lib也用于x86架构:

./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重复相同的过程。

最后,您可以使用TARGET_ARCH_ABI变量在 Android.mk 中包含正确的.a,如下所示:

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.