《ffmpeg-android dlopen failed: library “libclang_rt.ubsan_standalone-aarch64-android.so“ not found》
《nkd 编译ffmpeg错误: clang is unable to create an executable file. C compiler test failed.》
ndk编译libx264。(20210728)
一:环境:虚拟机Ubuntu+ndkandroid-ndk-r10e( Android NDK, Revision 10e (May 2015))
libx264
libx264自身的configure 默认使用gcc , 所以使用最新的ndk编译比较曲折,这里选用老板的ndkandroid-ndk-r10e
编译出来的库在源码根目录的 android/xxxabi下面
除了lib库,还有x264可执行程序,如果设备有root权限的,可以拷贝进去运行:(data目录)
二:编译流程:
在libx264源码根目录运行如下shell脚本
(将其中的ndk路径设置为下载解压好的ndk10e的路径,如果需要编译32bit的将下面--arm--注释的打开,--arm64--的注释掉)
#!/bin/bash
#NDK=/work/NDK/android-ndk-r18b
NDK=/work/NDK/android-ndk-r10efunction build_android
{
./configure \
--prefix=$PREFIX \
--enable-static \
--cross-prefix=$CROSS_PREFIX \
--sysroot=$SYSROOT \
--enable-pic \
--extra-cflags="-fPIC -fpic" \
--extra-ldflags=" -fPIE -pie" \
--host=aarch64-linux-android
if [ $? != 0 ];
then echo -e "\033[31mErr! get the detail message in config.log \033[0m" exit 0
fimake clean
make -j8
make install
}#------------arm64----------------
#SYSROOT=$NDK/sysroot //ndk18
SYSROOT=$NDK/platforms/android-21/arch-arm64
CROSS_PREFIX=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/arm64-v8a##------------arm--------------
#SYSROOT=$NDK/platforms/android-21/arch-arm
#CROSS_PREFIX=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
#PREFIX=$(pwd)/android/armeabi-v7a#----其他的可以参考对应NDK下的目录路径即可build_android
三:
问题1:编译libx264主要是ffmpeg需要,但是和编译ffmpeg不同,当前的libx264库提供的 configure竟然是没有配置使用clang 编译器,执行#./configure --help可以看到,可以设置--cross-prefix 交叉编译选项,没有-cc -cxx 的选项,添加上-cc -cxx的配置会报错,不添加的话, configure 里面默认使用的 CROSS_PREFIX-gcc 进行编译,最新的ndk (21) 已经抛弃了gcc, 没有gcc这个工具了,所以configure直接就会 cc test err,找不到编译器。
三种方法:
1.0 手动修改libx264 里面的configure, 让其像ffmpeg一样可以单独配置 -cc -cxx。 (weinan)
2.0 在网上看到有些做法是,export CC=xx-clang export CXX=xx-clang++
configure 脚本没有提供配置的接口,这里通过export 导出变量到当前shell 环境中,这种方法设置 编译器
3.0 既然libx264默认使用gcc, 就换一个支持gcc的ndk吧。
这里碰到一个坑,下载了android-ndk-r18b ,虽然这个ndk里面确实找到了 gcc, 但是这个交叉编译器工具链的gcc 有毛病,编译可以,连接就默认用到ubuntu 系统自身的 /usr/bin/ld 工具了,很是坑:
写个main空函数文件用它gcc 交叉编译一下都会报连接错误:
#android-ndk-r18b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin$ aarch64-linux-android-gcc my_test.c
/usr/bin/ld: unrecognised emulation mode: aarch64linux
Supported emulations: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu i386linux elf_l1om elf_k1om i386pep i386pe
clang: error: linker command failed with exit code 1 (use -v to see invocation)
所以这里干脆找了个 老版本的ndk:
Android NDK, Revision 10e (May 2015)
编译OK
问题2:编译出来的 x264 无法在设备上运行:
在连接的时候加上参数 -fPIE -pie 即可。
问题3: 添加上 -pie 之后,编译报错,undefined reference to 'main'
这是编译动态库 时添加了参数-pie (位置无关码)造成的问题(本篇把--enable-shared 配置项去掉了,只编译静态库),本来加这个参数是给 编译x264可执行程序使用的。 去掉这个 -pie参数,即可,或者单独修改configure之后的makefile, 只对 编译x264可执行文件的编译项添加 -pie参数:
x264$(EXE): $(GENERATED) .depend $(OBJCLI) $(CLI_LIBX264)$(LD)$@ $(OBJCLI) $(CLI_LIBX264) $(LDFLAGSCLI) $(LDFLAGS) -pie
@u-xiancan:~/share_can/libx264/libx264_for_android/x264-master$ ./configure --help
Usage: ./configure [options]Help:-h, --help print this messageStandard options:--prefix=PREFIX install architecture-independent files in PREFIX[/usr/local]--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX[PREFIX]--bindir=DIR install binaries in DIR [EPREFIX/bin]--libdir=DIR install libs in DIR [EPREFIX/lib]--includedir=DIR install includes in DIR [PREFIX/include]--extra-asflags=EASFLAGS add EASFLAGS to ASFLAGS--extra-cflags=ECFLAGS add ECFLAGS to CFLAGS--extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS--extra-rcflags=ERCFLAGS add ERCFLAGS to RCFLAGSConfiguration options:--disable-cli disable cli--system-libx264 use system libx264 instead of internal--enable-shared build shared library--enable-static build static library--disable-bashcompletion disable installation of bash-completion script--enable-bashcompletion force installation of bash-completion script--bashcompletionsdir=DIR install bash-completion script in DIR [auto]--disable-opencl disable OpenCL features--disable-gpl disable GPL-only features--disable-thread disable multithreaded encoding--disable-win32thread disable win32threads (windows only)--disable-interlaced disable interlaced encoding support--bit-depth=BIT_DEPTH set output bit depth (8, 10, all) [all]--chroma-format=FORMAT output chroma format (400, 420, 422, 444, all) [all]Advanced options:--disable-asm disable platform-specific assembly optimizations--enable-lto enable link-time optimization--enable-debug add -g--enable-gprof add -pg--enable-strip add -s--enable-pic build position-independent codeCross-compilation:--host=HOST build programs to run on HOST--cross-prefix=PREFIX use PREFIX for compilation tools--sysroot=SYSROOT root of cross-build treeExternal library support:--disable-avs disable avisynth support--disable-swscale disable swscale support--disable-lavf disable libavformat support--disable-ffms disable ffmpegsource support--disable-gpac disable gpac support--disable-lsmash disable lsmash support
其他的一些配置选项:
--disable-asm disable platform-specific assembly optimizations
默认开启,对于不同平台可以进行指令级别的专项优化
--enable-pic build position-independent code
和上面添加的 -fpic 参数同样效果
问题4: configure 出错应该第一时间查看 config.log ,里面详细记录有日志,如果 出现如下错误:
cannot find crtbegin_dynamic.o: No such file or directory
......
cannot find -lc
......
cannot find -ldl
--sysroot 参数可能设置错误,在ndk目录中找一下这个 sysroot目录,或者直接找 包含 /usr/include 路径的目录,即交叉编译器的连接根目录。