简介:面向 iOS 平台音视频开发者的 FFmpeg 交叉编译辅助工具,将 ffmpeg、x264、fdk-aac、lame 四大开源库的源码下载、参数配置与编译流程整合为一套 Shell 脚本,适合需要在模拟器或真机环境中快速获得自定义 iOS 库的中高级开发者。资源共 4 个文件,全部为 shell 脚本,压缩包仅 8KB;脚本按库拆分,既能单独构建 x264、fdk-aac、lame,又能由总控脚本一键串联执行,便于理解每一步编译依赖,也方便后续按需替换版本或调整参数。已有 344 人学习,结合浏览热度可以看出该脚本方案在实际 iOS 编译场景中具备一定参考价值。解压后进入目录并执行总控脚本,即可自动完成依赖获取、编译并生成 fdk-aac-ios、lame-ios、x264-ios、FFmpeg-iOS 等产物目录,省去手动下载源码与反复排查配置报错的时间,适合需要快速搭建 iOS 音视频采集、编码或推流开发环境的技术人员。
1. 一键编译脚本到底省掉了什么:iOS 上 FFmpeg 全家桶的编译真相
“iOS 平台 一键自动下载并编译脚本.sh(ffmpeg x264 fdk-aac lame)”,第一次看到这个标题的开发者,多半已经被这套组合折磨过:FFmpeg 官方并没有提供现成的 iOS 静态库,想在自己的播放器或录制器里用上 x264 做 H.264 编码、fdk-aac 做 AAC 音频、lame 做 MP3 编码,唯一的路就是交叉编译。而交叉编译这扇门里,挤着工具链、架构片、license 和一堆 configure 玄学。
这脚本做的事情,就是把你下载源码包、逐架构 configure、make、再把多个 .a 合并成 fat 库这一串重复劳动,从“手动两小时”压成“执行一行命令”。它解决的是中型音视频项目里最容易被低估的问题:不是编译本身难,而是换一台电脑、升级一次 Xcode、多一个模拟器架构,就能让昨天的脚本瞬间变成废纸。适合理音视频 SDK、直播、剪辑类 App 的开发者,尤其是不想被 Pod 里陈旧的 FFmpeg 封装限制版本的人。
2. 编译顺序背后的硬逻辑:工具链、架构片与四个库的依赖关系
动手抄脚本之前,得先把顺序这件事讲透,否则你会在C compiler test failed里耗掉一下午。这个章节回答三个问题:为什么先编谁后编谁有讲究,iOS 交叉编译到底在配什么,以及为什么现在的模拟器比几年前多了一个坑。
2.1 为什么四大件要按“lame/x264/fdk-aac → FFmpeg”的顺序出现在脚本里
FFmpeg 本身是主工程,x264、fdk-aac、lame 是三个外部库。FFmpeg 的 configure 阶段会去检查这些库的头文件和静态库是否存在,存在才生成对应的--enable-libx264、--enable-libfdk-aac、--enable-libmp3lame编译开关。换句话说,FFmpeg 编译时被动依赖它们,依赖库必须在主库之前落盘。
三个依赖库之间则没有互相引用关系,x264 不依赖 fdk-aac,lame 也不依赖 x264。所以理论上可以并行编译节省时间,我一般不会这么干,原因有两个:一是并行任务同时打日志,排查报错时几个 log 一起滚,定位更慢;二是这三个库的 configure 都接受--prefix参数,并行时如果它们往同一前缀目录写文件,偶发性的文件竞争会让你误判是编译参数问题。串行虽然慢几分钟,但失败时一眼就能看出是哪一个库出的问题。
还有一个容易被忽略的点:fdk-aac 和 FFmpeg 的结合在 license 上有特殊性。FFmpeg 的 configure 里,--enable-libfdk-aac会强制要求同时传--enable-nonfree,而 x264 和 lame 需要--enable-gpl。这两个开关并列,就意味着产物的分发约束是“GPL + nonfree 混合”,不是所有项目都能接受。所以脚本里把 ffmpeg 放在最后一步也有个现实好处:依赖库编译失败的损失最小,license 组合问题也在最后一步才集中暴露。
2.2 iOS 交叉编译的三件套:--host、clang、sysroot
iOS 上的交叉编译,本质上是让 clang 干一件它不太情愿的事:在 Mac 上编译出目标为 iOS 的机器码。clang 本身是跨编译器,但光有 cc 不够,你得同时告诉它三件事:目标架构是什么、SDK 头文件在哪、最低系统版本是多少。少了任何一件,configure 的测试程序编出来可能能跑在 Mac 上,但链接进 iOS 工程后直接崩。
第一件是--host三元组,比如arm64-apple-darwin。configure 脚本靠它决定生成什么样的 config.h、用哪套内联汇编、链接什么样的运行时。值得提醒的是,x264 和 fdk-aac 的 configure 对 host 字符串很敏感,传成arm-apple-darwin这种老写法在高版本 Xcode 上经常直接判失败,统一写成arm64-apple-darwin和x86_64-apple-darwin最省心。
第二件是--sysroot(fdk-aac 用--with-sysroot)。它指向 SDK 的根目录,也就是模拟器和真机的.sdk路径。这个值需要用xcrun --sdk iphoneos --show-sdk-path动态获取,不要手写,因为每次 Xcode 升级后路径里的版本号都会变。
第三件是-mios-version-min=12.0这样的最低版本参数。它决定 mt 值,影响链接时能否使用某些新 API。我用 12.0 做默认值,你按自己项目的 deployment target 改。
2.3 真机与模拟器的两个 slice 问题:M 系列芯片改变了什么
传统认知里,iOS 静态库编两个架构就够了:真机用 arm64,模拟器用 x86_64。这是 Intel Mac 时代的标准做法。M 系列芯片出现后,模拟器也跑 arm64 了,所以现在的模拟器 slice 实际有两个选项:x86_64(Rosetta 运行的老模拟器)和 arm64(Apple Silicon 原生模拟器)。
坑就在这里:真机 arm64 和模拟器 arm64 的架构名完全一样,都是arm64。如果你天真地把这两个 .a 文件用 lipo 合并进同一个 fat 库,lipo 会拒绝合并,报文件里出现重复架构。这不是参数错了,是设计如此。我目前的处理方式是分别维护两个 fat 库:一个libavcodec-arm64.a用于真机,一个libavcodec-sim.a合并 x86_64 与 arm64 两种模拟器片。Xcode 集成时,真机 Debug/Release 用前者,模拟器用后者。
如果你还在用模拟器 arm64 + 真机 arm64 合一的旧脚本,升级到 Apple Silicon 之后大概率会遇到“linker 不认这个库”的报错。不是脚本坏了,是架构片组合变了。这个点放在这里,是希望大家不要只是抄脚本,而是知道脚本里架构列表为什么要这样设计。
3. 把一键脚本拆给你看:下载、配置、编译、合并四段式
这一章给出一套能跑的脚本结构。我不准备贴一个 500 行的完整文件,而是按四段拆开讲:骨架与变量、下载与重试、四库各自的 configure 参数、lipo 合并。每段都能直接抄,抄完拼起来就是一个可用的一键脚本。
3.1 脚本骨架:环境变量与可配置的源码地址
#!/bin/bash # iOS 平台一键下载并编译 ffmpeg + x264 + fdk-aac + lame # 用法: ./build_ios.sh [all|download|libs|ffmpeg|fat] set -euo pipefail IOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path) SIM_SDK=$(xcrun --sdk iphonesimulator --show-sdk-path) MIN_VERSION=12.0 BUILD_DIR=$(pwd)/build PREFIX="${BUILD_DIR}/prefix" LOG_DIR="${BUILD_DIR}/logs" MANIFEST_DIR="${BUILD_DIR}/manifest" mkdir -p "$PREFIX" "$LOG_DIR" "$MANIFEST_DIR" "${BUILD_DIR}/src" # 源码包直链,需要去官方发布页把 tarball 地址填进来 X264_URL="" FDKAAC_URL="" LAME_URL="" FFMPEG_URL="" # 真机与模拟器架构列表 DEV_SLICE="arm64" SIM_SLICES=("arm64" "x86_64")这段脚本的逻辑很简单:先保证目录结构存在,再管 URL 和架构。set -euo pipefail是一键脚本的命根子,它保证任意一条命令失败就让整个脚本退出,而不是带着缺库的状态继续跑,最后给你一个查不出原因的链接错误。
两处参数值得说明:MIN_VERSION要和 App 工程的 deployment target 对齐,FFmpeg 和 x264 的符号在低版本系统上是否能解析由它决定;SIM_SLICES数组在 Intel Mac 上可以只留x86_64,在 Apple Silicon 上建议保留两个,Rosetta 模拟器并没有退出历史舞台。URL 变量留空不是偷懒,而是源码发布页的直达链接经常换,写死反而会让脚本失效。
3.2 下载与重试:一键脚本最容易翻车的地方
fetch_source() { local name=$1 url=$2 local archive="${BUILD_DIR}/src/${name}.tar.gz" if [ ! -f "$archive" ]; then echo "==> 下载 ${name}" curl -fL --retry 3 --retry-delay 5 \ --connect-timeout 20 \ -o "$archive" "$url" else echo "==> ${name} 源码包已存在,跳过下载" fi }这段代码解决的是网络下载的两个常见问题:下载到一半失败,以及因为网络抖动导致的假失败。--retry 3 --retry-delay 5让 curl 在传输中断时自动重试最多三次,--connect-timeout 20避免连不上时无限挂起。
有个细节必须说:-f参数(fail fast)在 HTTP 返回 404 或 403 时让 curl 直接返回非零退出码,这样脚本不会把错误页面存成 .tar.gz 然后带着一个坏压缩包继续编译。下载完成后,建议自己加一步校验逻辑,最轻量的是解压前用tar -tzf "$archive" >/dev/null验证压缩包完整性。某开发者曾经因为下载到一个 2KB 的 HTML 错误页,configure 阶段反复报 “not a directory”,查了半小时才反应过来是源码包坏了。
3.3 configure 参数逐个讲:x264、fdk-aac、lame、FFmpeg 各要什么
build_x264() { local arch=$1 sdk=$2 arch_prefix=$3 local log="${LOG_DIR}/x264_${arch}.log" pushd "${BUILD_DIR}/src/x264" >/dev/null make distclean >/dev/null 2>&1 || true ./configure \ --prefix="$arch_prefix" \ --host="${arch}-apple-darwin" \ --sysroot="$sdk" \ --enable-static --disable-shared --disable-cli \ --extra-cflags="-arch ${arch} -isysroot ${sdk} -mios-version-min=${MIN_VERSION}" \ --extra-ldflags="-arch ${arch} -isysroot ${sdk} -mios-version-min=${MIN_VERSION}" \ >>"$log" 2>&1 make -j"$(sysctl -n hw.ncpu)" >>"$log" 2>&1 make install >>"$log" 2>&1 popd >/dev/null }x264 的 configure 是这四家里对参数最敏感的。--disable-cli必须加,否则它会在编完静态库后额外尝试编一个命令行工具,这个工具依赖一堆 POSIX 接口,在 iOS 交叉编译环境下大概率撞墙。make distclean则是为了清掉上一次 configure 留下的 config.mak,保证每次构建从干净状态开始,后面三个库的脚本里同样保持这个习惯。
build_fdk_aac() { local arch=$1 sdk=$2 arch_prefix=$3 local log="${LOG_DIR}/fdk_aac_${arch}.log" pushd "${BUILD_DIR}/src/fdk-aac" >/dev/null make distclean >/dev/null 2>&1 || true ./configure \ --host="${arch}-apple-darwin" \ --with-sysroot="$sdk" \ --prefix="$arch_prefix" \ --enable-static --disable-shared \ CC="$(xcrun --find clang)" \ CFLAGS="-arch ${arch} -isysroot ${sdk} -mios-version-min=${MIN_VERSION}" \ LDFLAGS="-arch ${arch} -isysroot ${sdk} -mios-version-min=${MIN_VERSION}" \ >>"$log" 2>&1 make -j"$(sysctl -n hw.ncpu)" >>"$log" 2>&1 make install >>"$log" 2>&1 popd >/dev/null }fdk-aac 的 configure 家族对--extra-cflags不敏感,但对CC、CFLAGS环境变量很敏感。--with-sysroot和--host缺一不可,少了--with-sysroot时 clang 会默认用 macOS 的 SDK 头文件,编出来的 .a 在 iOS 工程里直接链接失败。CC="$(xcrun --find clang)"是显式指定编译器路径,避免脚本的 PATH 里混入其他编译器。
lame 的脚本与 fdk-aac 几乎相同,只需要多一个--disable-frontend,把 MP3 编码器自带的命令行工具关掉。这个参数在 Windows 和 Linux 上无所谓,但在 iOS 上不加,会在最后 make 阶段因为frontend目录下缺少目标系统函数而失败。
build_ffmpeg() { local arch=$1 sdk=$2 arch_prefix=$3 local log="${LOG_DIR}/ffmpeg_${arch}.log" pushd "${BUILD_DIR}/src/ffmpeg" >/dev/null make distclean >/dev/null 2>&1 || true ./configure \ --prefix="$arch_prefix" \ --cc="$(xcrun --find clang)" \ --target-os=darwin \ --arch="$arch" \ --sysroot="$sdk" \ --enable-cross-compile \ --enable-static --disable-shared \ --enable-pic \ --disable-programs --disable-doc --disable-debug \ --enable-libx264 --enable-libfdk-aac --enable-libmp3lame \ --enable-gpl --enable-nonfree \ --extra-cflags="-arch ${arch} -isysroot ${sdk} -mios-version-min=${MIN_VERSION} -I${arch_prefix}/include" \ --extra-ldflags="-arch ${arch} -isysroot ${sdk} -mios-version-min=${MIN_VERSION} -L${arch_prefix}/lib" \ >>"$log" 2>&1 make -j"$(sysctl -n hw.ncpu)" >>"$log" 2>&1 make install >>"$log" 2>&1 popd >/dev/null }FFmpeg 的 configure 是四家里最“挑食”的一个,几个开关必须同时出现:--enable-cross-compile告诉它现在不是本机编译;--enable-pic生成位置无关代码,iOS 静态库链接时要求目标文件带 PIC,漏了这个开关,真机链接会报relocation truncated;--enable-gpl和--enable-nonfree分开看,前者配合 x264、lame,后者来自 fdk-aac 的 license 约束。
-I${arch_prefix}/include和-L${arch_prefix}/lib这两项,是 FFmpeg configure 阶段能找到 x264 等三个库的关键。前面三个库的--prefix都指向独立的arch_prefix目录,ffmpeg 再通过 cflags/ldflags 把它们都搜进来。这样每个 slice 的依赖关系是隔离的,不会出现两个架构抢同一个目录的混乱。
四个库的 configure 对比可以收进下面这张表:
| configure 参数 | 作用 | 踩坑点 |
|---|---|---|
| --host=CPU-apple-darwin | 声明交叉编译目标三元组 | 传 arm 而不是 arm64 会链接失败 |
| --sysroot / --with-sysroot | 指向 SDK 根目录 | 不传时默认用 Mac 的 SDK 路径 |
| --disable-cli / --disable-frontend | 关闭命令行工具 | 不关会在最终 make 报目标系统函数缺失 |
| --enable-pic | 生成位置无关代码 | 漏掉后真机链接报 relocation 错误 |
| --disable-programs | 不编 FFmpeg 命令行程序 | 不关会多编几十个可执行文件、时间翻倍 |
| --enable-gpl + --enable-nonfree | 放行 x264/lame 与 fdk-aac | 组合式授权,上架前需确认合规 |
3.4 循环编译与 lipo 合并:把四个静态库拼成一个 fat 库
build_all_slices() { local lib_build=$1 for arch in "$DEV_SLICE" "${SIM_SLICES[@]}"; do local sdk="$IOS_SDK" if [ "$arch" = "x86_64" ] || { [ "$arch" = "arm64" ] && [ "$lib_build" = "sim" ]; }; then sdk="$SIM_SDK" fi local arch_prefix="${PREFIX}/${arch}" mkdir -p "$arch_prefix" "$lib_build" "$arch" "$sdk" "$arch_prefix" done } combine_fat() { local lib_name=$1 local slices=() for arch in "$DEV_SLICE" "${SIM_SLICES[@]}"; do slices+=("${PREFIX}/${arch}/lib/${lib_name}") done lipo -create "${slices[@]}" -output "${BUILD_DIR}/fat/${lib_name}" }这里有一个需要理解的概念:arch_prefix按架构拆分,每个架构的库安装到独立目录,lipo -create再从这些目录里取对应架构的 .a 合并。合并的产物是 fat 库,包含真机 arm64、模拟器 arm64、模拟器 x86_64 三种 slice,Xcode 链接时会自动挑选适合当前运行环境的那个。
这个循环里最值得注意的坑是 SDK 选择逻辑:模拟器 arm64 不能配IOS_SDK,它也需要SIM_SDK。真机 arm64 与模拟器 arm64 的 CPU 指令集相似,但头文件和链接环境不同,SDK 选错会导致 configure 生成了真机库却声称是模拟器库,链接时报一堆“文件已被占用”一类的怪异错误。合并完成后,用lipo -info build/fat/libavcodec.a看一眼,应该能看到三个架构列表,只看到一个架构就说明循环里漏了 slice。
4. 常见问题与避坑:编译失败时的三分钟定位法
这一章是血泪经验。下面几条都是从实际搭建这套 iOS 编译脚本时反复遇到的状况里挑出来的,每条都按现象、原因、解决来讲,照着排查,大部分问题能控制在三分钟内定位。
4.1 “C compiler test failed”十有八九是 sysroot 没配对
现象:FFmpeg configure 刚刚开始,就弹出C compiler test failed,config.log 里最后几行是找不到stdlib.h或_malloc.h。这个报错几乎没有任何解释性信息,像黑匣子。
原因:clang 找不到对应 SDK 的头文件。常见两种情况:一是--sysroot漏传,clang 默认用了 macOS 的 SDK;二是传错了方向,拿 iphoneos SDK 去编模拟器架构。它们都会让 configure 测试程序的头文件路径指向不存在的位置。
解决:先确认xcrun --sdk iphoneos --show-sdk-path和xcrun --sdk iphonesimulator --show-sdk-path两个路径和脚本里的一致,再检查循环里是否按架构传了正确的 SDK。我习惯在脚本开头打印一行“当前编译: 架构 + SDK”,这样日志里一眼就能看出是不是配错了对。
4.2 模拟器或真机的汇编错误:gas-preprocessor 缺席
现象:编译 x264,在 make 阶段报Unable to find gas-preprocessor.pl,或者一堆.S汇编文件编译失败,报找不到as指令。
原因:x264 在 arm64 架构下内联汇编需要用 gas-preprocessor 做预处理,这是 FFmpeg 生态在 iOS 交叉编译中长期依赖的脚本。Xcode 从某个版本开始不再随工具链提供这个脚本,于是真机 arm64 的汇编目标文件就编不过去。
解决:把 gas-preprocessor.pl 下载下来放到/usr/local/bin,然后chmod +x。之后重编 x264。这个脚本是纯 Perl 的单文件工具,不需要安装额外依赖。某开发者第一次遇到时以为是 clang 版本问题,折腾了半小时才定位到是少了个辅助脚本,后来每次搭新环境第一件事就是先放它。
4.3 升级 Xcode 后老脚本集体失效:configure 缓存与版本锁定
现象:同一套脚本,上个月还能编出完整的 fat 库,升级 Xcode 主版本后再跑,某一步 make 报错,报错内容指向汇编指令不识别或链接器参数不认可。
原因:源码目录里保留了上一次 configure 生成的config.h、config.mak、config.log。Xcode 升级后 SDK 路径和 clang 默认行为都变了,旧的 config 文件还指向旧环境,继续 make 时会复用缓存的配置,而不是按新环境重新生成。
解决:所有库在 configure 之前都执行make distclean,同时脚本里把“检测到 Xcode 版本变化”作为触发全部重编的条件。这个版本号的校验逻辑放在第 6 章的版本锁里一起讲。这里先记住一个原则:distclean不是可选项,是必要项。
4.4 上架许可:fdk-aac nonfree 与 GPL 的组合问题
现象:App 开发到一半,法务或 Leader 问一句“你确定这个库的许可没问题吗”,然后整个音视频能力被暂缓。
原因:fdk-aac 的库本身不是 GPL,而是需要单独获得授权的编码器;FFmpeg 里它的开关叫 nonfree。x264 和 lame 则默认是 GPL 系。混编后产物同时带有 GPL 和 nonfree 特征,如果你的 App 走应用市场上架,这需要提前走许可评估。
解决:技术上,脚本里--enable-gpl --enable-nonfree两个开关拿掉任何一个,configure 阶段就会自动禁用对应库。所以脚本会明确提示“当前产物含 GPL+nonfree,仅建议内部评估或学习验证使用”。商业项目如果必须用这些编码器,建议通过正当途径获取授权,或把音频编码切到 FFmpeg 内置的 AAC 编码器绕开 fdk-aac。这不是技术问题,但在一键脚本里留一句提醒,能让你在推进“一键”时不掉进合规的大坑。
5. 验证产物:把 .a 文件送进真实 App 工程前的三个动作
编译出 fat 库不代表结束,它只是从“脚本能跑”到“工程能用”的起点。这一章讲三个验证动作,顺序别乱。
5.1 用 lipo -info 确认 fat 库的架构片
lipo -info build/fat/libavcodec.a输出应类似Architectures in the fat file: ... are: arm64 arm64 x86_64。看到两个 arm64 时别慌,它们分别来自真机 slice 和模拟器 slice。
第一个信息点是架构数量。只有单个架构时,先怀疑模拟器循环没跑,或者SIM_SLICES数组在 Apple Silicon 上回退成了空值。第二个信息点是看 fat 是否同时包含 x86_64,如果你的目标用户还有 Intel Mac 上的模拟器,这一片不能省。做完这步再谈集成,否则链接阶段的报错会误导你去查脚本里的 cflags。
5.2 用 nm 验证符号与依赖:x264、fdk-aac、mp3lame 是否真的被链接
nm -gU build/fat/libavcodec.a | grep -E "x264_encoder_open|aacEncOpen|lame_init"这段命令检查三个关键符号是否存在于静态库中。-gU表示只显示全局导出符号,x264_encoder_open是 x264 编码器入口,aacEncOpen来自 fdk-aac,lame_init来自 lame。三个符号都在,说明 FFmpeg configure 阶段的 enable 开关确实生效了,外部库被真正编了进来。
如果 grep 结果里少了某一个符号,优先回头检查 FFmpeg 的 configure 日志里对应的检测结果。常见情况是:头文件目录-I路径指对了,但库目录-L没指对,configure 找到了头文件却找不到库,于是静默地把该功能标记为no。此时 configure 不会报错,只有 nm 才能揪出来。这一步是把“看起来编了”变成“确实编了”的分水岭。
5.3 最小验证 Demo:在 Xcode 工程里跑一次转码
#import <Foundation/Foundation.h> #import <lame/lame.h> - (void)verifyLame { lame_t lame = lame_init(); NSAssert(lame != NULL, @"lame 初始化失败,静态库链接有问题"); lame_close(lame); }在 Xcode 工程里新建一个空 App,把 fat 库拖进 Link Binary With Libraries,把${BUILD_DIR}/fat/include配进 Header Search Paths,然后在启动方法里调用lame_init。这块代码的逻辑很直白:如果静态库的链接和头文件路径有问题,编译或运行时会立刻暴露,比你把整个播放器接进去再排查要省时间得多。
建议按架构跑两次,模拟器跑一次,真机跑一次。特别是 M 系列芯片上,模拟器 arm64 与真机 arm64 的 slice 选择逻辑不同,两次都通过,才说明 fat 库的架构组合没问题。跑完这个最小 Demo,再把它删掉,回到你的真实音视频管线里验证 FFmpeg 的转码 API。
6. 把脚本从“一次能用”变成“长期复用”:版本锁与增量构建
脚本能交差和脚本能复用之间,差一个版本锁。我把“版本号记录在构建产物里”这句教训写死在脚本里之后,再没因为 Xcode 升级而翻车过。
declare -A VERSION_LOCK=( [x264]="2024-06-01" [fdk_aac]="2.0.3" [lame]="3.100" ) need_rebuild() { local lib=$1 arch=$2 local marker="${MANIFEST_DIR}/${lib}_${arch}.done" if [ -f "$marker" ] && [ "$(cat "$marker")" = "${VERSION_LOCK[$lib]}" ]; then return 1 fi return 0 }细看这段,它把每个库的版本号放进关联数组,每次构建成功后写一个标记文件。下次脚本运行时,标记文件里的版本号与 VERSION_LOCK 一致,就跳过该库的 configure 和 make。版本号变了或标记文件不存在,才触发重编。这样当你把 script 从一台 Mac 拷到另一台 Mac,或者换了个 Xcode 版本,只需要重新执行一次脚本,它会自动把所有版本不一致的库重建一遍,不用手动去删 build 目录。
增量构建配合日志留痕是个好习惯:每个库每架构的 log 独立存放,失败时脚本把对应 log 的最后 30 行打印出来,你会少翻很多次终端输出。这套组合的本质是把“编译靠运气”变成“编译靠证据”,版本锁就是你的后悔药——想回退到上一版 x264,改一个数组值,重新运行,一切回到可复现状态。
我自己的习惯是每次把固化版本的脚本和 VERSION_LOCK 一起提交到工程仓库,新同学克隆下来直接跑,不需要重新踩一遍我当年踩过的坑。版本锁、增量构建、日志留痕,这三样加起来,才配得上“一键”这两个字。希望帮到你。
本文还有配套的精品资源,点击获取