应用只支持arm平台,因为pad和部分手机是x86的CPU架构,所以启动应用会直接宕机,所以需要编译x86平台的底层库。
发现在5.0的x86上运行没有问题,然后直接试了8.0,提示 代码重定位:
E/linker: "xxxxxxxxxx==/lib/x86/xxx.so" has text relocations
java.lang.UnsatisfiedLinkError: dlopen failed: "xxxxxx==/lib/x86/xxx.so" has text relocations
网上说6.0后因为代码重定位,直接宕机,6.0前会有警告,
用readelf命令检验后,发现动态库的确是做了代码重定位,
readelf -d xxx.so |grep TEXTREL :
0x00000016 (TEXTREL) 0x0
0x0000001e (FLAGS) SYMBOLIC TEXTREL BIND_NOW
于是检查所有库的编译选项是否加入fPic(Position Independent Code,表明使用地址无关代码)
发现所有库都加入了该编译选项,
于是又对引用的静态库也使用readelf命令检验,发现都没有输出,即表示地址无关,没有重定向。
在快要灰心的时候,想起了readelf是检查动态库,于是将引用的静态库编译为动态库后,
使用readelf命令检验,确实是有输出,是ffmpeg库,
那接下来的问题就是处理ffmpeg库中的代码重定位问题,用尽了各种方法对fPic的编译配置,无果
在将要灰心的时候,突然看到stackoverflow上有网友讲,–disable-asm,抱着尝试的态度编译,运行后,真的就成功了,在Android 8.0 x86上运行没有问题。
--disable-asm disable all assembly optimizations
附上编译脚本:
#!/bin/bash
export TMPDIR=./android
NDK=/usr/ndk/android-ndk-r10e
SYSROOT=$NDK/platforms/android-9/arch-x86/
TOOLCHAIN=$NDK/toolchains/x86-4.9/prebuilt/linux-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--disable-shared \
--enable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--disable-asm \
--disable-yasm \
--cross-prefix=$TOOLCHAIN/bin/i686-linux-android- \
--target-os=linux \
--arch=x86 \
--enable-cross-compile \
--enable-gpl \
--enable-version3 \
--enable-nonfree \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-avfilter \
--disable-avformat \
--disable-postproc \
--disable-swresample \
--disable-avresample \
--disable-debug \
--disable-parsers \
--enable-parser=h264 \
--enable-parser=hevc \
--disable-stripping \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=x86
PREFIX=./android/$CPU
build_one