用clang进行ffmpeg动态库编译
aopmeta 8/27/2022 ndk
# ndk下载和配置
# 1. 下载最新ndk
$ wget https://dl.google.com/android/repository/android-ndk-r23c-linux.zip
$ unzip android-ndk-r23c-linux.zip
# 2. 配置环境变量
export NDK=/.../android-ndk-r23c
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
export API=21
export TARGET=aarch64-none-linux-android #模拟器使用x86_64替代
export AR=$TOOLCHAIN/bin/llvm-ar
export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API"
export CXX="$TOOLCHAIN/bin/clang++ --target=$TARGET$API"
export AS=$TOOLCHAIN/bin/llvm-as
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
# 测试clang打包
# 1. 编写源文件
// testget.h
#include <stdio.h>
int testget();
// testget.c
#include <stdio.h>
int testget() {
return 123;
}
# 2. 编写编译脚本
$ vim pkg.sh
#!bin/bash
export SYSROOT="--sysroot=$TOOLCHAIN/sysroot"
echo `$CC $SYSROOT -fPIC -c $1.c`
echo `$CC $SYSROOT -fPIC -shared -Wl,-soname,lib$1.so -o lib$1.so $1.o`
给脚本增加执行权限并执行脚本
$ sudo chmod 755 pkg.sh
$ bash pkg.sh testget
此时会生成libtestget.so
动态库文件
# 3. 将动态库引入Native工程
首先创建一个Android的Native C++工程
将libtestget.so
导入cpp/libs/shared/lib/arm64-v8a
目录下,testget.h
导入cpp/libs/shared/include
目录下
配置CMakeList.txt
,加入动态库的依赖
set(shared ${CMAKE_CURRENT_SOURCE_DIR}/libs/shared)
add_library(testget SHARED IMPORTED)
set_target_properties(testget PROPERTIES IMPORTED_LOCATION
${shared}/lib/${ANDROID_ABI}/libtestget.so)
target_include_directories(
...
${shared}/include
)
target_link_libraries(
...
testget
...)
在build.gradle
中指定ndk版本为最新版本
android {
...
ndkVersion '25.0.8775105'
在native-lib.cpp
中引入头文件
extern "C" {
#include "testget.h"
}
并修改的jni方法
Java_com_example_testso_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
int res = testget();
const char *str = hello.c_str();
char *buf = new char[strlen(str) + sizeof(res)];
sprintf(buf, "%s%d", str, res);
return env->NewStringUTF(buf);
}
运行并查看结果
# ffmpeg下载和编译
# 1. 下载最新ffmpeg
$ wget https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
$ tar -xjf ffmpeg-snapshot.tar.bz2
# 2. 编写编译脚本
$ vim compile.sh
#!/bin/bash
export TMPDIR=/.../ffmpeg/tmp
PLATFORM=/.../android-ndk-r23c/toolchains/llvm/prebuilt/linux-x86_64
function build
{
CPU=$1
PREFIX="/.../ffmpeg/output-$CPU"
TOOLCHAIN="/.../android-ndk-r23c/toolchains/llvm/prebuilt/linux-x86_64"
echo "Cpu is $CPU"
echo "Output is $PREFIX"
./configure \
--prefix=$PREFIX \
--target-os=android \
--arch=$CPU \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-symver \
--enable-cross-compile \
--sysroot=$TOOLCHAIN/sysroot \
--cross-prefix=$TOOLCHAIN/bin/llvm- \
--cc=$TOOLCHAIN/bin/$CPU-linux-android21-clang \
--cxx=$TOOLCHAIN/bin/$CPU-linux-android21-clang++ \
--extra-cflags="-I$TOOLCHAIN/sysroot/usr/include -fpic" \
--extra-ldflags="-L$TOOLCHAIN/sysroot/usr/lib"
make clean
make -j4
make install
}
build x86_64
安装yasm工具后切换到root用户下,并执行脚本
$ sudo yum install yasm
$ su - root
$ nohup bash compile.sh > run.log &
查看进程是否正在运行,并查看日志确定是否已完成
$ ps -aux | grep compile
$ tail -f -n 300 run.log
压缩并导出编译后的成果
$ zip -r os-x86_64.zip output-x86_64