2 # Copyright 2016 Christoph Reiter
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
10 DIR
="$( cd "$
( dirname "$0" )" && pwd )"
21 if [ "${ARCH}" = "x86_64" ]; then
28 GPO_VERSION_DESC
="UNKNOWN"
30 function set_build_root
{
32 REPO_CLONE
="${BUILD_ROOT}"/gpodder
33 MINGW_ROOT
="${BUILD_ROOT}/${MINGW}"
36 if [ "$APPVEYOR" == "True" ]; then
37 set_build_root
"$HOME/_gpodder_build_root"
38 elif [ -d "/home/IEUser" ]; then
39 set_build_root
"/home/IEUser/_gpodder_build_root"
41 set_build_root
"${DIR}/_build_root"
44 function build_pacman
{
45 pacman
--root "${BUILD_ROOT}" "$@"
49 "${MINGW_ROOT}"/bin
/python3.exe
-m pip
"$@"
52 function build_python
{
53 "${MINGW_ROOT}"/bin
/python3.exe
"$@"
56 function build_compileall
{
57 MSYSTEM
= build_python
-m compileall
-b "$@"
60 function install_pre_deps
{
61 # install python3 here to ensure same version
62 pacman
-S --needed --noconfirm p7zip git dos2unix rsync \
63 mingw-w64-
"${ARCH}"-nsis wget libidn2 libopenssl intltool mingw-w64-
"${ARCH}"-toolchain \
64 mingw-w64-
"${ARCH}"-python3
67 function create_root
{
68 mkdir
-p "${BUILD_ROOT}"
70 mkdir
-p "${BUILD_ROOT}"/var
/lib
/pacman
71 mkdir
-p "${BUILD_ROOT}"/var
/log
72 mkdir
-p "${BUILD_ROOT}"/tmp
75 build_pacman
--noconfirm -S base
78 function extract_installer
{
79 [ -z "$1" ] && (echo "Missing arg"; exit 1)
81 mkdir
-p "$BUILD_ROOT"
82 7z x
-o"$BUILD_ROOT"/"$MINGW" "$1"
83 rm -rf "$MINGW_ROOT"/'$PLUGINSDIR' "$MINGW_ROOT"/*.txt
"$MINGW_ROOT"/*.nsi
89 git+https://github.com/enthought/pywin32-ctypes.git@f27d6a0
95 youtube_dl==2019.9.12.1
98 function install_deps
{
100 # We don't use the fontconfig backend, and this skips the lengthy
101 # cache update step during package installation
102 export MSYS2_FC_CACHE_SKIP
=1
104 build_pacman
--noconfirm -S git mingw-w64-
"${ARCH}"-gdk-pixbuf2 \
105 mingw-w64-
"${ARCH}"-librsvg \
106 mingw-w64-
"${ARCH}"-gtk3 mingw-w64-
"${ARCH}"-python3 \
107 mingw-w64-
"${ARCH}"-python3-gobject \
108 mingw-w64-
"${ARCH}"-python3-cairo \
109 mingw-w64-
"${ARCH}"-python3-pip \
110 mingw-w64-
"${ARCH}"-make
112 build_pacman
-S --noconfirm mingw-w64-
"${ARCH}"-python3-setuptools
114 build_pip
install --no-deps --no-binary ":all:" --upgrade \
115 --force-reinstall $
(echo "$PIP_REQUIREMENTS" |
tr ["\\n"] [" "])
117 # replace ca-certificates with certifi's
118 build_pacman
--noconfirm -Rdds mingw-w64-
"${ARCH}"-ca-certificates || true
119 mkdir
-p ${MINGW_ROOT}/ssl
120 site_packages
=$
(build_python
-c 'import sys;print(next(c for c in sys.path if "site-packages" in c))')
121 cp -v ${site_packages}/certifi
/cacert.pem
${MINGW_ROOT}/ssl
/cert.pem
122 build_pip uninstall
-y certifi
124 build_pacman
--noconfirm -Rdds mingw-w64-
"${ARCH}"-python3-pip || true
127 function install_gpodder
{
128 [ -z "$1" ] && (echo "Missing arg"; exit 1)
130 rm -Rf "${REPO_CLONE}"
131 if [ "$2" == "rsync" ]; then
132 # development mode when not everything is committed
133 rsync
-rvt "${DIR}"/..
/..
"${REPO_CLONE}"
135 git clone
"${DIR}"/..
/..
"${REPO_CLONE}"
138 (cd "${REPO_CLONE}" && git checkout
"$1") ||
exit 1
140 (cd "${REPO_CLONE}" && PYTHON
="${MINGW_ROOT}"/bin
/python3.exe mingw32-make install-win
)
142 GPO_VERSION
=$
(MSYSTEM
= build_python
-c \
143 "import gpodder; import sys; sys.stdout.write(gpodder.__version__)")
144 GPO_VERSION_DESC
="$GPO_VERSION"
145 if [ "$1" = "master" ]
147 local GIT_REV
=$
(git rev-list
--count HEAD
)
148 local GIT_HASH
=$
(git rev-parse
--short HEAD
)
149 GPO_VERSION_DESC
="$GPO_VERSION-rev$GIT_REV-$GIT_HASH"
153 echo "python3 is $(which python3) version is $(python3 --version)"
154 python3
"${MISC}"/create-launcher.py \
155 "${GPO_VERSION}" "${MINGW_ROOT}"/bin
158 site_packages
=$
(build_python
-c 'import sys;print(next(c for c in sys.path if "site-packages" in c))')
159 site_packages_unix
=$
(echo "/$site_packages" |
sed -e 's/\\/\//g' -e 's/://')
160 rsync
-arv --delete "${REPO_CLONE}"/tools
/fake-dbus-module
/dbus
"${site_packages_unix}/"
162 # install gtk3 settings for a proper font
163 mkdir
-p "${MINGW_ROOT}"/etc
/gtk-3.0
164 cp "${MISC}"/gtk3.0_settings.ini
"${MINGW_ROOT}"/etc
/gtk-3.0
/settings.ini
166 # install bin/gpodder bin/gpo to a separate package, to be run before gpodder/__init__.py
167 gpodder_launch_dir
="${site_packages_unix}"/gpodder_launch
168 mkdir
-p "${gpodder_launch_dir}"
169 touch "${gpodder_launch_dir}"/__init__.py
170 cp ${REPO_CLONE}/bin
/gpo
"${gpodder_launch_dir}"/gpo.py
171 cp ${REPO_CLONE}/bin
/gpodder
"${gpodder_launch_dir}"/gpodder.py
173 build_compileall
-d "" -f -q "$(cygpath -w "${MINGW_ROOT}")"
175 # copy gpodder.ico for notification-win32
176 cp ${REPO_CLONE}/tools
/win_installer
/misc
/gpodder.ico
"${MINGW_ROOT}"/bin
179 function cleanup_before
{
180 # these all have svg variants
181 find "${MINGW_ROOT}"/share
/icons
-name "*.symbolic.png" -exec rm -f {} \
;
183 # remove some larger ones
184 rm -Rf "${MINGW_ROOT}/share/icons/Adwaita/512x512"
185 rm -Rf "${MINGW_ROOT}/share/icons/Adwaita/256x256"
186 rm -Rf "${MINGW_ROOT}/share/icons/Adwaita/96x96"
187 rm -Rf "${MINGW_ROOT}/share/icons/Adwaita/48x48"
188 "${MINGW_ROOT}"/bin
/gtk-update-icon-cache-3.0.exe \
189 "${MINGW_ROOT}"/share
/icons
/Adwaita
191 # remove some gtk demo icons
192 find "${MINGW_ROOT}"/share
/icons
/hicolor
-name "gtk3-*" -exec rm -f {} \
;
193 "${MINGW_ROOT}"/bin
/gtk-update-icon-cache-3.0.exe \
194 "${MINGW_ROOT}"/share
/icons
/hicolor
196 # python related, before installing gpodder
197 rm -Rf "${MINGW_ROOT}"/lib
/python3.
*/test
198 rm -f "${MINGW_ROOT}"/lib
/python3.
*/lib-dynload
/_tkinter
*
199 find "${MINGW_ROOT}"/lib
/python3.
* -type d
-name "test*" \
200 -prune -exec rm -rf {} \
;
201 find "${MINGW_ROOT}"/lib
/python3.
* -type d
-name "*_test*" \
202 -prune -exec rm -rf {} \
;
204 find "${MINGW_ROOT}"/bin
-name "*.pyo" -exec rm -f {} \
;
205 find "${MINGW_ROOT}"/bin
-name "*.pyc" -exec rm -f {} \
;
206 find "${MINGW_ROOT}" -type d
-name "__pycache__" -prune -exec rm -rf {} \
;
208 build_compileall
-d "" -f -q "$(cygpath -w "${MINGW_ROOT}")"
209 find "${MINGW_ROOT}" -name "*.py" -exec rm -f {} \
;
212 function cleanup_after
{
213 # delete translations we don't support
214 for d
in "${MINGW_ROOT}"/share
/locale
/*/LC_MESSAGES
; do
215 if [ ! -f "${d}"/gpodder.mo
]; then
220 find "${MINGW_ROOT}" -regextype "posix-extended" -name "*.exe" -a ! \
221 -iregex ".*/(gpodder|gpo|python)[^/]*\\.exe" \
224 rm -Rf "${MINGW_ROOT}"/libexec
225 rm -Rf "${MINGW_ROOT}"/share
/gtk-doc
226 rm -Rf "${MINGW_ROOT}"/include
227 rm -Rf "${MINGW_ROOT}"/var
228 rm -Rf "${MINGW_ROOT}"/etc
/fonts
229 rm -Rf "${MINGW_ROOT}"/etc
/pki
230 rm -Rf "${MINGW_ROOT}"/share
/zsh
231 rm -Rf "${MINGW_ROOT}"/share
/pixmaps
232 rm -Rf "${MINGW_ROOT}"/share
/gnome-shell
233 rm -Rf "${MINGW_ROOT}"/share
/dbus-1
234 rm -Rf "${MINGW_ROOT}"/share
/gir-1.0
235 rm -Rf "${MINGW_ROOT}"/share
/doc
236 rm -Rf "${MINGW_ROOT}"/share
/man
237 rm -Rf "${MINGW_ROOT}"/share
/info
238 rm -Rf "${MINGW_ROOT}"/share
/mime
239 rm -Rf "${MINGW_ROOT}"/share
/gettext
240 rm -Rf "${MINGW_ROOT}"/share
/libtool
241 rm -Rf "${MINGW_ROOT}"/share
/licenses
242 rm -Rf "${MINGW_ROOT}"/share
/appdata
243 rm -Rf "${MINGW_ROOT}"/share
/aclocal
244 rm -Rf "${MINGW_ROOT}"/share
/ffmpeg
245 rm -Rf "${MINGW_ROOT}"/share
/vala
246 rm -Rf "${MINGW_ROOT}"/share
/readline
247 rm -Rf "${MINGW_ROOT}"/share
/xml
248 rm -Rf "${MINGW_ROOT}"/share
/bash-completion
249 rm -Rf "${MINGW_ROOT}"/share
/common-lisp
250 rm -Rf "${MINGW_ROOT}"/share
/emacs
251 rm -Rf "${MINGW_ROOT}"/share
/gdb
252 rm -Rf "${MINGW_ROOT}"/share
/libcaca
253 rm -Rf "${MINGW_ROOT}"/share
/gettext
254 rm -Rf "${MINGW_ROOT}"/share
/gst-plugins-base
255 rm -Rf "${MINGW_ROOT}"/share
/gst-plugins-bad
256 rm -Rf "${MINGW_ROOT}"/share
/libgpg-error
257 rm -Rf "${MINGW_ROOT}"/share
/p11-kit
258 rm -Rf "${MINGW_ROOT}"/share
/pki
259 rm -Rf "${MINGW_ROOT}"/share
/thumbnailers
260 rm -Rf "${MINGW_ROOT}"/share
/gtk-3.0
261 rm -Rf "${MINGW_ROOT}"/share
/nghttp2
262 rm -Rf "${MINGW_ROOT}"/share
/themes
263 rm -Rf "${MINGW_ROOT}"/share
/fontconfig
264 rm -Rf "${MINGW_ROOT}"/share
/gettext-
*
265 rm -Rf "${MINGW_ROOT}"/share
/gstreamer-1.0
266 rm -Rf "${MINGW_ROOT}"/share
/installed-tests
268 find "${MINGW_ROOT}"/share
/glib-2.0
-type f
! \
269 -name "*.compiled" -exec rm -f {} \
;
271 # unused configuration example
272 rm -Rf "${MINGW_ROOT}"/ssl
/openssl.cnf
274 rm -Rf "${MINGW_ROOT}"/lib
/cmake
275 rm -Rf "${MINGW_ROOT}"/lib
/gettext
276 rm -Rf "${MINGW_ROOT}"/lib
/gtk-3.0
277 rm -Rf "${MINGW_ROOT}"/lib
/mpg123
278 rm -Rf "${MINGW_ROOT}"/lib
/p11-kit
279 rm -Rf "${MINGW_ROOT}"/lib
/pkcs11
280 rm -Rf "${MINGW_ROOT}"/lib
/ruby
281 rm -Rf "${MINGW_ROOT}"/lib
/engines
283 # remove all tcl/tk libs
284 rm -Rf "${MINGW_ROOT}"/lib
/dde
*
285 rm -Rf "${MINGW_ROOT}"/lib
/itcl
*
286 rm -Rf "${MINGW_ROOT}"/lib
/reg
*
287 rm -Rf "${MINGW_ROOT}"/lib
/tcl
*
288 rm -Rf "${MINGW_ROOT}"/lib
/tdbc
*
289 rm -Rf "${MINGW_ROOT}"/lib
/tk
*
291 # remove terminfo database (not used, even by gpo)
292 rm -Rf "${MINGW_ROOT}"/lib
/terminfo
293 rm -Rf "${MINGW_ROOT}"/share
/terminfo
295 rm -f "${MINGW_ROOT}"/bin
/libharfbuzz-icu-0.dll
296 rm -Rf "${MINGW_ROOT}"/lib
/python2.
*
298 find "${MINGW_ROOT}" -name "*.a" -exec rm -f {} \
;
299 find "${MINGW_ROOT}" -name "*.whl" -exec rm -f {} \
;
300 find "${MINGW_ROOT}" -name "*.h" -exec rm -f {} \
;
301 find "${MINGW_ROOT}" -name "*.la" -exec rm -f {} \
;
302 find "${MINGW_ROOT}" -name "*.sh" -exec rm -f {} \
;
303 find "${MINGW_ROOT}" -name "*.jar" -exec rm -f {} \
;
304 find "${MINGW_ROOT}" -name "*.def" -exec rm -f {} \
;
305 find "${MINGW_ROOT}" -name "*.cmd" -exec rm -f {} \
;
306 find "${MINGW_ROOT}" -name "*.cmake" -exec rm -f {} \
;
307 find "${MINGW_ROOT}" -name "*.pc" -exec rm -f {} \
;
308 find "${MINGW_ROOT}" -name "*.desktop" -exec rm -f {} \
;
309 find "${MINGW_ROOT}" -name "*.manifest" -exec rm -f {} \
;
310 find "${MINGW_ROOT}" -name "*.pyo" -exec rm -f {} \
;
312 find "${MINGW_ROOT}"/bin
-name "*-config" -exec rm -f {} \
;
313 find "${MINGW_ROOT}"/bin
-name "easy_install*" -exec rm -f {} \
;
314 find "${MINGW_ROOT}" -regex ".*/bin/[^.]+" -exec rm -f {} \
;
315 find "${MINGW_ROOT}" -regex ".*/bin/[^.]+\\.[0-9]+" -exec rm -f {} \
;
317 find "${MINGW_ROOT}" -name "gtk30-properties.mo" -exec rm -rf {} \
;
318 find "${MINGW_ROOT}" -name "gettext-tools.mo" -exec rm -rf {} \
;
319 find "${MINGW_ROOT}" -name "libexif-12.mo" -exec rm -rf {} \
;
320 find "${MINGW_ROOT}" -name "xz.mo" -exec rm -rf {} \
;
321 find "${MINGW_ROOT}" -name "libgpg-error.mo" -exec rm -rf {} \
;
323 find "${MINGW_ROOT}" -name "old_root.pem" -exec rm -rf {} \
;
324 find "${MINGW_ROOT}" -name "weak.pem" -exec rm -rf {} \
;
326 find "${MINGW_ROOT}"/bin
-name "*.pyo" -exec rm -f {} \
;
327 find "${MINGW_ROOT}"/bin
-name "*.pyc" -exec rm -f {} \
;
328 find "${MINGW_ROOT}" -type d
-name "__pycache__" -prune -exec rm -rf {} \
;
330 build_python
"${MISC}/depcheck.py" --delete
332 find "${MINGW_ROOT}" -type d
-empty -delete
335 function dump_packages
{
336 DUMPFILE
="${MINGW_ROOT}/contents.txt"
341 declare -A PKGVERSIONS
342 while read pkg version
; do
343 PKGVERSIONS
[$pkg]="$version"
344 done < <(build_pacman
-Q)
345 # REGFILES is a hash of file -> package name to check for unregistered files in the end
348 echo "msys2 packages:"
349 # first handle all files registered with pacman
350 while read _pkg
file; do
352 if [[ "$file" == "${MINGW_ROOT}"* ]]; then
353 if [ -f "$file" ]; then
355 elif [[ "$file" == *".py" ]] && [ -f "${file}c" ]; then
359 if [ -n "$realfile" ]; then
360 if [ "$_pkg" != "$pkg" ]; then
362 echo "$pkg ${PKGVERSIONS[$pkg]}"
364 echo " ${realfile#${MINGW_ROOT}}"
365 REGFILES
["$realfile"]="$pkg"
367 done < <(build_pacman
-Ql)
368 echo "==================="
369 # then handle all python packages (with an installed-files.txt)
370 echo "Python packages:"
371 for p
in ${PIP_REQUIREMENTS}; do
375 # pywin32-ctypes doesn't provide an egg-info/installed-files.txt
376 if [ "$pkg" == "pywin32-ctypes" ]; then
378 if [ ! ${REGFILES[$file]+_} ]; then
380 REGFILES
["$file"]="$pkg"
382 done < <(find "${MINGW_ROOT}" -type f
-a \
( -path '*/site-packages/pywin32_ctypes*' -o -path '*/site-packages/win32ctypes/*' \
))
383 elif [ "$pkg" == "certifi" ]; then
385 if [ ! ${REGFILES[$file]+_} ]; then
387 REGFILES
["$file"]="$pkg"
389 done < <(find "${MINGW_ROOT}/ssl" -type f
-path '*/ssl/cert.pem')
391 # other python deps provide an installed-files.txt, so simply go through them
392 egg
="${MINGW_ROOT}/lib/python3.6/site-packages/${pkg}-${version}-py3.6.egg-info"
393 if [ -f "$egg/installed-files.txt" ]; then
397 if [ -f "$tryfile" ]; then
398 realfile
=$
(realpath
"$tryfile")
399 # we precompiled all python modules
400 elif [[ "$tryfile" == *.py
]] && [ -f "${tryfile}c" ]; then
401 realfile
=$
(realpath
"${tryfile}c")
403 # this file (or compiled module) belongs to this python package
404 if [ -n "$realfile" ]; then
406 REGFILES
["$realfile"]="$pkg"
408 # installed-files.txt is not listed in itself, so add it manually
409 done < <(echo installed-files.txt
; tr -d '\r' < "$egg/installed-files.txt")
413 echo "==================="
415 # every file with gpodder in the path belongs to us!
416 while read relfile
; do
417 file="${MINGW_ROOT}/${relfile#./}"
418 if [ ! ${REGFILES[$file]+_} ]; then
420 REGFILES
["$file"]="gpodder"
422 done < <(cd "${MINGW_ROOT}" && find .
-type f
-a \
( -path '*gpodder*' -o -path '*/site-packages/dbus/*' -o -name gpo.exe \
))
423 echo "==================="
424 echo "Unregistered files:"
425 # a few generated files
427 if [ ! ${REGFILES[$file]+_} ]; then
430 done < <(find "${MINGW_ROOT}" -type f
)
432 unix2dos
"${DUMPFILE}"
433 cp "${DUMPFILE}" "$DIR/gpodder-$GPO_VERSION_DESC-contents.txt"
436 function build_installer
{
437 BUILDPY
=$
(echo "${MINGW_ROOT}"/lib
/python3.
*/site-packages
/gpodder
)/build_info.py
438 cp "${REPO_CLONE}"/src
/gpodder
/build_info.py
"$BUILDPY"
439 echo 'BUILD_TYPE = u"windows"' >> "$BUILDPY"
440 echo "BUILD_VERSION = $BUILD_VERSION" >> "$BUILDPY"
441 (cd "$REPO_CLONE" && echo "BUILD_INFO = u\"$(git rev-parse --short HEAD)\"" >> "$BUILDPY")
442 (cd $
(dirname "$BUILDPY") && build_compileall
-d "" -q -f -l .
)
445 cp "${MISC}"/gpodder.ico
"${BUILD_ROOT}"
446 (cd "$BUILD_ROOT" && makensis
-V3 -NOCD -DVERSION="$GPO_VERSION_DESC" "${MISC}"/win_installer.nsi
)
448 mv "$BUILD_ROOT/gpodder-LATEST.exe" "$DIR/gpodder-$GPO_VERSION_DESC-installer.exe"
451 function build_portable_installer
{
452 BUILDPY
=$
(echo "${MINGW_ROOT}"/lib
/python3.
*/site-packages
/gpodder
)/build_info.py
453 cp "${REPO_CLONE}"/src
/gpodder
/build_info.py
"$BUILDPY"
454 echo 'BUILD_TYPE = u"windows-portable"' >> "$BUILDPY"
455 echo "BUILD_VERSION = $BUILD_VERSION" >> "$BUILDPY"
456 (cd "$REPO_CLONE" && echo "BUILD_INFO = u\"$(git rev-parse --short HEAD)\"" >> "$BUILDPY")
457 (cd $
(dirname "$BUILDPY") && build_compileall
-d "" -q -f -l .
)
460 local PORTABLE
="$DIR/gpodder-${GPO_VERSION_DESC}-portable"
464 cp "$MISC"/gpodder.lnk
"$PORTABLE"
465 cp "$MISC"/gpo.lnk
"$PORTABLE"
466 cp "$MISC"/README-PORTABLE.txt
"$PORTABLE"/README.txt
467 unix2dos
"$PORTABLE"/README.txt
468 mkdir
"$PORTABLE"/config
469 cp -RT "${MINGW_ROOT}" "$PORTABLE"/data
471 rm -Rf 7zout
7z1604.exe
472 7z a payload
.7z
"$PORTABLE"
473 wget
-P "$DIR" -c http
://www
.7-zip.org
/a
/7z1604.exe
474 7z x
-o7zout 7z1604.exe
475 cat 7zout
/7z.sfx payload
.7z
> "$PORTABLE".exe
476 rm -Rf 7zout
7z1604.exe payload
.7z
"$PORTABLE"