diff --git a/Makefile b/Makefile index 4e9e16212..8724fe140 100644 --- a/Makefile +++ b/Makefile @@ -368,11 +368,9 @@ endif mv *.AppImage ../../koreader-$(DIST)-$(MACHINE)-$(VERSION).AppImage androidupdate: all - # in runtime luajit-launcher's libluajit.so will be loaded - -rm $(INSTALL_DIR)/koreader/libs/libluajit.so - - # fresh APK assets - rm -rfv $(ANDROID_ASSETS) $(ANDROID_LIBS_ROOT) + # Note: do not remove the module directory so there's no need + # for `mk7z.sh` to always recreate `assets.7z` from scratch. + rm -rfv $(ANDROID_LIBS_ROOT) mkdir -p $(ANDROID_ASSETS) $(ANDROID_LIBS_ABI) # APK version @@ -380,6 +378,8 @@ androidupdate: all # shared libraries are stored as raw assets cp -pR $(INSTALL_DIR)/koreader/libs $(ANDROID_LAUNCHER_DIR)/assets + # in runtime luajit-launcher's libluajit.so will be loaded + rm -vf $(ANDROID_LAUNCHER_DIR)/assets/libs/libluajit.so # binaries are stored as shared libraries to prevent W^X exception on Android 10+ # https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission @@ -387,31 +387,34 @@ androidupdate: all echo "sdcv libsdcv.so" > $(ANDROID_ASSETS)/map.txt # assets are compressed manually and stored inside the APK. - cd $(INSTALL_DIR)/koreader && 7z a -l -m0=lzma2 -mx=9 \ - ../../$(ANDROID_ASSETS)/koreader.7z * \ - -xr!*cache$ \ - -xr!*clipboard$ \ - -xr!*data/dict$ \ - -xr!*data/tessdata$ \ - -xr!*history$ \ - -xr!*l10n/templates$ \ - -xr!*libs$ \ - -xr!*ota$ \ - -xr!*resources/fonts* \ - -xr!*resources/icons/src* \ - -xr!*rocks/bin$ \ - -xr!*rocks/lib/luarocks$ \ - -xr!*screenshots$ \ - -xr!*share/man* \ - -xr!*spec$ \ - -xr!*tools$ \ - -xr!*COPYING$ \ - -xr!*Makefile$ \ - -xr!*NOTES.txt$ \ - -xr!*NOTICE$ \ - -xr!*README.md$ \ - -xr!*sdcv \ - -xr'!.*' + cd $(INSTALL_DIR)/koreader && \ + ./tools/mk7z.sh \ + ../../$(ANDROID_ASSETS)/koreader.7z \ + "$$(git show -s --format='%ci')" \ + -m0=lzma2 -mx=9 \ + -- . \ + '-x!cache' \ + '-x!clipboard' \ + '-x!data/dict' \ + '-x!data/tessdata' \ + '-x!history' \ + '-x!l10n/templates' \ + '-x!libs' \ + '-x!ota' \ + '-x!resources/fonts*' \ + '-x!resources/icons/src*' \ + '-x!rocks/bin' \ + '-x!rocks/lib/luarocks' \ + '-x!screenshots' \ + '-x!sdcv' \ + '-x!spec' \ + '-x!tools' \ + '-xr!.*' \ + '-xr!COPYING' \ + '-xr!NOTES.txt' \ + '-xr!NOTICE' \ + '-xr!README.md' \ + ; # make the android APK $(MAKE) -C $(ANDROID_LAUNCHER_DIR) $(if $(KODEBUG), debug, release) \ diff --git a/tools/mk7z.sh b/tools/mk7z.sh new file mode 100755 index 000000000..74093f5e0 --- /dev/null +++ b/tools/mk7z.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +set -eo pipefail +# set -x + +[[ $# -ge 3 ]] +archive="$(realpath "$1")" +epoch="$2" +shift 2 +options=() +for a in "$@"; do + shift + case "${a}" in + --) break ;; + -*) options+=("${a}") ;; + *) break ;; + esac +done +[[ $# -gt 0 ]] +patterns=("$@") + +# We need to use the full path to the executable to avoid +# a weird issue when using the p7zip project pre-built +# binary (`Can't load './7z.dll' (7z.so)...`). +sevenzip="$(which 7z)" + +# echo "archive : ${archive}" +# echo "epoch : ${epoch}" +# echo "options : ${options[@]}" +# echo "patterns: ${patterns[@]}" + +tmpdir="$(mktemp -d -t tmp7z.XXXXXXXXXX)" +trap 'rm -rf "${tmpdir}"' EXIT + +manifest="${tmpdir}/manifest" + +"${sevenzip}" -l -ba h "${patterns[@]}" | + awk '{ if ($3) print $3, $2, $1; else print $1 }' | + sort >"${manifest}" + +# cat "${manifest}" | less + +if [[ -r "${archive}" ]]; then + if diff --brief --label 'in archive' \ + <( + "${sevenzip}" -slt l "${archive}" | + awk ' + /^(\w+) = / { entry[$1] = $3; } + /^CRC =/ { if ($3) print entry["Path"], entry["Size"], $3; else print entry["Path"] } + ' | sort + ) --label 'to add' "${manifest}"; then + exit + fi + # There's no 7z option to overwrite the archive + # if it already exists (instead of updating it)… + rm -f "${archive}" +fi + +# Extract list of paths from manifest. +rev <"${manifest}" | cut -f3- -d' ' | rev >"${tmpdir}/paths" +# Quick sanity check: no path outside the current directory. +if grep '^(/|\.\./)' <"${tmpdir}/paths"; then + echo "^ some paths are outside the current directory!" + exit 1 +fi + +# Make a copy of everything so we can later +# patch timestamp to ensure reproducibility. +mkdir "${tmpdir}/contents" +# We want to copy "empty" (with ignored files) directories. +tar --dereference --no-recursion --create \ + --verbatim-files-from --files-from="${tmpdir}/paths" | + tar --extract --directory="${tmpdir}/contents" + +cd "${tmpdir}/contents" + +# Fix timestamps. +find . -depth -print0 | xargs -0 touch --date="${epoch}" + +# And create the final archive. +"${sevenzip}" -l -mqs "${options[@]}" a "${archive}" . + +# vim: sw=4