Ubuntu16.0.4
android-ndk-r21c-linux-x86_64
设置环境变量的方法有三种:
export
envprint
可以查看终端下所有环境变量。我们编译Android端可用的代码,首先需要指定CC
工具就是C语言编译器,如果不指定我们使用的是Linux下默认的CC,编译出来的程序也就只能Linux下可用了,对于Android平台不可用,毕竟二者还是有区别的,所以我们需要指定我们的CC。CC的路径就在我们的NDK路径下,NDK包含了各架构的编译工具,当然也包括CXX
C++语言编译器。下面会具体讲到。 其次我们需要指定库,我们编译的ffmpeg如果想集成fdk-aac等三方库就得引入三方库的动态链接库的和头文件,指定外部库的编译指令需要有CFLAGS
(C编译程序的命令行参数。) -I三方库的头文件路径
,以及LDFLAGS
(链接器的命令行参数)-L三方库的库文件路径(动态或静态库)
尽量不要用中文,且注意NDK版本,如果编译出现奇怪的问题无法解决的话不妨换个NDK版本试试吧,太老的就不要用了。
打开我们的环境变量文件
vim ~/.bashrc
在最后加上我们的NDK的路径,并重新赋值PATH,PATH是系统默认的环境变量,我们需要再它的基础上添加,不然会导致原有的环境变量不可用
export NDKROOT=/home/zhoubin/Documents/android-ndk-r21c
export PATH=$NDKROOT:$PATH
使环境变量生效
source ~/.bashrc
在解压的源码路径下编写一个build_v7.sh(名字你随便起)
#NDKROOT我们已经配置环境变量了所以可以直接用,TOOLCHAIN我们在这设置一个零时变量
TOOLCHAIN="$NDKROOT/toolchains/llvm/prebuilt/linux-x86_64"
#重新赋值我们的CC和CXX,用我们Android自己的C编译器,而且会有32和64之分
#32位V7的我们用armv7a-linux-androideabi
#64位V8的我们用aarch64-linux-android
HOST=armv7a-linux-androideabi
V=21
#至于这个21你可以自己选版本号,看你的目录下有哪些版本
export CC=$TOOLCHAIN/bin/$HOST$V-clang
export CXX=$TOOLCHAIN/bin/$HOST$V-clang++
echo $CC
#PREFIX定义我们的编译输出目录,这里指的是上级目录下新建armeabi-v7a文件夹存放
PREFIX=$(dirname $(pwd))/armeabi-v7a
#最简版本 指定编译动态链接库不编译静态库
#其它参数配置可以在lame源码根目录下执行./configure -h查看默认和支持的配置
function build_config
{
./configure \
--enable-static=no \
--host=$HOST \ #我们代码需要运行的平台
--disable-frontend \ #不编译可执行的命令程序
--prefix=$PREFIX
}
build_config
make clean
make -j8 #8是线程数 数字越大编译速度越快,前提是你电脑支持
make install
如果直接这样编译是会出问题的,问题出在./fdk-aac-2.0.2/libSBRdec/src/lpp_tran.cpp文件下,它引用了一个找不到的头文件"log/log.h"
,我们需要把它替换成"android/log.h"
,同时将 android_errorWriteLog
方法注释掉,如果你很看重这段log的话你可以替换成自己的log(可以但不是很必要),你其实也可以把有__ANDROID__
包裹的三段都注释掉。 稍等一会不出意外的话我们就能在我们设置的PREFIX路径看到我们的.so库和头文件之类
其实流程和lame是一样的,不一样的是fdk-aac没有--disable-frontend
这个配置,你通过./configure -h
看它的帮助里有哪些配置项也能知道。
下载方式很多,可以下载压缩包也可以git clone获取
如果不修改动态链接库名字那么它本来的样子是libavutils.56.so这种形式和我们平常的命名习惯有所出入,而且网友说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)'
有了前面的经验其实大多都已经差不多,与前面稍微不同的是我们需要引入ffd-aac和lame的编译好的包,所以我们的CFLAGS
和LDFLAGS
需要配置,我们可以单独配置ffd-aac和lame的头文件和库文件路径,也可以放同一路径下,我更倾向于放同一路径下,起码没那么的路径要指定。其它的一些就是ffmpeg的配置设置了,同样可以通过
./configure -h
查看ffmpeg的可选配置和默认配置。下面是我的shell脚本,我们可以根据自己的需求设置使能特定的编译器,例如我们如果只做音频的编辑我们可以只使能音频的编解码器,去掉视频的编解码,这样我们的包的大小更小编译所花的时间更少,当然你如果不介意包体积,反而更怕有些编解码器漏掉配置你也可以不特定设置,只要使能我们的ffd-aac和lame包即可。当然有些配置是需要三方包的,比如ffplay是需要引入SDL三方包的,它是依靠SDL进行播放,X264也是需要三方包的,默认并不带X264,引入这些三方包其实和lame是一样的,这里就不一一说了。有些配置我会注释在下面的shell脚本里,这是一个v8版本的shell脚本
#!/bin/bash
NDK=$NDKROOT
#我编译的ffd-aac和lame动态链接库生成的位置
EXTC=$(pwd)/libextern
lib_cflag="-I$EXTC/armeabi-v8a/include"
lib_ldflags="-L$EXTC/armeabi-v8a/lib"
#arm
CPU=arm
#版本号,可自选
V=21
#armv7a 和 aarch64
ARCH=aarch64
#32位V7的我们用armv7a-linux-androideabi
#64位V8的我们用aarch64-linux-android
HOST=aarch64-linux-android
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
CROSS_PREFIX=$TOOLCHAIN/aarch64-linux-android-
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
PREFIX=$(pwd)/android/$ARCH
configure()
{
./configure \
--prefix=$PREFIX \
--enable-cross-compile \#交叉编译所需配置 使能交叉编译
--cross-prefix=$CROSS_PREFIX \#交叉编译所需配置,在这个路径下自动去找到nm ar等这些编译工具
--target-os=android \#交叉编译所需配置 指定代码运行环境
--arch=$ARCH \#交叉编译所需配置 指定架构(指令集)
--extra-cflags=$lib_cflag \ #引入外部头文件
--extra-ldflags=$lib_ldflags \ #引入外部链接库文件
--cc=$TOOLCHAIN/$HOST$V-clang \
--cxx=$TOOLCHAIN/$HOS$V-clang++ \
--disable-static \
--enable-shared \
--disable-doc \#禁用文档编译
--disable-programs \#禁用编译命令行程序
--disable-avdevice \
--disable-network \#禁用了网络加载音视频
--disable-symver \
--enable-gpl \#开源代码所需
--enable-pic \#编译位置无关代码
--enable-jni \#适配Android的jni
--enable-pthreads \
--enable-libfdk-aac \
--enable-neon \#开源代码所需 fdk-aac和lame需要,毕竟别人开源的东西
--enable-nonfree \#开源代码所需
--enable-libmp3lame
}
build()
{
configure
make clean
make -j8
make install
}
build
看完上面你可能有几个问题:
百度安全验证
ar和nm命令的使用_流子的专栏-CSDN博客
在这里不做过多阐述,有兴趣可以去了解,不想了解其实关系不大
因为我目前以音频编辑为主,所以引入的都是音频的库,如果有同学想引入x264、opencv这些都是可以的,ffmpeg的可玩性很强。我目前也是一个新手。写这篇文章的原因在于网上有很多教怎么编译的,但是少有讲为什么这么配置,大抵还有一些也是到处复制过来的东西,所以我虽然能编译但是也有很多不懂的地方。所以我花了一点时间讲很多开始并不理解的东西去整理,才有了这篇文章,一来是写一篇自己看得懂的流程,二来也希望帮助到其他人。如果有错误的地方请大家批评指正。如果想要我编译好的动态链接库的也可以私聊我发邮箱。