Skip to content

Commit 2735bd7

Browse files
committed
fix: Ensure bit-for-bit reproducibility of AppImage builds.
Normalization of file timestamps and permissions was happening before some plugins were copied and the deploy step was run, making files in the AppDir non-deterministic. We now move the normalization to just before AppImage creation. Also, stop unsetting `SOURCE_DATE_EPOCH` during packaging. To avoid conflicts with `appimagetool`'s `-fstime` argument (which defaults to the current time), wrap `mksquashfs` to strip the `-fstime` flag, allowing it to honor the environment variable for the SquashFS superblock.
1 parent 3dfd682 commit 2735bd7

1 file changed

Lines changed: 29 additions & 13 deletions

File tree

platform/appimage/build.sh

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,25 @@ mv squashfs-root "$TOOL_EXTRACT_DIR"
9797
# This line in the appimagetool breaks musl DNS lookups (looking for /EEE/resolv.conf).
9898
sed -i -e 's!/EEE!/etc!g' "$TOOL_EXTRACT_DIR/usr/bin/appimagetool"
9999

100+
# appimagetool (go-appimage) passes -fstime to mksquashfs, which conflicts with
101+
# SOURCE_DATE_EPOCH environment variable. We wrap mksquashfs to strip -fstime,
102+
# allowing it to honor SOURCE_DATE_EPOCH for the superblock as well.
103+
mv "$TOOL_EXTRACT_DIR/usr/bin/mksquashfs" "$TOOL_EXTRACT_DIR/usr/bin/mksquashfs.real"
104+
cat >"$TOOL_EXTRACT_DIR/usr/bin/mksquashfs" <<'EOF'
105+
#!/usr/bin/env bash
106+
args=()
107+
while [[ $# -gt 0 ]]; do
108+
if [[ "$1" == "-fstime" ]]; then
109+
shift 2
110+
else
111+
args+=("$1")
112+
shift
113+
fi
114+
done
115+
exec "$(dirname "$0")/mksquashfs.real" "${args[@]}"
116+
EOF
117+
chmod +x "$TOOL_EXTRACT_DIR/usr/bin/mksquashfs"
118+
100119
export PKG_CONFIG_PATH=/opt/buildhome/lib/pkgconfig
101120

102121
ccache --zero-stats
@@ -118,13 +137,6 @@ cmake --install _build --prefix "$PROJECT_NAME.AppDir/usr"
118137

119138
ccache --show-stats
120139

121-
# Normalize file permissions and timestamps for reproducibility
122-
echo "Normalizing AppDir..."
123-
find "$PROJECT_APP_DIR" -exec touch -h -d @"$SOURCE_DATE_EPOCH" {} +
124-
find "$PROJECT_APP_DIR" -type d -exec chmod 0755 {} +
125-
find "$PROJECT_APP_DIR" -type f -perm /0111 -exec chmod 0755 {} +
126-
find "$PROJECT_APP_DIR" -type f ! -perm /0111 -exec chmod 0644 {} +
127-
128140
export QTDIR=/opt/buildhome/qt
129141
export LD_LIBRARY_PATH="/opt/buildhome/lib:/opt/buildhome/lib64:$QTDIR/lib"
130142

@@ -137,15 +149,19 @@ cp -r "$QTDIR/plugins/tls/" "$PROJECT_APP_DIR/$QTDIR/plugins/"
137149

138150
"$TOOL_EXTRACT_DIR/AppRun" -s deploy "$PROJECT_APP_DIR"/usr/share/applications/*.desktop
139151

152+
# Normalize file permissions and timestamps for reproducibility
153+
echo "Normalizing AppDir..."
154+
find "$PROJECT_APP_DIR" -exec touch -h -d @"$SOURCE_DATE_EPOCH" {} +
155+
find "$PROJECT_APP_DIR" -type d -exec chmod 0755 {} +
156+
find "$PROJECT_APP_DIR" -type f -perm /0111 -exec chmod 0755 {} +
157+
find "$PROJECT_APP_DIR" -type f ! -perm /0111 -exec chmod 0644 {} +
158+
140159
# print all links not contained inside the AppDir
141160
LD_LIBRARY_PATH='' find "$PROJECT_APP_DIR" -type f -exec ldd {} \; 2>&1 | grep '=>' | grep -v "$PROJECT_APP_DIR"
142161

143-
# appimagetool (go-appimage) passes -fstime to mksquashfs, which conflicts with
144-
# SOURCE_DATE_EPOCH environment variable.
145-
(
146-
unset SOURCE_DATE_EPOCH
147-
"$TOOL_EXTRACT_DIR/AppRun" "$PROJECT_APP_DIR"
148-
)
162+
# appimagetool (go-appimage) uses SOURCE_DATE_EPOCH for the SquashFS creation
163+
# time if set.
164+
"$TOOL_EXTRACT_DIR/AppRun" "$PROJECT_APP_DIR"
149165

150166
# Deterministic filename
151167
readonly SHA="$(git rev-parse --short HEAD | head -c7)"

0 commit comments

Comments
 (0)