在之前的博客中介绍了一个差分包工具 zstd
(虽然说人家的专业是压缩软件,谁让它的差分能力那么出众呢)。
这货很能打,用起来也很爽。但是有个痛点就是制作差分包的时候有文件大小限制:不支持大于 2G
的文件。
但是在使用中经常遇到这种情况,为了彻底不再忍受 bsdiff
那蜗牛般的速度,遂决定通过修改 ztsd
源代码来支持对 2G
文件的支持。
由于我主要的使用场景是在 Windows
系统,所以记录的是构建 Windows
下的可执行程序。
但是我又不想在 Windows
下折腾 VS
和 MinGW-w64
,最终采用 Debian
容器安装 MinGW-w64
的方式来编译。
想要折腾
VS
或者Windows
下的MinGW-w64
的可以参考我的另外两篇笔记:
源码
zstd
的源码是开源的,地址在:https://github.com/facebook/zstd
因为我要修改,所以 fork
了一份:https://github.com/lx0758/zstd
克隆一份:
cd ~/projects/
git clone https://github.com/lx0758/zstd
镜像
基础环境镜像
构建镜像
docker build -t build-base - <<\EOF
FROM debian:12
RUN <<EOT
sed -e 's|deb.debian.org|mirrors.tuna.tsinghua.edu.cn|g' -i.bak /etc/apt/sources.list.d/debian.sources
apt update
apt install -y sudo bash-completion command-not-found
apt update
apt clean && rm -rf /var/lib/apt/lists/*
EOT
COPY <<EOT /etc/profile.d/aliases.sh
alias ll='ls -lh -F --color=auto --time-style=long-iso'
alias la='ls -lhA -F --color=auto --time-style=long-iso'
alias lt='ls -lht -F --color=auto --time-style=long-iso'
alias lat='ls -lhAt -F --color=auto --time-style=long-iso'
EOT
ENV TZ=Asia/Shanghai
RUN <<EOT
useradd --create-home --uid 1000 --groups users,sudo --shell /bin/bash user
echo "user:1111" | chpasswd
ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime
echo "${TZ}" > /etc/timezone
EOT
USER user
WORKDIR /home/user/
EOF
- 使用管道输入
Dockerfile
内容,自定义镜像标签为build-base
。
https://docs.docker.com/build/building/context/#how-to-build-without-a-context- 使用
Here-Documents
运行RUN
、COPY
指令,注意如果是在Dockerfile
中使用需要保证文件换行符是LF
。
https://docs.docker.com/reference/dockerfile/#here-documents
使用镜像
docker run -ti --rm build-base bash -l
- 默认为
non-login
的shell
,需要使用 ‘-l’ 参数登录以生效/etc/profile
配置。
https://github.com/gliderlabs/docker-alpine/issues/443
编译环境镜像
构建镜像
docker build -t build-windows - <<\EOF
FROM build-base
USER root
RUN <<EOT
apt update
apt install -y make mingw-w64
apt clean && rm -rf /var/lib/apt/lists/*
EOT
USER user
EOF
- 软件包
mingw-w64
提供了在Linux
编译Windows
下x86
和x64
架构的程序的工具链.
使用镜像
docker run -ti --rm --privileged -v ~/projects/:/projects/ build-windows bash -l
构建
声明工具链
zstd
的 Makefile
中默认没有设置工具链的配置,所以需要改造一下 Makefile
:
diff --git a/Makefile b/Makefile
index 5598cdd0..554a82f0 100644
--- a/Makefile
+++ b/Makefile
@@ -206,7 +206,7 @@ clangbuild-darwin-fat: clean
mv programs/zstd programs/zstd_x64
lipo -create programs/zstd_x64 programs/zstd_arm64 -output programs/zstd
-.PHONY: gcc5build gcc6build gcc7build clangbuild m32build armbuild aarch64build ppcbuild ppc64build
+.PHONY: gcc5build gcc6build gcc7build clangbuild m32build armbuild aarch64build ppcbuild ppc64build mingw64build
gcc5build: clean
gcc-5 -v
CC=gcc-5 $(MAKE) all MOREFLAGS="-Werror $(MOREFLAGS)"
@@ -239,6 +239,10 @@ ppcbuild: clean
ppc64build: clean
CC=powerpc-linux-gnu-gcc CFLAGS="-m64 -Werror" $(MAKE) -j allzstd
+mingw64build: clean
+ x86_64-w64-mingw32-gcc -v
+ CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar $(MAKE) all MOREFLAGS="$(MOREFLAGS)"
+
.PHONY: armfuzz aarch64fuzz ppcfuzz ppc64fuzz
armfuzz: clean
CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static MOREFLAGS="-static $(MOREFLAGS)" FUZZER_FLAGS="--no-big-tests $(FUZZER_FLAGS)" $(MAKE) -C $(TESTDIR) fuzztest
x86_64-w64-mingw32-
是MingW-w64
编译x64
软件的工具链前缀。i686-w64-mingw32-
是MingW-w64
编译x86
软件的工具链前缀,我这没有用到。
修改源码
这个改动最终就比较大了,详情见提交:
https://github.com/lx0758/zstd/tree/64g
改了源码只验证了我需要的功能,没有补全单元测试用例。凑合用吧~
编译
cd /projects/
make TARGET_SYSTEM=Windows mingw64build
实践证明这个源码用这种方式编译不能开多线程,否则编译失败。
产物
相关的编译产物已经归档至 Github
,方便有需要的朋友直接取用:
https://github.com/lx0758/zstd/releases
使用
# 创建差分补丁
$ ls -lh
总用量 14G
-rw-r--r-- 1 Liux 197121 6.5G 2024-10-19 23:23 zh-cn_windows_10_business_editions_version_22h2_updated_july_2024_x64_dvd_53d015e8.iso
-rw-r--r-- 1 Liux 197121 6.6G 2024-10-19 23:22 zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso
$ sha1sum zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso
4c80a05919a1eb838d5b5174bd4985e7374fca64 *zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso
$ ./zstd.exe --patch-from=zh-cn_windows_10_business_editions_version_22h2_updated_july_2024_x64_dvd_53d015e8.iso zh-cn
_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso -o windows.diff
long mode automatically triggered
zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso : 87.73% ( 6.59 GiB => 5.79 GiB, windows.diff)
# 差分还原
$ ../zstd.exe -d --patch-from=zh-cn_windows_10_business_editions_version_22h2_updated_july_2024_x64_dvd_53d015e8.iso windows.diff -o zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso
windows.diff : 7080916992 bytes
$ sha1sum zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso
4c80a05919a1eb838d5b5174bd4985e7374fca64 *zh-cn_windows_11_business_editions_version_23h2_updated_july_2024_x64_dvd_8c3fbaa8.iso
- 这里使用两个基本不相关的
Windows
安装镜像做了测试,差分功能正常。- 对于测试的这个
6.5G
超大文件差分操作,大约需要占用7.5G
内存。内存不足会报zstd: windows.diff: Permission denied
错误。