《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-r10e
function 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
fi
make 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 message
Standard 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 RCFLAGS
Configuration 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 code
Cross-compilation:
--host=HOST build programs to run on HOST
--cross-prefix=PREFIX use PREFIX for compilation tools
--sysroot=SYSROOT root of cross-build tree
External 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 路径的目录,即交叉编译器的连接根目录。