Android 端IjkPlayer交叉编译的逻辑分析
交叉编译的原理
所谓交叉编译,就是一个平台(如PC)上生成另外一个平台(Android,iOS或者其他嵌入式设备)的可执行代码。
为什么要交叉编译
在一般的嵌入式设备开发系统中(Android,ios),运行程序的目标平台其存储空间和运算能力都是有限的。
交叉编译的工具
无论是PC机上的编译还是嵌入式设备中的编译,它们都会提供以下几个工具:CC、AS、AR、LD、NM、GDB。那么,这几个工具到底是做什么用的呢?下面就逐一解释下。
CC:编译器,对C源文件进行编译处理,生成汇编语言。
AS:将汇编语言生成目标文件.
AR:打包器,用于库操作,通过该工具从一个库中删除或者增加代码模块.
LD:连接器,将多个目标文件链接成一个库或者可执行文件.
GDB:调试工具.
STRIP:以最终可执行的文件或者库文件作为输入,然后消除掉其中的源码.
NM:查看静态库中的符号表.
Objdump:查看静态库或者动态库的方法签名.
Android NDK 支持的编译器
Android NDK 提供了两种编译器: GCC、Clang
Android NDK从r11开始建议大家切换到clang。并且把GCC标记为deprecated,将GCC版本锁定在GCC 4.9不再更新。
- PSA: Everyone should be switching to Clang.
- Clang has been updated to 3.8svn (r243773, build 2481030).
-
Time to start using Clang if you haven’t already. If you have
problems with Clang, please file bugs! -
The NDK will not be upgrading to 5.x, nor will we be accepting non-critical backports.
Maintenance for miscompiles and internal compiler errors in 4.9 will be handled on a case by case basis.
Note that this is now a nearly pure upstream clang.
Also note that Clang packaged in the Windows 64 NDK is actually 32-bit.
GCC in the NDK is now deprecated. -
GCC 4.8 has been removed. All targets now use GCC 4.9.
-
Synchronized with google/gcc-4_9 to r224707 (from r214835).
-
Android平台的交叉编译
Android NDK 的目录结构
ndk-build: 该shell脚本用来构建项目动态库
ndk-gdb: 该shell脚本用GUN调试器调试Native代码
ndk-stack: 该shell脚本分析Native代码崩溃是的堆栈信息
build: 该目录包含NDK构建系统的所有模块
platform: 该目录包含支持不同Android目标版本的头文件和库文件,NDK构建系统会根据具体的配置来引用指定平台下的头文件和库文件
toolchiains:该目录包含目前NDK所支持的不同平台下的交叉编译器------ARM、x86、MIPS
高版本NDK toolchiains目录:
Clang 主要使用llvm 实现交叉编译
GCC 编译 FFmpeg
Android交叉编译主要使用android NDK目录结构中platform、toolchiains;
现在我主要讲解利用GCC编译器实现交叉编译,Clang编译器目前主要是在高版本的NDK中才支持,后面讲解如何利用Clang编译器交叉编译FFmpeg 4.0+;
建议GCC编译FFmpeg 4.0以下的版本,用Clang编译FFmpeg4.0以上的版本,否则你会发现用GCC编译FFmpeg4.0以上的版本会出现各种错误;
- FFmpeg 下载 : http://ffmpeg.org/download.html (下载3.2.14)
修改FFmpeg的configure,下载FFmpeg源代码之后,首先需要对源代码中的 - configure文件进行修改。由于编译出来的动态库文件名的版本号在.so之后(例如“libavcodec.so.5.100.1”),而android平台不能识别这样文件名,所以需要修改这种文件名。在configure文件中找到下面几行代码:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'
替换为下面内容:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
- 生成FFmpeg的头文件和类库文件
cd ffmpeg-3.2.14
export NDK=/Users/videopls/android/android-ndk-r14b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-9/arch-arm
export PREFIX=../ffmpeg_3.2.14_lib
build_one(){
./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-small \
--disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-debug --disable-ffserver \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a"
}
build_one
make clean
make -j8
make install
cd ..
- FFmpeg 的裁剪及链接x264、fdk_aac等第三方库这里就不讲解了,如果想了解的可以通过 ./configure -h
查看每个参数的具体含义及网上搜索资料;
Clang 编译 FFmpeg
Clang 主要使用NDK → toolchiains → llvm 中的编译工具实现交叉编译 ;
- clang 编译环境的位置: toolchains/llvm/prebuilt/darwin-x86_64
- 编译工具的内容:toolchains/llvm/prebuilt/darwin-x86_64/bin
aarch64-linux-android-addr2line
aarch64-linux-android-ar
aarch64-linux-android-as
aarch64-linux-android-c++filt
aarch64-linux-