问题
新出的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_CUSTOM
do_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形式的静态包
如果需要支持openssl也需要将./compile-openssl.sh和./do-compile-openssl.sh文件做类似处理,大同小异。改完脚本的代码放在这里:github.com/hecong2735/…