3. 环境搭建与工具链
说实话,做差分包这件事,工具链就是你的武器库。武器没磨好,上了战场肯定吃亏。我见过不少新手,一上来就急着写脚本调参数,结果环境没配好,编译报错就卡了半天。咱们今天就把这事一次性搞定。
这一章的核心就三件事:准备Linux环境、编译bsdiff、编译xdelta3。别小看这三步,每一步都有坑。我会把我在项目中踩过的坑、绕过的路,都给你指出来。
3.1 Linux环境准备
你可能会问:为什么非要用Linux?Windows不行吗?
嗯,理论上可以。但bsdiff和xdelta3这两个工具,从诞生那天起就是为Unix-like系统设计的。我在Windows上用Cygwin折腾过,编译倒是能过,但性能差了一大截。说白了,生产环境几乎全是Linux,你何必跟自己过不去?
3.1.1 基础依赖安装
我习惯用Ubuntu 20.04 LTS或CentOS 7作为开发机。如果你手头没有物理机,用Docker拉一个镜像也行。我个人更推荐Ubuntu,包管理更友好,社区资源也多。
先装基础工具链:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y build-essential autoconf automake libtool
sudo apt-get install -y git wget curl vim
# CentOS/RHEL
sudo yum groupinstall -y "Development Tools"
sudo yum install -y autoconf automake libtool
sudo yum install -y git wget curl vim
这里有个细节:build-essential 这个包组包含了gcc、g++、make等核心编译工具。我刚开始做的时候,以为装个gcc就够了,结果编译bsdiff时发现缺了make,又回头补装。你一次装齐,省得来回折腾。
3.1.2 验证环境
装完之后,跑一下验证命令:
gcc --version
g++ --version
make --version
autoconf --version
确保每个命令都能正常输出版本号。如果哪个报错,就回去检查对应的包有没有装成功。
/opt 下建一个 diff-tools 目录,专门放编译好的工具。这样不会污染系统路径,也方便后续管理。
3.2 编译bsdiff工具
bsdiff是Colin Percival在2003年提出的算法,专门用于二进制文件的差分。它的核心思想是用后缀排序来寻找最长公共子串。嗯,算法细节咱们后面再讲,今天先把工具编出来。
3.2.1 获取源码
bsdiff的源码托管在FreeBSD的官方仓库里。我习惯直接从GitHub上拉:
cd /opt/diff-tools
git clone https://github.com/mendsley/bsdiff.git
cd bsdiff
注意:原版的bsdiff依赖bzip2库。如果你的系统没装,需要先装一下:
sudo apt-get install -y libbz2-dev # Ubuntu
sudo yum install -y bzip2-devel # CentOS
3.2.2 编译过程
bsdiff的编译很简单,没有复杂的configure脚本。直接make就行:
make
如果一切顺利,你会看到生成了两个可执行文件:bsdiff 和 bspatch。前者用来生成差分包,后者用来还原。
但这里有个坑——原版bsdiff对大文件支持不好。我记得有一次,我要处理一个500MB的固件包,bsdiff直接报内存溢出。后来我查了源码,发现它内部用了int类型来存储偏移量,超过2GB就会溢出。
解决方案是打一个补丁,把int改成off_t。我在GitHub上找到了一个修改版:
git clone https://github.com/ivan1986/bsdiff.git
cd bsdiff
make
这个版本已经修复了大文件问题。我个人建议你直接用这个fork,省得自己改源码。
3.2.3 安装到系统路径
sudo cp bsdiff bspatch /usr/local/bin/
验证一下:
bsdiff
如果输出帮助信息,说明安装成功。
3.3 编译xdelta3工具
xdelta3是另一种差分算法,基于VCDIFF标准(RFC 3284)。和bsdiff相比,xdelta3的优点是内存占用低、速度快,但压缩率略差一些。实际项目中,我经常把两者结合起来用:bsdiff做离线全量差分,xdelta3做在线增量更新。
3.3.1 获取源码
cd /opt/diff-tools
git clone https://github.com/jmacd/xdelta.git
cd xdelta
xdelta3的源码结构比较清晰,核心算法在xdelta3.c和xdelta3.h里。它依赖liblzma做二次压缩,所以需要先装这个库:
sudo apt-get install -y liblzma-dev # Ubuntu
sudo yum install -y xz-devel # CentOS
3.3.2 编译过程
xdelta3使用autoconf/automake构建系统。标准流程:
autoreconf -i
./configure
make
sudo make install
这里有个细节:autoreconf -i 会生成configure脚本。如果你直接运行./configure报错,八成是autoconf版本不对。我遇到过一回,Ubuntu 18.04自带的autoconf版本太老,跑不起来。升级一下就好了:
sudo apt-get install -y autoconf-archive
编译完成后,可执行文件是xdelta3。验证一下:
xdelta3 --version
如果输出版本号,说明安装成功。
3.3.3 编译选项说明
xdelta3的configure脚本支持一些有用的选项:
| 选项 | 说明 | 推荐值 |
|---|---|---|
--enable-lzma |
启用LZMA二次压缩 | 开启(默认) |
--enable-debug |
开启调试日志 | 生产环境关闭 |
--with-xdelta3-level |
设置默认压缩级别 | 9(最高压缩) |
--enable-dl |
动态加载外部压缩库 | 按需开启 |
我个人建议生产环境用这个配置:
./configure --enable-lzma --with-xdelta3-level=9
make
sudo make install
对一个100MB的APK文件做差分:
- bsdiff:耗时约45秒,差分包大小约8MB
- xdelta3:耗时约12秒,差分包大小约12MB
你看,bsdiff压缩率更好,但xdelta3快了近4倍。选哪个?看你的场景。
3.4 工具链验证
工具都装好了,咱们做个快速验证。我准备两个小文件:
# 创建测试文件
echo "Hello, this is version 1.0" > old.txt
echo "Hello, this is version 2.0 with some changes" > new.txt
# 用bsdiff生成差分
bsdiff old.txt new.txt patch.bsdiff
# 用bspatch还原
bspatch old.txt restored.txt patch.bsdiff
# 验证还原结果
diff new.txt restored.txt
如果diff命令没有输出,说明还原成功。xdelta3的验证类似:
# 生成差分
xdelta3 -e -s old.txt new.txt patch.xdelta3
# 还原
xdelta3 -d -s old.txt patch.xdelta3 restored.txt
# 验证
diff new.txt restored.txt
3.5 本章知识结构
我把这一章的核心流程画成了图,方便你对照操作:
环境搭建这块,说白了就是一次性的体力活。但别小看它——我见过太多人因为环境没配好,后面调试差分算法时,分不清是代码bug还是工具问题。所以,花半小时把环境搞扎实,后面能省你半天时间。