一次性说清楚MAC OS环境的FFmpeg交叉编译

2023年 9月 21日 76.3k 0

本次编译的环境和版本

  • Mac OS
  • Android
  • NDK r21e
  • ffmpeg-4.2.2

编译工具链

Android的NDK在r17c版本之后移除了GCC,不再支持GCC编译,r17c版本之后都使用CLANG进行编译。
NDK版本下载路径:developer.android.google.cn/ndk/downloa…

下载NDK之后,解压文件,进入NDK目录,之后来看下改版本的编译工具链。

WX20230912-174304@2x.png

该编译工具链中有两个重要的路径:

编译工具链目录:
toolchains/llvm/prebuilt/darwin-x86_64/bin
 
交叉编译环境目录:
toolchains/llvm/prebuilt/darwin-x86_64/sysroot

编译工具路径:

WX20230912-175057@2x.png

该截图未完整展示。

对于x86的CPU架构,编译工具是i686开头的文件,对于x86_64的CPU架构,编译工具是x86_64开头的文件。

根据不同的CPU架构区和不同的Android版本,区分了不同的clang工具,根据自己需要选择就好了。

例如:您要编译CPU架构是armeabi-v7a,最低支持Android21版本的ffmpeg,那么你选择的编译工具就是:

armv7a-linux-androideabi21-clang
armv7a-linux-androideabi21-clang++

下载FFmpeg

下载连接:ffmpeg.org/releases/
该地址ffmpeg所有的版本都有,可按需下载。本文采用的是4.2.2版本,所以选择ffmpeg-4.2.2.tar.gz 文件下载

下载好源码后,进入根目录,找到一个名为 congfigure 的文件,这是一个shell脚本,用于生成一些 FFmpeg 编译需要的配置文件。

网上很多教程会对此文件进行修改,但是3.4版本后不需要更改configure文件内容,下载解压后就ok,主要是后面脚本配置两步

创建编译脚本

在FFmpeg源码根目录新建编译脚本 build_android.sh

################################ arm64-v8a ################################
#!/bin/sh
# NDK 所在的路径
NDK=/Users/geely/FFmpeg/android-ndk-r21e

# 需要编译出的平台,这里是 arm64-v8a
ARCH=aarch64

CPU=arm64-v8a

# 支持的最低 Android API
API=21

# 编译后输出目录,在 ffmpeg 源码目录下的 /android/arm64-v8a
OUTPUT=$(pwd)/android/$CPU

# NDK 交叉编译工具链所在路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
SYSROOT_L=$TOOLCHAIN/sysroot/usr/lib/aarch64-linux-android
GCC_L=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/lib/gcc/aarch64-linux-android/4.9.x

build_arm64() {
    echo "33[32m Compiling FFmpeg for $CPU 33[0m"
  ./configure 
  --target-os=android 
  --prefix=$OUTPUT 
  --arch=$ARCH 
  --sysroot=$TOOLCHAIN/sysroot 
  --enable-static 
  --disable-ffmpeg 
  --disable-ffplay 
  --disable-ffprobe 
  --disable-debug 
  --disable-doc 
  --disable-avdevice 
  --disable-shared 
  --enable-cross-compile 
  --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- 
  --cc=$TOOLCHAIN/bin/aarch64-linux-android$API-clang 
  --cxx=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++ 
  --extra-cflags="-fpic -I$OUTPUT/include" 
  --extra-ldflags="-lc -ldl -lm -lz -llog -lgcc -L$OUTPUT/lib"

  make clean all
  make -j8
  make install
  echo "33[32m The Compilation of FFmpeg for $CPU is completed 33[0m"
}

package_library_arm64() {
    echo "33[32m package $CPU libffmpeg.so start 33[0m"

  $TOOLCHAIN/bin/aarch64-linux-android-ld -L$OUTPUT/lib -L$GCC_L 
    -rpath-link=$SYSROOT_L/$API -L$SYSROOT_L/$API -soname libffmpeg.so 
    -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $OUTPUT/libffmpeg.so 
    -lavcodec -lavfilter -lswresample -lavformat -lavutil -lswscale -lgcc 
    -lc -ldl -lm -lz -llog 
    --dynamic-linker=/system/bin/linker
    # 设置动态链接器,不同平台的不同,android 使用的是/system/bin/linker

    echo "33[32m package $CPU libffmpeg.so success 33[0m"
}

build_arm64
package_library_arm64

# 编译配置详解答
# 设置编译针对的系统
#--target-os=android 

# 编译后文件的输出目录
#--prefix=$OUTPUT 

# 设置编译so库的架构,当前设置为aarch64,可以根据实际需求修改
#--arch=$ARCH

# 平台架构和arch值对应关系如下:
# armv8a -> arm64 -> aarch64-linux-android-
# armv7a -> arm -> arm-linux-androideabi-
# x86 -> x86 -> i686-linux-android-
# x86_64 -> x86_64 -> x86_64-linux-android-

# 编译动态库,shared和static的开关是相对的。
#--enable-static 
#--disable-shared 
#这个配置会生成.a文件,用于后续将多个.a文件打包成一个so

#--disable-static 
#--enable-shared 
#这个配置会生成多个so文件

# 生成文档,以及相关的功能模块
#--disable-doc 

# 禁止编译可执行文件
#--disable-programs


# 设置交叉编译器,按照实际路径修改就可以了。
#--cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- 

# 设置编译器,不然会报错,系统默认会使用arm-linux-androideabi-clang,但是此编译器在NDK不存# # 在,导致编译失败
# 这里在设置编译器的时候要注意,根据NDK的版本有不同的设置;由于r17c版本之后就用的是clang编译,
# 所以应该配置cc和cxx
#--cc=$TOOLCHAIN/bin/aarch64-linux-android$API-clang 
#--cxx=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++ 

# r17c及以前的版本是这个配置
#--cc=$TOOLCHAIN/bin/aarch64-linux-androideabi-gcc 
#--nm=$TOOLCHAIN/bin/aarch64-linux-androideabi-nm 

另外需要注意的是:编译x86平台的需要加上 --disable-asm 这个配置,否则编译不通过

文件配置完成之后就可以给文件授权变成可执行文件,授权方式:

chmod a+x build_android.sh

执行完成之后,就会在之前配置文件设置的OUTPUT输出目录输出对应的文件

WX20230921-104337@2x.png

完整编译脚本

最后附上arm64-v8a armeabi-v7a x86 x86_64 平台的完整的编译脚本


################################ arm64-v8a ################################
#!/bin/sh
# NDK 所在的路径
NDK=/Users/geely/FFmpeg/android-ndk-r21e
# 需要编译出的平台,这里是 arm64-v8a
ARCH=aarch64
CPU=arm64-v8a
# 支持的最低 Android API
API=21
# 编译后输出目录,在 ffmpeg 源码目录下的 /android/arm64-v8a
OUTPUT=$(pwd)/android/$CPU
# NDK 交叉编译工具链所在路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
SYSROOT_L=$TOOLCHAIN/sysroot/usr/lib/aarch64-linux-android
GCC_L=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/lib/gcc/aarch64-linux-android/4.9.x

build_arm64() {
    echo "33[32m Compiling FFmpeg for $CPU 33[0m"
  ./configure 
  --target-os=android 
  --prefix=$OUTPUT 
  --arch=$ARCH 
  --sysroot=$TOOLCHAIN/sysroot 
  --enable-static 
  --disable-ffmpeg 
  --disable-ffplay 
  --disable-ffprobe 
  --disable-debug 
  --disable-doc 
  --disable-avdevice 
  --disable-shared 
  --enable-cross-compile 
  --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- 
  --cc=$TOOLCHAIN/bin/aarch64-linux-android$API-clang 
  --cxx=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++ 
  --extra-cflags="-fpic -I$OUTPUT/include" 
  --extra-ldflags="-lc -ldl -lm -lz -llog -lgcc -L$OUTPUT/lib"

  make clean all
  make -j8
  make install
  echo "33[32m The Compilation of FFmpeg for $CPU is completed 33[0m"
}

package_library_arm64() {
    echo "33[32m package $CPU libffmpeg.so start 33[0m"

  $TOOLCHAIN/bin/aarch64-linux-android-ld -L$OUTPUT/lib -L$GCC_L 
    -rpath-link=$SYSROOT_L/$API -L$SYSROOT_L/$API -soname libffmpeg.so 
    -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $OUTPUT/libffmpeg.so 
    -lavcodec -lavfilter -lswresample -lavformat -lavutil -lswscale -lgcc 
    -lc -ldl -lm -lz -llog 
    --dynamic-linker=/system/bin/linker
    # 设置动态链接器,不同平台的不同,android 使用的是/system/bin/linker

    echo "33[32m package $CPU libffmpeg.so success 33[0m"
}

build_arm64
package_library_arm64



################################ armeabi-v7a ################################
#!/bin/sh
# NDK 所在的路径
NDK=/Users/geely/FFmpeg/android-ndk-r21e
# 需要编译出的平台,这里是 arm64-v8a
ARCH=arm
CPU=armeabi-v7a
# 支持的最低 Android API
API=21
# 编译后输出目录,在 ffmpeg 源码目录下的 /android/arm64-v8a
OUTPUT=$(pwd)/android/$CPU
# NDK 交叉编译工具链所在路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
SYSROOT_L=$TOOLCHAIN/sysroot/usr/lib/arm-linux-androideabi
GCC_L=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x

build_arm() {
    echo "33[32m Compiling FFmpeg for $CPU 33[0m"
  ./configure 
  --target-os=android 
  --prefix=$OUTPUT 
  --arch=$ARCH 
  --sysroot=$TOOLCHAIN/sysroot 
  --enable-static 
  --disable-ffmpeg 
  --disable-ffplay 
  --disable-ffprobe 
  --disable-debug 
  --disable-doc 
  --disable-avdevice 
  --disable-shared 
  --enable-cross-compile 
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- 
  --cc=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang 
  --cxx=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++ 
  --extra-cflags="-fpic -I$OUTPUT/include" 
  --extra-ldflags="-lc -ldl -lm -lz -llog -lgcc -L$OUTPUT/lib"

  make clean all
  make -j8
  make install
  echo "33[32m The Compilation of FFmpeg for $CPU is completed 33[0m"
}

package_library_arm() {
    echo "33[32m package $CPU libffmpeg.so start 33[0m"

  $TOOLCHAIN/bin/arm-linux-androideabi-ld -L$OUTPUT/lib -L$GCC_L 
    -rpath-link=$SYSROOT_L/$API -L$SYSROOT_L/$API -soname libffmpeg.so 
    -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $OUTPUT/libffmpeg.so 
    -lavcodec -lavfilter -lswresample -lavformat -lavutil -lswscale -lgcc 
    -lc -ldl -lm -lz -llog 
    --dynamic-linker=/system/bin/linker
    # 设置动态链接器,不同平台的不同,android 使用的是/system/bin/linker

    echo "33[32m package $CPU libffmpeg.so success 33[0m"
}

build_arm
package_library_arm



################################ x86 ################################
#!/bin/sh
# NDK 所在的路径
NDK=/Users/geely/FFmpeg/android-ndk-r21e
# 需要编译出的平台,这里是 arm64-v8a
ARCH=x86
CPU=x86
# 支持的最低 Android API
API=21
# 编译后输出目录,在 ffmpeg 源码目录下的 /android/arm64-v8a
OUTPUT=$(pwd)/android/$CPU
# NDK 交叉编译工具链所在路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
SYSROOT_L=$TOOLCHAIN/sysroot/usr/lib/i686-linux-android
GCC_L=$NDK/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x

build_x86() {
    echo "33[32m Compiling FFmpeg for $CPU 33[0m"
  ./configure 
  --target-os=android 
  --prefix=$OUTPUT 
  --arch=$ARCH 
  --sysroot=$TOOLCHAIN/sysroot 
  --disable-asm 
  --enable-static 
  --disable-ffmpeg 
  --disable-ffplay 
  --disable-ffprobe 
  --disable-debug 
  --disable-doc 
  --disable-avdevice 
  --disable-shared 
  --enable-cross-compile 
  --cross-prefix=$TOOLCHAIN/bin/i686-linux-android- 
  --cc=$TOOLCHAIN/bin/i686-linux-android$API-clang 
  --cxx=$TOOLCHAIN/bin/i686-linux-android$API-clang++ 
  --extra-cflags="-fpic -I$OUTPUT/include" 
  --extra-ldflags="-lc -ldl -lm -lz -llog -lgcc -L$OUTPUT/lib"

  make clean all
  make -j8
  make install
  echo "33[32m The Compilation of FFmpeg for $CPU is completed 33[0m"
}

package_library_x86() {
    echo "33[32m package $CPU libffmpeg.so start 33[0m"

  $TOOLCHAIN/bin/i686-linux-android-ld -L$OUTPUT/lib -L$GCC_L 
    -rpath-link=$SYSROOT_L/$API -L$SYSROOT_L/$API -soname libffmpeg.so 
    -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $OUTPUT/libffmpeg.so 
    -lavcodec -lavfilter -lswresample -lavformat -lavutil -lswscale -lgcc 
    -lc -ldl -lm -lz -llog 
    --dynamic-linker=/system/bin/linker
    # 设置动态链接器,不同平台的不同,android 使用的是/system/bin/linker

    echo "33[32m package $CPU libffmpeg.so success 33[0m"
}

build_x86
package_library_x86



################################ x86_64 ################################
#!/bin/sh
# NDK 所在的路径
NDK=/Users/geely/FFmpeg/android-ndk-r21e
# 需要编译出的平台,这里是 arm64-v8a
ARCH=x86_64
CPU=x86_64
# 支持的最低 Android API
API=21
# 编译后输出目录,在 ffmpeg 源码目录下的 /android/arm64-v8a
OUTPUT=$(pwd)/android/$CPU
# NDK 交叉编译工具链所在路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
SYSROOT_L=$TOOLCHAIN/sysroot/usr/lib/x86_64-linux-android
GCC_L=$NDK/toolchains/x86_64-4.9/prebuilt/darwin-x86_64/lib/gcc/x86_64-linux-android/4.9.x

build_x86_64() {
    echo "33[32m Compiling FFmpeg for $CPU 33[0m"
  ./configure 
  --target-os=android 
  --prefix=$OUTPUT 
  --arch=$ARCH 
  --sysroot=$TOOLCHAIN/sysroot 
  --enable-static 
  --disable-ffmpeg 
  --disable-ffplay 
  --disable-ffprobe 
  --disable-debug 
  --disable-doc 
  --disable-avdevice 
  --disable-shared 
  --enable-cross-compile 
  --cross-prefix=$TOOLCHAIN/bin/x86_64-linux-android- 
  --cc=$TOOLCHAIN/bin/x86_64-linux-android$API-clang 
  --cxx=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++ 
  --extra-cflags="-fpic -I$OUTPUT/include" 
  --extra-ldflags="-lc -ldl -lm -lz -llog -lgcc -L$OUTPUT/lib"

  make clean all
  make -j8
  make install
  echo "33[32m The Compilation of FFmpeg for $CPU is completed 33[0m"
}

package_library_x86_64() {
    echo "33[32m package $CPU libffmpeg.so start 33[0m"

  $TOOLCHAIN/bin/x86_64-linux-android-ld -L$OUTPUT/lib -L$GCC_L 
    -rpath-link=$SYSROOT_L/$API -L$SYSROOT_L/$API -soname libffmpeg.so 
    -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $OUTPUT/libffmpeg.so 
    -lavcodec -lavfilter -lswresample -lavformat -lavutil -lswscale -lgcc 
    -lc -ldl -lm -lz -llog 
    --dynamic-linker=/system/bin/linker
    # 设置动态链接器,不同平台的不同,android 使用的是/system/bin/linker

    echo "33[32m package $CPU libffmpeg.so success 33[0m"
}

build_x86_64
package_library_x86_64



相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论