linux: add support for AppImage packages
AppImage is a more flexible packaging solution for Linux than what PyInstaller currently offers. Some of the benefits are: - Ability to ship the app with predefined environment variables (solving issues like #321) - Improved integration with the desktop environment (if you're using go-appimage[1] or libappimage[2]) - Much lighter in size (~27 MB difference) To actually make the AppImage, I'm using appimage-builder[3], which makes the process a bit easier. For more details about the AppImage technology, check out their website[4]. [1] https://github.com/probonopd/go-appimage [2] https://github.com/AppImageCommunity/libappimage [3] https://appimage-builder.readthedocs.io/en/latest/index.html [4] https://appimage.org/
This commit is contained in:
1 parent
1e31957388
commit
a31fa375c9
4 files changed
+166
-9
No files matched your search
@@ -16,3 +16,9 @@ log.txt
|
|||||||
/lock.file
|
/lock.file
|
||||||
settings.json
|
settings.json
|
||||||
/lang/English.json
|
/lang/English.json
|
||||||
|
# AppImage
|
||||||
|
/AppDir
|
||||||
|
/appimage-builder
|
||||||
|
/appimage-build
|
||||||
|
/*.AppImage
|
||||||
|
/*.AppImage.zsync
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
# Useful links:
|
||||||
|
# https://appimage-builder.readthedocs.io/en/latest/reference/recipe.html
|
||||||
|
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
script:
|
||||||
|
# Clean up any previous builds.
|
||||||
|
- rm -rf "$BUILD_DIR" "$TARGET_APPDIR" || true
|
||||||
|
- mkdir -p "$BUILD_DIR" "$TARGET_APPDIR"
|
||||||
|
- cd "$BUILD_DIR"
|
||||||
|
|
||||||
|
# Build a recent version of libXft first. This fixes an issue where the app won't start with libXft 2.3.3 if an emoji font is installed on the system.
|
||||||
|
- curl -L https://xorg.freedesktop.org/releases/individual/lib/libXft-2.3.8.tar.xz -o libXft.tar.xz
|
||||||
|
- tar xvf libXft.tar.xz
|
||||||
|
- cd libXft-2.3.8
|
||||||
|
- ./configure --prefix="$TARGET_APPDIR/usr" --disable-static
|
||||||
|
- make -j$(nproc)
|
||||||
|
- make install-strip
|
||||||
|
|
||||||
|
# Package the app.
|
||||||
|
- mkdir -p "$TARGET_APPDIR"/usr/{src,share/icons/hicolor/128x128/apps}
|
||||||
|
- cp -r "$SOURCE_DIR/../lang" "$SOURCE_DIR/../pickaxe.ico" "$SOURCE_DIR"/../*.py "$TARGET_APPDIR/usr/src"
|
||||||
|
- cp "$SOURCE_DIR/pickaxe.png" "$TARGET_APPDIR/usr/share/icons/hicolor/128x128/apps/io.github.devilxd.twitchdropsminer.png"
|
||||||
|
|
||||||
|
# Remove certifi from the line below if using Python 3.10+.
|
||||||
|
- python3.8 -m pip install --ignore-installed --prefix=/usr --root="$TARGET_APPDIR" -r "$SOURCE_DIR/../requirements.txt" certifi
|
||||||
|
|
||||||
|
AppDir:
|
||||||
|
app_info:
|
||||||
|
id: io.github.devilxd.twitchdropsminer
|
||||||
|
name: Twitch Drops Miner
|
||||||
|
icon: io.github.devilxd.twitchdropsminer
|
||||||
|
version: '{{APP_VERSION}}'
|
||||||
|
exec: usr/bin/python3.8
|
||||||
|
exec_args: '${APPDIR}/usr/src/main.py $@'
|
||||||
|
|
||||||
|
apt:
|
||||||
|
arch: amd64
|
||||||
|
sources:
|
||||||
|
- sourceline: deb http://archive.ubuntu.com/ubuntu/ focal main universe
|
||||||
|
- sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates main universe
|
||||||
|
- sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-backports main universe
|
||||||
|
- sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-security main universe
|
||||||
|
key_url: http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3b4fe6acc0b21f32
|
||||||
|
|
||||||
|
include:
|
||||||
|
- gir1.2-appindicator3-0.1
|
||||||
|
- python3-tk
|
||||||
|
|
||||||
|
exclude:
|
||||||
|
- adwaita-icon-theme
|
||||||
|
- dconf-service
|
||||||
|
- glib-networking-services
|
||||||
|
- gsettings-desktop-schemas
|
||||||
|
- hicolor-icon-theme
|
||||||
|
- humanity-icon-theme
|
||||||
|
- libavahi-client3
|
||||||
|
- libavahi-common3
|
||||||
|
- libbrotli1
|
||||||
|
- libcolord2
|
||||||
|
- libcups2
|
||||||
|
- libdb5.3
|
||||||
|
- libdconf1
|
||||||
|
- libgmp10
|
||||||
|
- libgnutls30
|
||||||
|
- libgssapi-krb5-2
|
||||||
|
- libhogweed5
|
||||||
|
- libicu66
|
||||||
|
- libjson-glib-1.0-0
|
||||||
|
- libk5crypto3
|
||||||
|
- libkrb5-3
|
||||||
|
- libkrb5support0
|
||||||
|
- liblcms2-2
|
||||||
|
- libncursesw6
|
||||||
|
- libnettle7
|
||||||
|
- libp11-kit0
|
||||||
|
- libpangoxft-1.0-0
|
||||||
|
- libpsl5
|
||||||
|
- librest-0.7-0
|
||||||
|
- libsoup2.4-1
|
||||||
|
- libsoup-gnome2.4-1
|
||||||
|
- libsqlite3-0
|
||||||
|
- libtasn1-6
|
||||||
|
- libtiff5
|
||||||
|
- libtinfo6
|
||||||
|
- libunistring2
|
||||||
|
- libwebp6
|
||||||
|
- libxft2 # We'll ship our own, updated version of this library.
|
||||||
|
- libxml2
|
||||||
|
- mime-support
|
||||||
|
- readline-common
|
||||||
|
- tzdata
|
||||||
|
- xkb-data
|
||||||
|
|
||||||
|
files:
|
||||||
|
exclude:
|
||||||
|
- etc
|
||||||
|
- usr/bin/normalizer
|
||||||
|
- usr/bin/pdb3*
|
||||||
|
- usr/bin/py3*
|
||||||
|
- usr/bin/pydoc*
|
||||||
|
- usr/bin/pygettext3*
|
||||||
|
- usr/include
|
||||||
|
# The next 2 files come from our own build of libXft, and they can be removed.
|
||||||
|
- usr/lib/libXft.la
|
||||||
|
- usr/lib/pkgconfig
|
||||||
|
- usr/lib/python3.9
|
||||||
|
- usr/lib/valgrind
|
||||||
|
- usr/lib/*-linux-gnu/engines-1.1
|
||||||
|
- usr/lib/*-linux-gnu/glib-2.0
|
||||||
|
- usr/lib/*-linux-gnu/gtk-3.0
|
||||||
|
- usr/lib/*-linux-gnu/libgtk-3.0
|
||||||
|
- usr/share/applications
|
||||||
|
- usr/share/binfmts
|
||||||
|
- usr/share/bug
|
||||||
|
- usr/share/doc
|
||||||
|
- usr/share/doc-base
|
||||||
|
- usr/share/glib-2.0
|
||||||
|
- usr/share/lintian
|
||||||
|
- usr/share/man
|
||||||
|
- usr/share/pixmaps
|
||||||
|
- usr/share/python3
|
||||||
|
- usr/share/themes
|
||||||
|
|
||||||
|
runtime:
|
||||||
|
env:
|
||||||
|
PATH: '${APPDIR}/usr/bin:${PATH}'
|
||||||
|
PYTHONHOME: '${APPDIR}/usr'
|
||||||
|
PYTHONPATH: '${APPDIR}/usr/lib/python3.8/tkinter:${APPDIR}/usr/lib/python3.8/site-packages'
|
||||||
|
APPDIR_LIBRARY_PATH: '${APPDIR}/usr/lib:${APPDIR}/usr/lib/x86_64-linux-gnu:${APPDIR}/lib/x86_64-linux-gnu'
|
||||||
|
TCL_LIBRARY: '${APPDIR}/usr/share/tcltk/tcl8.6'
|
||||||
|
TK_LIBRARY: '${APPDIR}/usr/lib/tcltk/x86_64-linux-gnu/tk8.6'
|
||||||
|
TKPATH: '${APPDIR}/usr/lib/tcltk/x86_64-linux-gnu/tk8.6'
|
||||||
|
# Remove the line below if using Python 3.10+.
|
||||||
|
SSL_CERT_FILE: '${APPDIR}/usr/lib/python3.8/site-packages/certifi/cacert.pem'
|
||||||
|
# The app seems to have problems running on Wayland at the moment.
|
||||||
|
# See: https://github.com/DevilXD/TwitchDropsMiner/issues/321
|
||||||
|
GDK_BACKEND: x11
|
||||||
|
|
||||||
|
AppImage:
|
||||||
|
arch: x86_64
|
||||||
|
file_name: Twitch.Drops.Miner-x86_64.AppImage
|
||||||
|
sign-key: None
|
||||||
|
update-information: guess
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
+16
-9
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
@@ -18,8 +19,9 @@ if TYPE_CHECKING:
|
|||||||
from typing_extensions import TypeAlias
|
from typing_extensions import TypeAlias
|
||||||
|
|
||||||
|
|
||||||
# True if we're running from a built EXE, False inside a dev build
|
# True if we're running from a built EXE (or a Linux AppImage), False inside a dev build
|
||||||
IS_PACKAGED = hasattr(sys, "_MEIPASS")
|
IS_APPIMAGE = "APPIMAGE" in os.environ and os.path.exists(os.environ["APPIMAGE"])
|
||||||
|
IS_PACKAGED = hasattr(sys, "_MEIPASS") or IS_APPIMAGE
|
||||||
# logging special levels
|
# logging special levels
|
||||||
CALL = logging.INFO - 1
|
CALL = logging.INFO - 1
|
||||||
logging.addLevelName(CALL, "CALL")
|
logging.addLevelName(CALL, "CALL")
|
||||||
@@ -39,7 +41,9 @@ def _resource_path(relative_path: Path | str) -> Path:
|
|||||||
|
|
||||||
Works for dev and for PyInstaller.
|
Works for dev and for PyInstaller.
|
||||||
"""
|
"""
|
||||||
if IS_PACKAGED:
|
if IS_APPIMAGE:
|
||||||
|
base_path = Path(sys.argv[0]).absolute().parent
|
||||||
|
elif IS_PACKAGED:
|
||||||
# PyInstaller's folder where the one-file app is unpacked
|
# PyInstaller's folder where the one-file app is unpacked
|
||||||
meipass: str = getattr(sys, "_MEIPASS")
|
meipass: str = getattr(sys, "_MEIPASS")
|
||||||
base_path = Path(meipass)
|
base_path = Path(meipass)
|
||||||
@@ -73,12 +77,15 @@ def _merge_vars(base_vars: JsonType, vars: JsonType) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# Base Paths
|
# Base Paths
|
||||||
# NOTE: pyinstaller will set this to its own executable when building,
|
if IS_APPIMAGE:
|
||||||
# detect this to use __file__ and main.py redirection instead
|
SELF_PATH = Path(os.environ["APPIMAGE"]).absolute()
|
||||||
SELF_PATH = Path(sys.argv[0]).absolute()
|
else:
|
||||||
if SELF_PATH.stem == "pyinstaller":
|
# NOTE: pyinstaller will set sys.argv[0] to its own executable when building,
|
||||||
SELF_PATH = Path(__file__).with_name("main.py").absolute()
|
# detect this to use __file__ and main.py redirection instead
|
||||||
WORKING_DIR = SELF_PATH.absolute().parent
|
SELF_PATH = Path(sys.argv[0]).absolute()
|
||||||
|
if SELF_PATH.stem == "pyinstaller":
|
||||||
|
SELF_PATH = Path(__file__).with_name("main.py").absolute()
|
||||||
|
WORKING_DIR = SELF_PATH.parent
|
||||||
# Development paths
|
# Development paths
|
||||||
VENV_PATH = Path(WORKING_DIR, "env")
|
VENV_PATH = Path(WORKING_DIR, "env")
|
||||||
SITE_PACKAGES_PATH = Path(VENV_PATH, SYS_SITE_PACKAGES)
|
SITE_PACKAGES_PATH = Path(VENV_PATH, SYS_SITE_PACKAGES)
|
||||||
|
|||||||
Reference in new issue
Block a user