Skip to content

Commit ecc5c65

Browse files
committed
Replace .zip with a self-extracting 7-zip (#87)
Cuts the distribution size by around 60%, and unpacks around 100x faster than Windows built-in .zip support. However, 7-zip is the worst packaged project included so far. The source release is a tarbomb with a URL that contains two variations of the release version. It is not designed for cross-compilation, and so requires minor source corrections and a custom build script. Still, considering the circumstances, it's surprising how easily it compiles.
1 parent f004250 commit ecc5c65

File tree

6 files changed

+167
-35
lines changed

6 files changed

+167
-35
lines changed

Dockerfile

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ FROM debian:bookworm-slim
22

33
ARG VERSION=1.23.0
44
ARG PREFIX=/w64devkit
5+
ARG Z7_VERSION=2301
56
ARG BINUTILS_VERSION=2.42
67
ARG BUSYBOX_VERSION=FRP-5398-g89ae34445
78
ARG CTAGS_VERSION=6.0.0
@@ -18,11 +19,12 @@ ARG PDCURSES_VERSION=3.9
1819
ARG VIM_VERSION=9.0
1920

2021
RUN apt-get update && apt-get install --yes --no-install-recommends \
21-
build-essential curl libgmp-dev libmpc-dev libmpfr-dev m4 zip
22+
build-essential curl libgmp-dev libmpc-dev libmpfr-dev m4 p7zip-full
2223

2324
# Download, verify, and unpack
2425

2526
RUN curl --insecure --location --remote-name-all --remote-header-name \
27+
https://downloads.sourceforge.net/project/sevenzip/7-Zip/23.01/7z$Z7_VERSION-src.tar.xz \
2628
https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.xz \
2729
https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.xz \
2830
https://ftp.gnu.org/gnu/gdb/gdb-$GDB_VERSION.tar.xz \
@@ -39,6 +41,7 @@ RUN curl --insecure --location --remote-name-all --remote-header-name \
3941
https://downloads.sourceforge.net/project/pdcurses/pdcurses/$PDCURSES_VERSION/PDCurses-$PDCURSES_VERSION.tar.gz
4042
COPY src/SHA256SUMS $PREFIX/src/
4143
RUN sha256sum -c $PREFIX/src/SHA256SUMS \
44+
&& tar xJf 7z$Z7_VERSION-src.tar.xz --xform 's%^%7z/%' \
4245
&& tar xJf binutils-$BINUTILS_VERSION.tar.xz \
4346
&& tar xzf busybox-w32-$BUSYBOX_VERSION.tgz \
4447
&& tar xzf ctags-$CTAGS_VERSION.tar.gz \
@@ -446,6 +449,13 @@ RUN sed -i /RT_MANIFEST/d win32/ctags.rc \
446449
OPT= CFLAGS=-Os LDFLAGS=-s \
447450
&& cp ctags.exe $PREFIX/bin/
448451

452+
WORKDIR /7z
453+
COPY src/7z.mak $PREFIX/src/
454+
RUN sed -i s/CommCtrl/commctrl/ $(grep -Rl CommCtrl CPP/) \
455+
&& sed -i s%7z\\.ico%$PREFIX/src/w64devkit.ico% \
456+
CPP/7zip/Bundles/SFXWin/resource.rc \
457+
&& make -f $PREFIX/src/7z.mak -j$(nproc) CROSS=$ARCH-
458+
449459
# Pack up a release
450460

451461
WORKDIR /
@@ -486,6 +496,7 @@ RUN printf "id ICON \"$PREFIX/src/w64devkit.ico\"" >w64devkit.rc \
486496
>>$PREFIX/COPYING.MinGW-w64-runtime.txt . \
487497
&& cat /mingw-w64-v$MINGW_VERSION/mingw-w64-libraries/winpthreads/COPYING \
488498
>>$PREFIX/COPYING.MinGW-w64-runtime.txt \
489-
&& echo $VERSION >$PREFIX/VERSION.txt
499+
&& echo $VERSION >$PREFIX/VERSION.txt \
500+
&& 7z a -mx=9 $PREFIX.7z $PREFIX
490501
ENV PREFIX=${PREFIX}
491-
CMD zip -q9Xr - $PREFIX
502+
CMD cat /7z/7z.sfx $PREFIX.7z

README.md

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ the kit itself.
2020

2121
## Build
2222

23-
First build the image, then run it to produce a distribution .zip file:
23+
Build the image, then run it to produce a self-extracting 7z archive:
2424

2525
docker build -t w64devkit .
26-
docker run --rm w64devkit >w64devkit.zip
26+
docker run --rm w64devkit >w64devkit-x64.exe
2727

28-
This takes about half an hour on modern systems. You will need an internet
28+
This takes about 15 minutes on modern systems. You will need an internet
2929
connection during the first few minutes of the build. **Note:** Do not use
3030
PowerShell because it lacks file redirection.
3131

3232
## Usage
3333

34-
The final .zip file contains tools in a typical unix-like configuration.
35-
Unzip the contents anywhere. Inside is `w64devkit.exe`, which launches a
36-
console window with the environment configured and ready to go. It is the
37-
easiest way to enter the development environment, and requires no system
38-
changes. It also sets two extra environment variables: `W64DEVKIT_HOME` to
39-
the installation root and `W64DEVKIT` to the version.
34+
The self-extracting 7z archive contains tools in a typical unix-like
35+
configuration. Extract wherever is convenient. Inside is `w64devkit.exe`,
36+
which launches a console window with the environment configured and ready
37+
to go. It is the easiest way to enter the development environment, and
38+
requires no system changes. It also sets two extra environment variables:
39+
`W64DEVKIT_HOME` to the installation root and `W64DEVKIT` to the version.
4040

4141
Alternatively, add the `bin/` directory to your path. For example, inside
4242
a `cmd.exe` console or batch script:
@@ -176,12 +176,6 @@ ported to Mingw-w64][san] ([also][san2]), but Undefined Behavior Sanitizer
176176
`-fsanitize-trap`, GDB will [break precisely][break] on undefined
177177
behavior, and it does not require linking with libsanitizer.
178178

179-
Since the build environment is so stable and predicable, it would be
180-
great for the .zip to be reproducible, i.e. builds by different people
181-
are bit-for-bit identical. There are multiple reasons why this is not
182-
currently the case, the least of which are [timestamps in the .zip
183-
file][zip].
184-
185179
## Licenses
186180

187181
When distributing binaries built using w64devkit, your .exe will include
@@ -225,4 +219,3 @@ binaries.
225219
[vim]: https://www.vim.org/
226220
[w64]: http://mingw-w64.org/
227221
[w64devkit]: https://github.com/skeeto/w64devkit
228-
[zip]: https://tanzu.vmware.com/content/blog/barriers-to-deterministic-reproducible-zip-files

multibuild.sh

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@
99

1010
set -e
1111
arch=""
12-
compact=no
1312
dryrun=
1413
flavors=""
1514
suffix="$(git describe --exact-match 2>/dev/null | tr v - || true)"
1615

1716
usage() {
1817
cat <<EOF
1918
usage: multibuild.sh [-48abfhnOs] [-s SUFFIX]
20-
-4 Enable i686 build (default: no)
21-
-8 Enable x86_64 build (default: auto)
19+
-4 Enable x86 build (default: no)
20+
-8 Enable x64 build (default: auto)
2221
-a All: Enable all builds
2322
-h Print this help message
2423
-n Dry run, print commands but do nothing
@@ -29,12 +28,11 @@ EOF
2928

3029
while getopts 48abfhmnOs: opt; do
3130
case $opt in
32-
4) arch="$arch w64devkit-i686";;
33-
8) arch="$arch w64devkit";;
34-
a) flavors="X"; arch="w64devkit w64devkit-i686";;
31+
4) arch="$arch w64devkit-x86";;
32+
8) arch="$arch w64devkit-x64";;
33+
a) flavors="X"; arch="w64devkit-x64 w64devkit-x86";;
3534
h) usage; exit 0;;
3635
n) dryrun=echo;;
37-
O) compact=yes;;
3836
s) suffix="$OPTARG";;
3937
?) usage >&2; exit 1;;
4038
esac
@@ -48,7 +46,7 @@ if [ $# -gt 0 ]; then
4846
fi
4947

5048
if [ -z "$arch" ]; then
51-
arch="w64devkit"
49+
arch="w64devkit-x64"
5250
fi
5351
if [ -z "$flavors" ]; then
5452
flavors="X"
@@ -76,20 +74,17 @@ for build in $builds; do
7674
IFS=-
7775
set $build; shift
7876
for flavor in "$@"; do
79-
$dryrun patch -p1 -i src/variant-$flavor.patch
77+
if [ -e src/variant-$flavor.patch ]; then
78+
$dryrun patch -p1 -i src/variant-$flavor.patch
79+
fi
8080
done
8181
)
8282
$dryrun docker build -t $target .
8383
if [ -n "$dryrun" ]; then
84-
$dryrun docker run --rm $target ">$build$suffix.zip"
84+
$dryrun docker run --rm $target ">$build$suffix.exe"
8585
else
86-
docker run --rm $target >$build$suffix.zip
86+
docker run --rm $target >$build$suffix.exe
8787
fi
8888
done
8989

90-
if [ $compact = yes ]; then
91-
printf "%s$suffix.zip\n" $builds \
92-
| xargs -I{} -P$(nproc) $dryrun advzip -z4 {}
93-
fi
94-
9590
cleanup

src/7z.mak

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
CROSS = x86_64-w64-mingw32-
2+
CC = $(CROSS)gcc
3+
CXX = $(CROSS)g++
4+
WINDRES = $(CROSS)windres
5+
LDFLAGS = -mwindows -s -Wl,--gc-sections
6+
LDLIBS = -lcomdlg32 -lole32 -loleaut32 -luuid
7+
CFLAGS = -fno-ident -Oz \
8+
-DZ7_SFX \
9+
-DZ7_EXTRACT_ONLY \
10+
-DZ7_NO_CRYPTO \
11+
-DZ7_NO_REGISTRY \
12+
-DZ7_NO_READ_FROM_CODER \
13+
14+
obj = \
15+
CPP/7zip/Bundles/SFXWin/resource.o \
16+
CPP/7zip/Bundles/SFXWin/SfxWin.o \
17+
CPP/7zip/UI/GUI/ExtractDialog.o \
18+
CPP/7zip/UI/GUI/ExtractGUI.o \
19+
CPP/Common/CRC.o \
20+
CPP/Common/CommandLineParser.o \
21+
CPP/Common/IntToString.o \
22+
CPP/Common/NewHandler.o \
23+
CPP/Common/MyString.o \
24+
CPP/Common/StringConvert.o \
25+
CPP/Common/MyVector.o \
26+
CPP/Common/Wildcard.o \
27+
CPP/Windows/Clipboard.o \
28+
CPP/Windows/CommonDialog.o \
29+
CPP/Windows/DLL.o \
30+
CPP/Windows/ErrorMsg.o \
31+
CPP/Windows/FileDir.o \
32+
CPP/Windows/FileFind.o \
33+
CPP/Windows/FileIO.o \
34+
CPP/Windows/FileName.o \
35+
CPP/Windows/MemoryGlobal.o \
36+
CPP/Windows/PropVariant.o \
37+
CPP/Windows/PropVariantConv.o \
38+
CPP/Windows/ResourceString.o \
39+
CPP/Windows/Shell.o \
40+
CPP/Windows/Synchronization.o \
41+
CPP/Windows/System.o \
42+
CPP/Windows/Window.o \
43+
CPP/Windows/Control/ComboBox.o \
44+
CPP/Windows/Control/Dialog.o \
45+
CPP/Windows/Control/ListView.o \
46+
CPP/7zip/Common/CreateCoder.o \
47+
CPP/7zip/Common/CWrappers.o \
48+
CPP/7zip/Common/FilePathAutoRename.o \
49+
CPP/7zip/Common/FileStreams.o \
50+
CPP/7zip/Common/InBuffer.o \
51+
CPP/7zip/Common/FilterCoder.o \
52+
CPP/7zip/Common/LimitedStreams.o \
53+
CPP/7zip/Common/OutBuffer.o \
54+
CPP/7zip/Common/ProgressUtils.o \
55+
CPP/7zip/Common/PropId.o \
56+
CPP/7zip/Common/StreamBinder.o \
57+
CPP/7zip/Common/StreamObjects.o \
58+
CPP/7zip/Common/StreamUtils.o \
59+
CPP/7zip/Common/VirtThread.o \
60+
CPP/7zip/UI/Common/ArchiveExtractCallback.o \
61+
CPP/7zip/UI/Common/ArchiveOpenCallback.o \
62+
CPP/7zip/UI/Common/DefaultName.o \
63+
CPP/7zip/UI/Common/Extract.o \
64+
CPP/7zip/UI/Common/ExtractingFilePath.o \
65+
CPP/7zip/UI/Common/LoadCodecs.o \
66+
CPP/7zip/UI/Common/OpenArchive.o \
67+
CPP/7zip/UI/Explorer/MyMessages.o \
68+
CPP/7zip/UI/FileManager/BrowseDialog.o \
69+
CPP/7zip/UI/FileManager/ComboDialog.o \
70+
CPP/7zip/UI/FileManager/ExtractCallback.o \
71+
CPP/7zip/UI/FileManager/FormatUtils.o \
72+
CPP/7zip/UI/FileManager/OverwriteDialog.o \
73+
CPP/7zip/UI/FileManager/PasswordDialog.o \
74+
CPP/7zip/UI/FileManager/ProgressDialog2.o \
75+
CPP/7zip/UI/FileManager/PropertyName.o \
76+
CPP/7zip/UI/FileManager/SysIconUtils.o \
77+
CPP/7zip/Archive/SplitHandler.o \
78+
CPP/7zip/Archive/Common/CoderMixer2.o \
79+
CPP/7zip/Archive/Common/ItemNameUtils.o \
80+
CPP/7zip/Archive/Common/MultiStream.o \
81+
CPP/7zip/Archive/Common/OutStreamWithCRC.o \
82+
CPP/7zip/Archive/7z/7zDecode.o \
83+
CPP/7zip/Archive/7z/7zExtract.o \
84+
CPP/7zip/Archive/7z/7zHandler.o \
85+
CPP/7zip/Archive/7z/7zIn.o \
86+
CPP/7zip/Archive/7z/7zRegister.o \
87+
CPP/7zip/Compress/Bcj2Coder.o \
88+
CPP/7zip/Compress/Bcj2Register.o \
89+
CPP/7zip/Compress/BcjCoder.o \
90+
CPP/7zip/Compress/BcjRegister.o \
91+
CPP/7zip/Compress/BranchMisc.o \
92+
CPP/7zip/Compress/BranchRegister.o \
93+
CPP/7zip/Compress/CopyCoder.o \
94+
CPP/7zip/Compress/CopyRegister.o \
95+
CPP/7zip/Compress/DeltaFilter.o \
96+
CPP/7zip/Compress/Lzma2Decoder.o \
97+
CPP/7zip/Compress/Lzma2Register.o \
98+
CPP/7zip/Compress/LzmaDecoder.o \
99+
CPP/7zip/Compress/LzmaRegister.o \
100+
CPP/7zip/Compress/PpmdDecoder.o \
101+
CPP/7zip/Compress/PpmdRegister.o \
102+
C/7zCrc.o \
103+
C/7zCrcOpt.o \
104+
C/7zStream.o \
105+
C/Alloc.o \
106+
C/Bcj2.o \
107+
C/Bra.o \
108+
C/Bra86.o \
109+
C/BraIA64.o \
110+
C/CpuArch.o \
111+
C/Delta.o \
112+
C/DllSecur.o \
113+
C/Lzma2Dec.o \
114+
C/Lzma2DecMt.o \
115+
C/LzmaDec.o \
116+
C/MtDec.o \
117+
C/Ppmd7.o \
118+
C/Ppmd7Dec.o \
119+
C/Sha256.o \
120+
C/Sha256Opt.o \
121+
C/Threads.o \
122+
123+
7z.sfx: $(obj)
124+
$(CXX) $(LDFLAGS) -o $@ $(obj) $(LDLIBS)
125+
clean:
126+
rm -f 7z.sfx $(obj)
127+
%.o: %.cpp
128+
$(CXX) -c $(CFLAGS) -o $@ $^
129+
%.o: %.c
130+
$(CC) -c $(CFLAGS) -o $@ $^
131+
%.o: %.rc
132+
$(WINDRES) -o $@ $^

src/SHA256SUMS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
356071007360e5a1824d9904993e8b2480b51b570e8c9faf7c0f58ebe4bf9f74 7z2301-src.tar.xz
12
f6e4d41fd5fc778b06b7891457b3620da5ecea1006c6a4a41ae998109f85a800 binutils-2.42.tar.xz
23
e366f887a56bf6f64adff15b7b08ba487fea14c121045078437abe7217cf060d busybox-w32-FRP-5398-g89ae34445.tgz
34
71229a73f25529c9e3dabb2cb7310c55405d31caee8e8a9ab5c71b2406d4005a ctags-6.0.0.tar.gz
File renamed without changes.

0 commit comments

Comments
 (0)