使用ndk生成arm64-v8a框架下的libiconv.a静态库以及编译64位so库
目录
build_native.bat的内容——执行ndk-build命令
生成arm64-v8a的libiconv.a静态库
1.下一个ndk版本,官网下就可以了,我用的是 android-ndk-r14b-linux-x86_64.zip 解压到到linux下
https://developer.android.google.cn/ndk/downloads/revision_history
2.下一个libiconv源码,不能用1.14(这个不能生成64位),我用的最新的1.16, 解压到到linux下。
http://ftp.gnu.org/pub/gnu/libiconv/
3.写一个编译脚本,放到第2步骤解压下的根目录下执行。使用make进行编译
内容如下,需要自行修改一下自己的最终输出的libiconv路径(脚本中的 –prefix值,最后到这个路径下找.a就行了)和ndk路径(脚本中的ANDROID_NDK)。
#!/bin/bash
export ANDROID_HOST=aarch64-linux-android
export ANDROID_BUILD=linux-x86_64
export ANDROID_ARCH=arm64
export ANDROID_NDK=/home/ftpuser1/android-ndk-r14b
export ANDROID_VERSION=24
export ANDROID_TOOLCHAIN_VERSION=4.9
export ANDROID_SYSROOT=$ANDROID_NDK/platforms/android-$ANDROID_VERSION/arch-$ANDROID_ARCH
export CFLAGS=--sysroot=$ANDROID_SYSROOT
export CPPFLAGS=--sysroot=$ANDROID_SYSROOT
export AR=$ANDROID_HOST-ar
export RANLIB=$ANDROID_HOST-ranlib
export PATH=$ANDROID_NDK/toolchains/$ANDROID_HOST-$ANDROID_TOOLCHAIN_VERSION/prebuilt/$ANDROID_BUILD/bin:$PATH
./configure --host=$ANDROID_HOST --with-sysroot=$ANDROID_SYSROOT --prefix=/home/ftpuser1/libiconv --enable-static --disable-shared
make
make install
exit
注意点
1.
如果使用libiconv1.14源码用上述脚本编译64位的话 会出现以下错误:
Invalid configuration `aarch64-linux-android‘: machine `aarch64′ not recognized
2.
最后生成的.a存放目录是根据我脚本中的配置,在/home/ftpuser1/libiconv/lib/libiconv.a
头文件在的/home/ftpuser1/libiconv/include/libiconv.h
3.
使用 objdump -a libiconv.a (动态库用 file XXX.so)可以查看格式,应该是elf64-little的
之前我生成了一个错误的格式,是elf64-86-64的。
如果使用elf64-86-64格式的.a 去参与编译arm64-v8a的so库的时候就会出现如下错误:
arm64-v8a/libiconv.a(iconv.o): Relocations in generic ELF (EM: 62)
arm64-v8a/libiconv.a: error adding symbols: File in wrong format
参考
https://medium.com/@zw3rk/building-iconv-for-android-e3581a52668f
编译64位so库
项目中的一个库目录如下:
目录结构
–jni文件夹
–Android.mk
—Application.mk文件
Android.mk内容
例子1:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cpp
LOCAL_MODULE:= XX
LOCAL_PRELINK_MODULE := true
LOCAL_SRC_FILES := XX1.cpp XX2.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_CFLAGS := -Wall -std=c++11
include $(BUILD_SHARED_LIBRARY)
例子2:
LOCAL_MODULE_FILENAME := libxxx
T_MY_FILES += $(wildcard $(LOCAL_PATH)/../../xxx/*.cpp) \
$(wildcard $(LOCAL_PATH)/../../xxx/simulation2/system/*.cpp) \
MY_FILES := $(T_MY_FILES:$(LOCAL_PATH)/%=%)
LOCAL_SRC_FILES += $(MY_FILES)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../xxx\
$(LOCAL_PATH)/../../xxx/boost/include \
$(LOCAL_PATH)/../../xxx/simulation2/system
LOCAL_C_INCLUDES += ${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.9/include
LOCAL_CFLAGS := -DAndroid
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/support)
include $(BUILD_SHARED_LIBRARY) 生成动态库
include $(BUILD_STATIC_LIBRARY) 生成静态库
Application.mk内容
https://developer.android.com/ndk/guides/application_mk?hl=zh-cn(Application.mk 指定 ndk-build 的项目范围设置。默认情况下,它位于应用项目目录中的 jni/Application.mk 下)
一个例子:
APP_ABI:=armeabi-v7a
APP_STL := stlport_static
APP_CPPFLAGS +=-fexceptions
另一个例子:
APP_ABI := armeabi-v7a
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -std=c++11
APP_OPTIM := release
APP_PLATFORM := android-17
APP_BUILD_SCRIPT := ./jni/Android.mk
build_native.bat的内容——执行ndk-build命令
@echo off
set DIR=%~dp0
set APP_ANDROID_ROOT=%DIR%
echo - config:
echo ANDROID_NDK_ROOT = %ANDROID_NDK_ROOT%
echo APP_ANDROID_ROOT = %APP_ANDROID_ROOT%
rem if use quick-cocos2d-x mini, uncomments line below
rem set NDK_BUILD_FLAGS=CPPFLAGS=-DQUICK_MINI_TARGET=1 QUICK_MINI_TARGET=1
rem if use DEBUG, set NDK_DEBUG=1, otherwise set NDK_DEBUG=0
set NDK_DEBUG=0
echo - cleanup
if exist "%APP_ANDROID_ROOT%obj" rmdir /s /q "%APP_ANDROID_ROOT%obj"
if exist "%APP_ANDROID_ROOT%libs" rmdir /s /q "%APP_ANDROID_ROOT%libs"
mkdir "%APP_ANDROID_ROOT%libs"
echo Using prebuilt externals
"%ANDROID_NDK_ROOT%\ndk-build" -B %ANDROID_NDK_BUILD_FLAGS% NDK_DEBUG=%NDK_DEBUG% NDK_APPLICATION_MK=Application.mk NDK_PROJECT_PATH=%APP_ANDROID_ROOT% %NDK_BUILD_FLAGS% -C %APP_ANDROID_ROOT%
注意:
将 APP_PLATFORM 设置为高于应用的 minSdkVersion 可能会生成一个无法在旧设备上运行的应用。
在大多数情况下,库将无法加载,因为它们引用了在旧设备上不可用的符号。
一些小知识
交叉编译vs本地编译
交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序:比如,我们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。
ndk下载
ndk编译C/C++源码生成.so文件
使用的是unity2018,需要下载android-ndk-r16
各版本ndk的下载地址 https://developer.android.google.cn/ndk/downloads/revision_history
解压以后设置两个环境变量:
ANDROID_NDK
PATH
windows下测试是否成功输入
打开cmd输入ndk-build回车,如下图则表示安装成功。