ndk-build 输出‘添加符号时出错。文件格式错误’
ndk-build outputs ‘error adding symbols. File in wrong format’
我想在我的 Android 项目中使用用 C++ 编写的 exiv2 库。为此,我尝试使用 Android NDK.
交叉编译库
对于交叉编译,我遵循以下步骤:
将ndk路径添加到变量PATH
$ PATH="/home/patrycja/android-packages/ndk:${PATH}"
$ export PATH
为 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.
设置一些环境变量,以便配置和构建过程使用正确的编译器。
$ 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++'
构建静态库和足够的头文件
./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.a
和 include
文件夹复制到 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 <= 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
您至少为 armv5+ 设备 运行 编译了 exiv2 Lollipop。这里 ndk-build 失败了,因为它试图从它正在构建的 arm64-v8a 库中 link 它。
不使用 ndk-build 的交叉编译很难在 Android 上正确运行,尤其是因为您不仅要支持 armv5,还要支持 armv7、x86、x86_64、arm64-v8a.. .
您应该首先将 --platform
选项设置为与最低 SDK 级别相同的级别。然后重建你的库并将它放在 ../prebuild/armeabi
下。
然后为 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.
我想在我的 Android 项目中使用用 C++ 编写的 exiv2 库。为此,我尝试使用 Android NDK.
交叉编译库对于交叉编译,我遵循以下步骤:
将ndk路径添加到变量PATH
$ PATH="/home/patrycja/android-packages/ndk:${PATH}" $ export PATH
为 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.
设置一些环境变量,以便配置和构建过程使用正确的编译器。
$ 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++'
构建静态库和足够的头文件
./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.a
和 include
文件夹复制到 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 <= 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
您至少为 armv5+ 设备 运行 编译了 exiv2 Lollipop。这里 ndk-build 失败了,因为它试图从它正在构建的 arm64-v8a 库中 link 它。
不使用 ndk-build 的交叉编译很难在 Android 上正确运行,尤其是因为您不仅要支持 armv5,还要支持 armv7、x86、x86_64、arm64-v8a.. .
您应该首先将 --platform
选项设置为与最低 SDK 级别相同的级别。然后重建你的库并将它放在 ../prebuild/armeabi
下。
然后为 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.