ijk编译arm64模拟器版本的ffmpeg

1,292 阅读1分钟

问题

新出的Apple silicon版本的mac无法在模拟器上运行ijk,会报ffmpeg中的库找不到arm64版本的错误

解决方案一

修改Build Settings -> Excluded Architetures,在Any iOS Simulator SDK一栏中添加arm64,这样编译的时候就会以x86_64的架构运行。

但问题是,这样只是治标不治本,通过逃避问题来解决问题。那么,为什么不编译出带arm64模拟器版本的ffmpeg呢?

解决方案二

ijk自带的compile-ffmpeg.sh脚本并没有编译arm64模拟器的功能,所以需要我们做一点小小的变化

compile-ffmpeg.sh -> do_lipo_ffmpeg()
#添加自定义架构合集
FF_ALL_AECHS_CUSTOM="arm64-simulator armv7 arm64 i386 x86_64"
#将架构合集指向自己的自定义合集
FF_ALL_ARCHS=$FF_ALL_AECHS_CUSTOMdo_lipo_ffmpeg () {
   LIB_FILE=$1
   LIPO_FLAGS=
   #添加模拟器flags变量
+    LIPO_SIMULATOR_FLAGS=
 #添加iOSflags变量
+    LIPO_IPHONE_FLAGS=
 #iOS头文件地址
+    LIPO_IPHONE_OUTPUT_HEADERS="$UNI_BUILD_ROOT/build/universal/iphone"
   #模拟器头文件地址
+    LIPO_SIMULAROR_OUTPUT_HEADERS="$UNI_BUILD_ROOT/build/universal/simulator"
+
   for ARCH in $FF_ALL_ARCHS
   do
   #删除原有通过lipo方式合成fat包的代码
-        ARCH_LIB_FILE="$UNI_BUILD_ROOT/build/ffmpeg-$ARCH/output/lib/$LIB_FILE"
-        if [ -f "$ARCH_LIB_FILE" ]; then
-            LIPO_FLAGS="$LIPO_FLAGS $ARCH_LIB_FILE"
-        else
-            echo "skip $LIB_FILE of $ARCH";
#拼接lib地址
+        ARCH_LIB_FILE="$UNI_BUILD_ROOT/build/ffmpeg-$ARCH/output/lib/$LIB_FILE.a"
+        ARCH_LIB_HEADER="$UNI_BUILD_ROOT/build/ffmpeg-$ARCH/output/include/$LIB_FILE"
#如果是arm64和armv7架构,则添加到iOS的flags中
+        if [[ "${ARCH}" == "arm64" || "${ARCH}" == "armv7" ]]; then
+            LIPO_IPHONE_FLAGS="$LIPO_IPHONE_FLAGS $ARCH_LIB_FILE"
+        fi
+   #如果是arm64-simulator,x86-64,i386架构,则添加到模拟器flags中
+        if [[ "${ARCH}" == "arm64-simulator" || "${ARCH}" == "x86_64" || "${ARCH}" == "i386" ]]; then
+            LIPO_SIMULATOR_FLAGS="$LIPO_SIMULATOR_FLAGS $ARCH_LIB_FILE"
#将头文件拷贝到include文件夹,用于header search
+            cp -rf $ARCH_LIB_HEADER $LIPO_IPHONE_OUTPUT_HEADERS
+        fi
+        
+        echo "$ARCH_LIB_FILE"
   done
   #删除原有通过lipo方式合成fat包的代码
-    xcrun lipo -create $LIPO_FLAGS -output $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE
-    xcrun lipo -info $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE
+    echo "lipo simulator flags: $LIPO_SIMULATOR_FLAGS"
+    echo "lipo iphone flags: $LIPO_IPHONE_FLAGS"
+    #iOS fat包路径
+    LIPO_IPHONE_OUTPUT_LIB="$UNI_BUILD_ROOT/build/universal/iphone/$LIB_FILE.a"
  #iPhone fat包路径
+    LIPO_SIMULATOR_OUTPUT_LIB="$UNI_BUILD_ROOT/build/universal/simulator/$LIB_FILE.a"
+    #注意:必须先将iOS平台和模拟器平台的架构都放到同一个fat包里才能去创建xcframework
+    xcrun lipo -create $LIPO_IPHONE_FLAGS -output $LIPO_IPHONE_OUTPUT_LIB
+    xcrun lipo -create $LIPO_SIMULATOR_FLAGS -output $LIPO_SIMULATOR_OUTPUT_LIB
 #创建xcframework
+    xcodebuild -create-xcframework -library $LIPO_IPHONE_OUTPUT_LIB -headers $LIPO_IPHONE_OUTPUT_HEADERS/$LIB_FILE -library $LIPO_SIMULATOR_OUTPUT_LIB -headers $LIPO_SIMULAROR_OUTPUT_HEADERS/$LIB_FILE -output $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE.xcframework
 }
complie-ffmpeg.sh -> do_lipo_all()
#修改文件路径
-        do_lipo_ffmpeg "$FF_LIB.a";
+        do_lipo_ffmpeg "$FF_LIB";
do-compile-ffmpeg.sh
#添加对arm64-simulator的处理
elif [ "$FF_ARCH" = "arm64-simulator" ]; then 
#架构还是arm64,要改回去 
  FF_ARCH="arm64"
  FF_BUILD_NAME="ffmpeg-arm64"
#新增一个FF_BUILD_OUTPUT_NAME变量,用户输出
  FF_BUILD_OUTPUT_NAME="ffmpeg-arm64-simulator"
  FF_BUILD_NAME_OPENSSL=openssl-arm64
#这里也需要将最小系统改为模拟器系统
  FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0"
  FF_XCODE_BITCODE="-fembed-bitcode"
#平台改为模拟器
  FF_XCRUN_PLATFORM="iPhoneSimulator"
  FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_FLAGS_ARM"
  FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1"#去除复用机制,因为arm64和arm64模拟器都是用的ffmpeg-arm64版本编译而来,如果服用就会跳过某个版本的编译
   if [ -f "./config.h" ]; then
-    echo 'reuse configure'
-else
-    echo "config: $FFMPEG_CFG_FLAGS $FF_XCRUN_CC"
-    ./configure \
-        $FFMPEG_CFG_FLAGS \
-        --cc="$FF_XCRUN_CC" \
-        $FFMPEG_CFG_CPU \
-        --extra-cflags="$FFMPEG_CFLAGS" \
-        --extra-cxxflags="$FFMPEG_CFLAGS" \
-        --extra-ldflags="$FFMPEG_LDFLAGS $FFMPEG_DEP_LIBS"
-    make clean
+    rm -f "./config.h"
 fi
+echo "config: $FFMPEG_CFG_FLAGS $FF_XCRUN_CC"
+./configure \
+    $FFMPEG_CFG_FLAGS \
+    --cc="$FF_XCRUN_CC" \
+    $FFMPEG_CFG_CPU \
+    --extra-cflags="$FFMPEG_CFLAGS" \
+    --extra-cxxflags="$FFMPEG_CFLAGS" \
+    --extra-ldflags="$FFMPEG_LDFLAGS $FFMPEG_DEP_LIBS"
+make clean

改完之后再次运行./complie-ffmpeg.sh all就会生成xcframework形式的静态包

image-20211208162842430.png

如果需要支持openssl也需要将./compile-openssl.sh和./do-compile-openssl.sh文件做类似处理,大同小异。改完脚本的代码放在这里:github.com/hecong2735/…