From 4e16870f427f4f953984fd9f797d450ec28250ed Mon Sep 17 00:00:00 2001 From: Fatih Bakal Date: Fri, 26 Jun 2026 16:51:21 +0300 Subject: [PATCH 01/13] push --- .gitignore | 11 + src/protontricks/data/appimage/PKGBUILD-git | 57 ++ .../data/appimage/execve-sharun-hack.c | 715 ++++++++++++++++++ .../data/appimage/get-dependencies.sh | 18 + .../data/appimage/make-appimage.sh | 39 + .../apps/com.github.Matoking.protontricks.svg | 209 +++++ 6 files changed, 1049 insertions(+) create mode 100644 src/protontricks/data/appimage/PKGBUILD-git create mode 100644 src/protontricks/data/appimage/execve-sharun-hack.c create mode 100755 src/protontricks/data/appimage/get-dependencies.sh create mode 100755 src/protontricks/data/appimage/make-appimage.sh create mode 100644 src/protontricks/data/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg diff --git a/.gitignore b/.gitignore index 0c1eaed..f23ec27 100644 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,14 @@ pip-selfcheck.json # End of https://www.gitignore.io/api/python,virtualenv + +# AppImage +AppDir/ + +*.tar.zst + +quick-sharun* +get-debloated-pkgs* +src/protontricks/data/appimage/protontricks/pkg +src/protontricks/data/appimage/protontricks/ +src/protontricks/data/appimage/protontricks/src/ diff --git a/src/protontricks/data/appimage/PKGBUILD-git b/src/protontricks/data/appimage/PKGBUILD-git new file mode 100644 index 0000000..6ce6594 --- /dev/null +++ b/src/protontricks/data/appimage/PKGBUILD-git @@ -0,0 +1,57 @@ +# Kudos to maintainers from official arch repos +# Carl Smedstad +# Jason Stryker +# Konstantin Liberty + +pkgname=protontricks +pkgver=1.14.1 +pkgrel=1 +pkgdesc="Run Winetricks commands for Steam Play/Proton games among other common Wine features" +arch=('any') +url="https://github.com/twig6943/protontricks" +license=('GPL-3.0-only') +depends=( + 'python' + 'python-pillow' + 'python-vdf' + 'winetricks' + 'zenity' + 'yad' + 'openjpeg2' + 'libimagequant' +) +makedepends=( + 'git' + 'python-build' + 'python-installer' + 'python-setuptools' + 'python-setuptools-scm' + 'python-wheel' +) +checkdepends=('python-pytest') + +source=("git+$url.git#tag=$pkgver") +b2sums=('beef1b9c7d7ca6a724a3777560d0109ad415d199efe130cb6a6d70139c6ad327f83bdf657ef035cd8a7dc66aea7f0c4d5dde0c72d2549750b913ababba7e5710') + +build() { + cd $pkgname + python -m build --wheel --no-isolation +} + +check() { + cd $pkgname + python -m venv --system-site-packages test-env + test-env/bin/python -m installer dist/*.whl + test-env/bin/python -m pytest +} + +package() { + cd $pkgname + python -m installer --destdir="$pkgdir" dist/*.whl + install -vDm644 -t "$pkgdir/usr/share/doc/$pkgname" ./*.md + + # We already install the desktop entries, not needed + rm -v "$pkgdir/usr/bin/protontricks-desktop-install" + local site_packages=$(python -c "import site; print(site.getsitepackages()[0])") + rm -vr "$pkgdir/$site_packages/protontricks/data/share" +} diff --git a/src/protontricks/data/appimage/execve-sharun-hack.c b/src/protontricks/data/appimage/execve-sharun-hack.c new file mode 100644 index 0000000..369b674 --- /dev/null +++ b/src/protontricks/data/appimage/execve-sharun-hack.c @@ -0,0 +1,715 @@ +/* + * execve-sharun-hack.c — LD_PRELOAD library that intercepts execve()/posix_spawn() + * calls to dynamic 64-bit ELF binaries under directories listed in + * ANYLINUX_EXECVE_WRAP_PATHS and redirects them through: + * + * execve("$APPDIR/sharun", + * ["sharun", "env", + * "$APPDIR/lib/ld-linux-.so.?", + * "--library-path", "$APPDIR/lib:$APPDIR/lib/sub:...", + * "--preload", "/path/to/this/lib.so", + * "/path/to/target", ], + * envp) + * + * ANYLINUX_EXECVE_WRAP_PATHS — colon-separated list of directories; wrapping + * only occurs when the resolved target starts with one of these directories. + * If unset or empty, no wrapping occurs. + * + * Supported: glibc only, x86_64 and aarch64. + * + * Build: + * cc -shared -fPIC -O2 -Wall -Wextra -o execve-sharun-hack.so execve-sharun-hack.c -ldl + * + * Debug: + * export EXECVE_SHARUN_DEBUG=1 + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char **environ; + +typedef int (*execve_func_t)(const char *, char *const [], char *const []); +typedef int (*execvpe_func_t)(const char *, char *const [], char *const []); + +typedef int (*posix_spawn_func_t)(pid_t *, const char *, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *, + char *const [], char *const []); + +typedef int (*posix_spawnp_func_t)(pid_t *, const char *, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *, + char *const [], char *const []); + +typedef ssize_t (*readlink_func_t)(const char *, char *, size_t); +typedef ssize_t (*readlinkat_func_t)(int, const char *, char *, size_t); + +#define VISIBLE __attribute__((visibility("default"))) + +/* ───────────────────────── debug ───────────────────────── */ + +static int debug_enabled(void) { + static int cached = -1; + if (cached == -1) { + const char *v = getenv("EXECVE_SHARUN_DEBUG"); + cached = (v && v[0] == '1' && v[1] == '\0'); + } + return cached; +} + +#define DEBUG(...) do { \ + if (debug_enabled()) \ + fprintf(stderr, " [execve_sharun.so] >> " __VA_ARGS__); \ +} while (0) + +/* ───────────────────── self path ──────────────────────── */ + +static const char *get_self_path(void) { + static char self_path[PATH_MAX]; + static int resolved; + + if (resolved) + return self_path[0] ? self_path : NULL; + resolved = 1; + + Dl_info info; + if (dladdr((void *)get_self_path, &info) && info.dli_fname) { + if (realpath(info.dli_fname, self_path)) + return self_path; + } + + self_path[0] = '\0'; + return NULL; +} + +/* Constructor ping: proves the library loaded */ +__attribute__((constructor)) +static void preload_ctor(void) { + if (debug_enabled()) { + const char *self = get_self_path(); + fprintf(stderr, " [execve_sharun.so] >> LOADED pid=%d self=%s\n", + getpid(), self ? self : "(null)"); + const char *lp = getenv("LD_PRELOAD"); + fprintf(stderr, " [execve_sharun.so] >> LD_PRELOAD=%s\n", lp ? lp : "(null)"); + } +} + +/* ───────────────────── ELF helpers ─────────────────────── */ + +static int is_dynamic_elf64(const char *path) { + int fd = open(path, O_RDONLY); + if (fd < 0) return 0; + + unsigned char e_ident[EI_NIDENT]; + if (read(fd, e_ident, EI_NIDENT) != EI_NIDENT) { + close(fd); + return 0; + } + + if (e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 || + e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3) { + close(fd); + return 0; + } + + if (e_ident[EI_CLASS] != ELFCLASS64) { + close(fd); + return 0; + } + + Elf64_Ehdr ehdr; + if (lseek(fd, 0, SEEK_SET) != 0 || + read(fd, &ehdr, sizeof(ehdr)) != (ssize_t)sizeof(ehdr)) { + close(fd); + return 0; + } + + int found = 0; + for (int i = 0; i < ehdr.e_phnum && !found; i++) { + Elf64_Phdr phdr; + off_t off = ehdr.e_phoff + (off_t)i * ehdr.e_phentsize; + if (lseek(fd, off, SEEK_SET) == off && + read(fd, &phdr, sizeof(phdr)) == (ssize_t)sizeof(phdr)) { + if (phdr.p_type == PT_INTERP) + found = 1; + } + } + + close(fd); + return found; +} + +/* ───────────────────── path helpers ────────────────────── */ + +static int path_starts_with(const char *path, const char *prefix) { + size_t plen = strlen(prefix); + if (strncmp(path, prefix, plen) != 0) return 0; + return (path[plen] == '/' || path[plen] == '\0'); +} + +static int find_sharun(const char *appdir, char *out, size_t outsz) { + snprintf(out, outsz, "%s/sharun", appdir); + return (access(out, X_OK) == 0); +} + +/* glibc only: x86_64/aarch64 */ +static int find_ld_linux(const char *appdir, char *out, size_t outsz) { + struct utsname uts; + if (uname(&uts) != 0) + return 0; + + const char *ld_name = NULL; + if (strcmp(uts.machine, "x86_64") == 0) { + ld_name = "ld-linux-x86-64.so.2"; + } else if (strcmp(uts.machine, "aarch64") == 0) { + ld_name = "ld-linux-aarch64.so.1"; + } else { + return 0; + } + + snprintf(out, outsz, "%s/lib/%s", appdir, ld_name); + return (access(out, R_OK) == 0); +} + +/* Resolve to canonical path; returns malloc'd path or NULL */ +static char *resolve_binary_path(const char *filename) { + if (!filename || !*filename) return NULL; + + if (strchr(filename, '/')) + return realpath(filename, NULL); + + const char *pathenv = getenv("PATH"); + if (!pathenv) return NULL; + + char *pathcopy = strdup(pathenv); + if (!pathcopy) return NULL; + + char *saveptr = NULL; + for (char *dir = strtok_r(pathcopy, ":", &saveptr); + dir; + dir = strtok_r(NULL, ":", &saveptr)) + { + char candidate[PATH_MAX]; + snprintf(candidate, sizeof(candidate), "%s/%s", dir, filename); + if (access(candidate, X_OK) == 0) { + char *rp = realpath(candidate, NULL); + free(pathcopy); + return rp; + } + } + + free(pathcopy); + return NULL; +} + +/* ───────────────────── redirect logic ───────────────────── */ + +/* + * Returns 1 if target_resolved should be wrapped. + * Reads ANYLINUX_EXECVE_WRAP_PATHS (colon-separated directory list) and + * wraps only when the resolved target starts with one of those directories. + * Returns 0 if the env var is unset/empty or the target does not match. + */ +static int should_redirect_target(const char *target_resolved) { + const char *wrap_paths = getenv("ANYLINUX_EXECVE_WRAP_PATHS"); + if (!wrap_paths || !*wrap_paths) return 0; + + char *paths_copy = strdup(wrap_paths); + if (!paths_copy) return 0; + + int match = 0; + char *saveptr = NULL; + for (char *dir = strtok_r(paths_copy, ":", &saveptr); + dir && !match; + dir = strtok_r(NULL, ":", &saveptr)) + { + if (!*dir) continue; + char canon[PATH_MAX]; + if (!realpath(dir, canon)) + continue; + if (path_starts_with(target_resolved, canon)) + match = 1; + } + + free(paths_copy); + if (!match) return 0; + if (!is_dynamic_elf64(target_resolved)) return 0; + return 1; +} + +/* + * Append immediate subdirectories of `base` (one level deep, real dirs only — + * symlinks and hidden entries are skipped) to a dynamic string buffer. + * Each found directory is appended as ":". + * Returns 1 on success, 0 on allocation failure. + */ +static int append_immediate_subdirs(const char *base, char **buf, size_t *len, + size_t *cap) { + DIR *d = opendir(base); + if (!d) return 1; /* inaccessible — not a hard error */ + + struct dirent *entry; + while ((entry = readdir(d)) != NULL) { + /* Skip ".", "..", and any other hidden entry */ + if (entry->d_name[0] == '.') continue; + + char child[PATH_MAX]; + int rc = snprintf(child, sizeof(child), "%s/%s", base, entry->d_name); + if (rc < 0 || (size_t)rc >= sizeof(child)) continue; /* path too long */ + + struct stat st; + if (lstat(child, &st) != 0 || !S_ISDIR(st.st_mode)) continue; + + /* Grow buffer as needed: colon + path + NUL */ + size_t child_len = (size_t)rc; + size_t needed = *len + 1 + child_len + 1; + if (needed > *cap) { + size_t new_cap = *cap * 2; + if (new_cap < needed) new_cap = needed + 256; + char *tmp = realloc(*buf, new_cap); + if (!tmp) { closedir(d); return 0; } + *buf = tmp; + *cap = new_cap; + } + + (*buf)[*len] = ':'; + memcpy(*buf + *len + 1, child, child_len + 1); + *len += 1 + child_len; + } + + closedir(d); + return 1; +} + +/* + * Build a colon-separated library path string: $APPDIR/lib followed by every + * immediate (one-level-deep) real subdirectory within it. + * Returns a malloc'd string that the caller must free. + */ +static char *build_library_path(const char *appdir) { + char base[PATH_MAX]; + int rc = snprintf(base, sizeof(base), "%s/lib", appdir); + if (rc < 0 || (size_t)rc >= sizeof(base)) return NULL; + + size_t base_len = (size_t)rc; + size_t cap = base_len + 1024; + char *buf = malloc(cap); + if (!buf) return NULL; + + memcpy(buf, base, base_len + 1); + size_t len = base_len; + + if (!append_immediate_subdirs(base, &buf, &len, &cap)) { + free(buf); + return NULL; + } + return buf; +} + +/* ─────────────────────── redirect context ──────────────────── */ + +/* + * All information needed to perform a redirect, gathered in one place. + * `resolved` is heap-allocated; all others point to static/existing storage. + */ +typedef struct { + char *resolved; /* malloc'd canonical target path */ + char sharun_path[PATH_MAX]; + char ld_path[PATH_MAX]; + const char *self; /* points to static buffer */ + const char *appdir; /* points to environ */ +} redirect_ctx_t; + +/* + * Populate `ctx` with everything needed to redirect `filename`. + * Returns 1 if the redirect should proceed (ctx fully populated). + * Returns 0 if no redirect should happen; in that case ctx->resolved is + * always freed internally and set to NULL. + */ +static int gather_redirect_ctx(const char *filename, redirect_ctx_t *ctx) { + ctx->resolved = resolve_binary_path(filename); + if (!ctx->resolved) return 0; + + if (!should_redirect_target(ctx->resolved)) { + free(ctx->resolved); + ctx->resolved = NULL; + return 0; + } + + ctx->appdir = getenv("APPDIR"); + if (!ctx->appdir || !*ctx->appdir) { + free(ctx->resolved); + ctx->resolved = NULL; + return 0; + } + + if (!find_sharun(ctx->appdir, ctx->sharun_path, sizeof(ctx->sharun_path)) || + !find_ld_linux(ctx->appdir, ctx->ld_path, sizeof(ctx->ld_path))) { + free(ctx->resolved); + ctx->resolved = NULL; + return 0; + } + + ctx->self = get_self_path(); + if (!ctx->self) { + free(ctx->resolved); + ctx->resolved = NULL; + return 0; + } + + return 1; +} + +/* + * Build the redirected argv: + * sharun env ld-linux --library-path --preload self target [flags...] + * + * Returns malloc'd new_argv on success, NULL on failure. + * new_argv[4] (the library path string) is heap-allocated; use + * free_redirect_resources() to clean up. + */ +static char **build_redirect_argv(const redirect_ctx_t *ctx, + char *const argv[], + int *out_argc) +{ + int orig_argc = 0; + if (argv) while (argv[orig_argc]) orig_argc++; + + int skip = (orig_argc > 0) ? 1 : 0; + int trailing = orig_argc - skip; + + /* Fixed prefix: + * [0] sharun + * [1] env + * [2] ld-linux + * [3] --library-path + * [4] lib-path (heap-allocated) + * [5] --preload + * [6] self + * [7] target + */ + int new_total = 8 + trailing; + + char *lib_path = build_library_path(ctx->appdir); + if (!lib_path) return NULL; + + char **new_argv = calloc((size_t)new_total + 1, sizeof(char *)); + if (!new_argv) { + free(lib_path); + return NULL; + } + + new_argv[0] = (char *)ctx->sharun_path; + new_argv[1] = (char *)"env"; + new_argv[2] = (char *)ctx->ld_path; + new_argv[3] = (char *)"--library-path"; + new_argv[4] = lib_path; /* caller frees via free_redirect_resources */ + new_argv[5] = (char *)"--preload"; + new_argv[6] = (char *)ctx->self; + new_argv[7] = (char *)ctx->resolved; + + for (int i = 0; i < trailing; i++) + new_argv[8 + i] = argv[skip + i]; + + new_argv[new_total] = NULL; + if (out_argc) *out_argc = new_total; + return new_argv; +} + +/* Release resources allocated by build_redirect_argv and gather_redirect_ctx. */ +static void free_redirect_resources(char **new_argv, redirect_ctx_t *ctx) { + if (new_argv) { + free(new_argv[4]); /* lib_path */ + free(new_argv); + } + if (ctx) { + free(ctx->resolved); + ctx->resolved = NULL; + } +} + +/* ─────────── _SHARUN_TARGET_EXE helpers ────────────────────────── + * + * When redirecting a binary through sharun/ld-linux, we inject + * _SHARUN_TARGET_EXE= into the child's environment. + * The readlink() interceptor below reads this variable so that + * /proc/self/exe queries return the real binary path rather than the + * ld-linux interpreter path. + * ──────────────────────────────────────────────────────────────── */ + +#define SHARUN_TARGET_VAR "_SHARUN_TARGET_EXE=" +#define SHARUN_TARGET_VAR_LEN (sizeof(SHARUN_TARGET_VAR) - 1) + +/* + * Build a new envp array identical to `envp` except that + * _SHARUN_TARGET_EXE is set to `target`. + * + * Returns a heap-allocated array; free with free_envp_with_target(). + * `envp` may be NULL (treated as empty). + * Returns NULL if `target` is NULL or memory allocation fails. + */ +static char **build_envp_with_target(const char *target, + char *const envp[]) +{ + if (!target) return NULL; + + int n = 0; + int var_idx = -1; + + if (envp) { + while (envp[n]) { + if (strncmp(envp[n], SHARUN_TARGET_VAR, SHARUN_TARGET_VAR_LEN) == 0) + var_idx = n; + n++; + } + } + + size_t target_len = strlen(target); + size_t sz = SHARUN_TARGET_VAR_LEN + target_len + 1; + char *entry = malloc(sz); + if (!entry) return NULL; + memcpy(entry, SHARUN_TARGET_VAR, SHARUN_TARGET_VAR_LEN); + memcpy(entry + SHARUN_TARGET_VAR_LEN, target, target_len + 1); + + int new_n = (var_idx < 0) ? n + 1 : n; + char **new_envp = malloc(((size_t)new_n + 1) * sizeof(char *)); + if (!new_envp) { free(entry); return NULL; } + + int j = 0; + for (int i = 0; i < n; i++) { + if (i == var_idx) continue; + new_envp[j++] = (char *)envp[i]; + } + new_envp[j++] = entry; + new_envp[j] = NULL; + return new_envp; +} + +/* Release resources allocated by build_envp_with_target(). */ +static void free_envp_with_target(char **new_envp) +{ + if (!new_envp) return; + for (int i = 0; new_envp[i]; i++) { + if (strncmp(new_envp[i], SHARUN_TARGET_VAR, SHARUN_TARGET_VAR_LEN) == 0) { + free(new_envp[i]); + break; + } + } + free(new_envp); +} + +/* ───────────────────── execve interception ───────────────────── */ + +static int maybe_redirect_execve(execve_func_t real_execve, + const char *filename, + char *const argv[], + char *const envp[]) +{ + redirect_ctx_t ctx = {0}; + if (!gather_redirect_ctx(filename, &ctx)) + return real_execve(filename, argv, envp); + + int new_argc = 0; + char **new_argv = build_redirect_argv(&ctx, argv, &new_argc); + if (!new_argv) { + free(ctx.resolved); + return real_execve(filename, argv, envp); + } + + DEBUG("Redirect execve: %s -> %s\n", filename, ctx.sharun_path); + if (debug_enabled()) { + for (int i = 0; i < new_argc; i++) + fprintf(stderr, " [execve_sharun.so] >> argv[%d]=%s\n", i, new_argv[i]); + } + + /* + * Propagate the real binary path via _SHARUN_TARGET_EXE so that the + * readlink("/proc/self/exe") interceptor in the child returns the + * correct path instead of the ld-linux interpreter path. + */ + char **new_envp = build_envp_with_target(ctx.resolved, envp); + + /* Execute sharun; only returns on failure */ + (void)real_execve(ctx.sharun_path, new_argv, new_envp ? new_envp : envp); + + int saved = errno; + DEBUG("Redirect execve failed errno=%d (%s), falling back\n", saved, strerror(saved)); + + free_envp_with_target(new_envp); + free_redirect_resources(new_argv, &ctx); + return real_execve(filename, argv, envp); +} + +VISIBLE int execve(const char *filename, char *const argv[], char *const envp[]) { + execve_func_t real = (execve_func_t)dlsym(RTLD_NEXT, "execve"); + if (!real) { + errno = ENOSYS; + return -1; + } + return maybe_redirect_execve(real, filename, argv, envp); +} + +VISIBLE int execv(const char *filename, char *const argv[]) { + return execve(filename, argv, environ); +} + +VISIBLE int execvpe(const char *filename, char *const argv[], char *const envp[]) { + /* Prefer our logic by resolving and calling execve; falls back to real execvpe */ + char *resolved = resolve_binary_path(filename); + if (resolved) { + int ret = execve(resolved, argv, envp); + free(resolved); + return ret; + } + + execvpe_func_t real = (execvpe_func_t)dlsym(RTLD_NEXT, "execvpe"); + if (!real) { + errno = ENOSYS; + return -1; + } + return real(filename, argv, envp); +} + +VISIBLE int execvp(const char *filename, char *const argv[]) { + return execvpe(filename, argv, environ); +} + +/* ───────────────────── posix_spawn interception ────────────────── */ + +VISIBLE int posix_spawn(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *attr, + char *const argv[], char *const envp[]) +{ + posix_spawn_func_t real = (posix_spawn_func_t)dlsym(RTLD_NEXT, "posix_spawn"); + if (!real) return ENOSYS; + + redirect_ctx_t ctx = {0}; + if (!gather_redirect_ctx(path, &ctx)) + return real(pid, path, fa, attr, argv, envp); + + int new_argc = 0; + char **new_argv = build_redirect_argv(&ctx, argv, &new_argc); + if (!new_argv) { + free(ctx.resolved); + return real(pid, path, fa, attr, argv, envp); + } + + DEBUG("Redirect posix_spawn: %s -> %s\n", path, ctx.sharun_path); + + char **new_envp = build_envp_with_target(ctx.resolved, envp); + int rc = real(pid, ctx.sharun_path, fa, attr, new_argv, + new_envp ? new_envp : envp); + free_envp_with_target(new_envp); + free_redirect_resources(new_argv, &ctx); + return rc; +} + +VISIBLE int posix_spawnp(pid_t *pid, const char *file, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *attr, + char *const argv[], char *const envp[]) +{ + posix_spawnp_func_t real = (posix_spawnp_func_t)dlsym(RTLD_NEXT, "posix_spawnp"); + if (!real) return ENOSYS; + + /* Resolve first so ANYLINUX_EXECVE_WRAP_PATHS check can apply */ + redirect_ctx_t ctx = {0}; + if (!gather_redirect_ctx(file, &ctx)) + return real(pid, file, fa, attr, argv, envp); + + int new_argc = 0; + char **new_argv = build_redirect_argv(&ctx, argv, &new_argc); + if (!new_argv) { + free(ctx.resolved); + return real(pid, file, fa, attr, argv, envp); + } + + DEBUG("Redirect posix_spawnp: %s -> %s\n", file, ctx.sharun_path); + + char **new_envp = build_envp_with_target(ctx.resolved, envp); + int rc = real(pid, ctx.sharun_path, fa, attr, new_argv, + new_envp ? new_envp : envp); + free_envp_with_target(new_envp); + free_redirect_resources(new_argv, &ctx); + return rc; +} + +/* ───────────────────── readlink interception ──────────────────── + * + * When a binary runs under "ld-linux /path/to/binary", /proc/self/exe + * resolves to the ld-linux interpreter path, not the binary itself. + * Programs like the JDK launcher read /proc/self/exe to locate their + * installation directory (JAVA_HOME); if it returns the ld-linux path + * the derived path is wrong. + * + * To fix this, we intercept readlink()/readlinkat() for /proc/self/exe + * and /proc/thread-self/exe and return the real target binary path + * stored in _SHARUN_TARGET_EXE, which is injected into the process + * environment by build_envp_with_target() when our execve/posix_spawn + * hooks redirect through sharun. + * ─────────────────────────────────────────────────────────────── */ + +static int is_proc_self_exe(const char *pathname) +{ + if (!pathname) return 0; + return (strcmp(pathname, "/proc/self/exe") == 0 || + strcmp(pathname, "/proc/thread-self/exe") == 0); +} + +VISIBLE ssize_t readlink(const char *pathname, char *buf, size_t bufsz) +{ + readlink_func_t real = (readlink_func_t)dlsym(RTLD_NEXT, "readlink"); + if (!real) { errno = ENOSYS; return -1; } + + if (is_proc_self_exe(pathname)) { + const char *target = getenv("_SHARUN_TARGET_EXE"); + if (target && *target) { + size_t len = strlen(target); + /* readlink(2) truncates to bufsz without NUL-terminating. */ + size_t copy_len = (len < bufsz) ? len : bufsz; + memcpy(buf, target, copy_len); + DEBUG("readlink(%s) -> %.*s\n", pathname, (int)copy_len, buf); + return (ssize_t)copy_len; + } + } + + return real(pathname, buf, bufsz); +} + +VISIBLE ssize_t readlinkat(int dirfd, const char *pathname, + char *buf, size_t bufsz) +{ + readlinkat_func_t real = (readlinkat_func_t)dlsym(RTLD_NEXT, "readlinkat"); + if (!real) { errno = ENOSYS; return -1; } + + /* AT_FDCWD with an absolute /proc path is the only case we handle. */ + if (dirfd == AT_FDCWD && is_proc_self_exe(pathname)) { + const char *target = getenv("_SHARUN_TARGET_EXE"); + if (target && *target) { + size_t len = strlen(target); + size_t copy_len = (len < bufsz) ? len : bufsz; + memcpy(buf, target, copy_len); + DEBUG("readlinkat(AT_FDCWD, %s) -> %.*s\n", pathname, + (int)copy_len, buf); + return (ssize_t)copy_len; + } + } + + return real(dirfd, pathname, buf, bufsz); +} diff --git a/src/protontricks/data/appimage/get-dependencies.sh b/src/protontricks/data/appimage/get-dependencies.sh new file mode 100755 index 0000000..4125779 --- /dev/null +++ b/src/protontricks/data/appimage/get-dependencies.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -eu + +ARCH=$(uname -m) + +echo "Installing package dependencies..." +echo "---------------------------------------------------------------" +pacman -Syu --noconfirm protontricks zenity yad + +echo "Installing debloated packages..." +echo "---------------------------------------------------------------" +./get-debloated-pkgs.sh --add-common --prefer-nano + +# Comment this out if you need an AUR package +#make-aur-package PACKAGENAME + +# If the application needs to be manually built that has to be done down here diff --git a/src/protontricks/data/appimage/make-appimage.sh b/src/protontricks/data/appimage/make-appimage.sh new file mode 100755 index 0000000..18f2b92 --- /dev/null +++ b/src/protontricks/data/appimage/make-appimage.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +set -eu + +ARCH=$(uname -m) +VERSION=$(pacman -Q protontricks | awk '{print $2; exit}') # example command to get version of application here + +SHARUN="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/quick-sharun.sh" +DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" + +# ADD LIBRARIES +wget --retry-connrefused --tries=30 "$DEBLOATED_PKGS" -O ./get-debloated-pkgs +wget --retry-connrefused --tries=30 "$SHARUN" -O ./quick-sharun +chmod +x ./quick-sharun ./get-debloated-pkgs + +export ARCH VERSION +#export APPDIR="$PWD/AppDir" +export OUTPATH=./dist +export ADD_HOOKS="self-updater.bg.hook" +#export UPINFO="gh-releases-zsync|${GITHUB_REPOSITORY%/*}|${GITHUB_REPOSITORY#*/}|latest|*$ARCH.AppImage.zsync" +export ICON=/usr/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg +export DESKTOP=/usr/share/applications/protontricks.desktop +export LIB_DIR=/usr/lib +export DEPLOY_PYTHON=1 +export DEPLOY_OPENGL=1 +export DEPLOY_VULKAN=1 + +# Deploy dependencies +./quick-sharun /usr/bin/*tricks* /usr/bin/zenity /usr/bin/yad +echo 'unset VK_DRIVER_FILES' >> ./AppDir/.env + +cc -shared -fPIC -O2 -o ./AppDir/lib/execve-sharun-hack.so execve-sharun-hack.c -ldl +echo 'execve-sharun-hack.so' >> ./AppDir/.preload +echo 'export ANYLINUX_EXECVE_WRAP_PATHS="$DATADIR:$HOME/.steam"' >> ./AppDir/bin/execve-wrap-path.hook + +# Additional changes can be done in between here + +# Turn AppDir into AppImage +./quick-sharun --make-appimage diff --git a/src/protontricks/data/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg b/src/protontricks/data/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg new file mode 100644 index 0000000..b44e802 --- /dev/null +++ b/src/protontricks/data/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ab8df670cbc31b4b9abb2aa2a541c4dd7d4a847c Mon Sep 17 00:00:00 2001 From: Fatih Bakal Date: Fri, 26 Jun 2026 16:54:33 +0300 Subject: [PATCH 02/13] update --- .gitignore | 2 +- .../data/share/applications/protontricks-launch.desktop | 2 +- src/protontricks/data/share/applications/protontricks.desktop | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f23ec27..defaa4c 100644 --- a/.gitignore +++ b/.gitignore @@ -126,6 +126,6 @@ AppDir/ quick-sharun* get-debloated-pkgs* -src/protontricks/data/appimage/protontricks/pkg src/protontricks/data/appimage/protontricks/ src/protontricks/data/appimage/protontricks/src/ +src/protontricks/data/appimage/pkg/ diff --git a/src/protontricks/data/share/applications/protontricks-launch.desktop b/src/protontricks/data/share/applications/protontricks-launch.desktop index 56112d7..66cac55 100644 --- a/src/protontricks/data/share/applications/protontricks-launch.desktop +++ b/src/protontricks/data/share/applications/protontricks-launch.desktop @@ -5,5 +5,5 @@ Type=Application Terminal=false NoDisplay=true Categories=Utility -Icon=wine +Icon=com.github.Matoking.protontricks MimeType=application/x-ms-dos-executable;application/x-msi;application/x-ms-shortcut; diff --git a/src/protontricks/data/share/applications/protontricks.desktop b/src/protontricks/data/share/applications/protontricks.desktop index ec0e964..bfd53c7 100644 --- a/src/protontricks/data/share/applications/protontricks.desktop +++ b/src/protontricks/data/share/applications/protontricks.desktop @@ -5,5 +5,5 @@ Comment=A simple wrapper that does winetricks things for Proton enabled games Type=Application Terminal=false Categories=Utility; -Icon=wine +Icon=com.github.Matoking.protontricks Keywords=Steam;Proton;Wine;Winetricks; From 0e14d41a63c61de9adb78e3cb9396dec230b2a52 Mon Sep 17 00:00:00 2001 From: Fatih Bakal Date: Fri, 26 Jun 2026 18:13:44 +0300 Subject: [PATCH 03/13] works --- src/protontricks/data/appimage/PKGBUILD-git | 11 +++++---- .../data/appimage/get-dependencies.sh | 8 ++++++- .../data/appimage/make-appimage.sh | 24 +++++++++++++++---- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/protontricks/data/appimage/PKGBUILD-git b/src/protontricks/data/appimage/PKGBUILD-git index 6ce6594..7687ed9 100644 --- a/src/protontricks/data/appimage/PKGBUILD-git +++ b/src/protontricks/data/appimage/PKGBUILD-git @@ -30,8 +30,8 @@ makedepends=( ) checkdepends=('python-pytest') -source=("git+$url.git#tag=$pkgver") -b2sums=('beef1b9c7d7ca6a724a3777560d0109ad415d199efe130cb6a6d70139c6ad327f83bdf657ef035cd8a7dc66aea7f0c4d5dde0c72d2549750b913ababba7e5710') +source=("git+$url.git#branch=appimage") +b2sums=('SKIP') build() { cd $pkgname @@ -47,11 +47,12 @@ check() { package() { cd $pkgname + install -vDm644 src/protontricks/data/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg "$pkgdir/usr/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg" python -m installer --destdir="$pkgdir" dist/*.whl install -vDm644 -t "$pkgdir/usr/share/doc/$pkgname" ./*.md # We already install the desktop entries, not needed - rm -v "$pkgdir/usr/bin/protontricks-desktop-install" - local site_packages=$(python -c "import site; print(site.getsitepackages()[0])") - rm -vr "$pkgdir/$site_packages/protontricks/data/share" + #rm -v "$pkgdir/usr/bin/protontricks-desktop-install" + #local site_packages=$(python -c "import site; print(site.getsitepackages()[0])") + #rm -vr "$pkgdir/$site_packages/protontricks/data/share" } diff --git a/src/protontricks/data/appimage/get-dependencies.sh b/src/protontricks/data/appimage/get-dependencies.sh index 4125779..67decea 100755 --- a/src/protontricks/data/appimage/get-dependencies.sh +++ b/src/protontricks/data/appimage/get-dependencies.sh @@ -1,16 +1,22 @@ + #!/bin/sh set -eu ARCH=$(uname -m) +DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" +wget --retry-connrefused --tries=30 "$DEBLOATED_PKGS" -O ./get-debloated-pkgs + +chmod +x ./quick-sharun ./get-debloated-pkgs + echo "Installing package dependencies..." echo "---------------------------------------------------------------" pacman -Syu --noconfirm protontricks zenity yad echo "Installing debloated packages..." echo "---------------------------------------------------------------" -./get-debloated-pkgs.sh --add-common --prefer-nano +./get-debloated-pkgs --add-common --prefer-nano # Comment this out if you need an AUR package #make-aur-package PACKAGENAME diff --git a/src/protontricks/data/appimage/make-appimage.sh b/src/protontricks/data/appimage/make-appimage.sh index 18f2b92..2bbfcff 100755 --- a/src/protontricks/data/appimage/make-appimage.sh +++ b/src/protontricks/data/appimage/make-appimage.sh @@ -6,12 +6,10 @@ ARCH=$(uname -m) VERSION=$(pacman -Q protontricks | awk '{print $2; exit}') # example command to get version of application here SHARUN="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/quick-sharun.sh" -DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" # ADD LIBRARIES -wget --retry-connrefused --tries=30 "$DEBLOATED_PKGS" -O ./get-debloated-pkgs wget --retry-connrefused --tries=30 "$SHARUN" -O ./quick-sharun -chmod +x ./quick-sharun ./get-debloated-pkgs +chmod +x ./quick-sharun export ARCH VERSION #export APPDIR="$PWD/AppDir" @@ -26,8 +24,26 @@ export DEPLOY_OPENGL=1 export DEPLOY_VULKAN=1 # Deploy dependencies -./quick-sharun /usr/bin/*tricks* /usr/bin/zenity /usr/bin/yad +quick-sharun \ + /usr/bin/*tricks* \ + /usr/lib/libopenjp2.so* \ + /usr/lib/libtiff.so* \ + /usr/lib/libimagequant.so* \ + /usr/bin/zenity \ + /usr/bin/yad + echo 'unset VK_DRIVER_FILES' >> ./AppDir/.env +# Fix python symlinks to point to 3.11 which has the stdlib bundled +rm -f ./AppDir/shared/bin/python ./AppDir/shared/bin/python3 +ln -s python3.11 ./AppDir/shared/bin/python +ln -s python3.11 ./AppDir/shared/bin/python3 + +# Install protontricks and its Python dependencies into the AppDir's Python 3.11 +SITE_PACKAGES="$PWD/AppDir/lib/python3.11/site-packages" +python3.11 -m venv /tmp/protontricks-venv +/tmp/protontricks-venv/bin/pip install --target="$SITE_PACKAGES" --no-deps vdf Pillow +rsync -a --exclude='data/appimage' "$PWD/../../" "$SITE_PACKAGES/protontricks/" +rm -rf /tmp/protontricks-venv cc -shared -fPIC -O2 -o ./AppDir/lib/execve-sharun-hack.so execve-sharun-hack.c -ldl echo 'execve-sharun-hack.so' >> ./AppDir/.preload From ff6b842af937478803cfdf786ac6ddd64954b545 Mon Sep 17 00:00:00 2001 From: Fatih Bakal Date: Fri, 26 Jun 2026 20:25:04 +0300 Subject: [PATCH 04/13] Polish --- .github/workflows/appimage.yml | 84 +++++++++++++++++++ .../{appstream.yaml => appstream.yml} | 0 src/protontricks/data/appimage/PKGBUILD-git | 10 +-- .../data/appimage/get-dependencies.sh | 4 +- .../data/appimage/make-appimage.sh | 16 +--- .../applications/protontricks-launch.desktop | 1 + .../share/applications/protontricks.desktop | 1 + 7 files changed, 97 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/appimage.yml rename .github/workflows/{appstream.yaml => appstream.yml} (100%) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml new file mode 100644 index 0000000..3e8f550 --- /dev/null +++ b/.github/workflows/appimage.yml @@ -0,0 +1,84 @@ +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + release_tag: + description: "Release tag (example: 1.0.0)" + required: false + type: string + + prerelease: + description: "Mark as prerelease" + required: false + default: "false" + type: choice + options: + - "false" + - "true" + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + + container: + image: archlinux:latest + + steps: + - name: Install base dependencies + run: | + pacman -Syu --noconfirm archlinux-keyring + pacman -Syu --noconfirm pkg-config \ + base-devel \ + sudo \ + wget \ + patchelf + + - name: Create build user + run: | + useradd -m builder + echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Fix permissions + run: chown -R builder:builder . + + - name: Build + run: | + sudo -u builder sh <<'EOF' + set -e + cd src/protontricks/data/appimage + makepkg -p PKGBUILD-git -fs --noconfirm + EOF + ls -lh + cd src/protontricks/data/appimage + pacman --noconfirm -U ./*.pkg.tar.zst + chmod +x ./get-dependencies.sh ./make-appimage.sh + ./get-dependencies.sh + ./make-appimage.sh + + - name: Upload build artifacts + uses: actions/upload-artifact@v7 + with: + name: AppImage + path: "packaging/dist/*.AppImage" + archive: false + + - name: Create GitHub Release + if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.release_tag != '') + uses: softprops/action-gh-release@v3 + with: + tag_name: ${{ github.event.inputs.release_tag || github.ref_name }} + name: ${{ github.event.inputs.release_tag || github.ref_name }} + files: "packaging/dist/*.AppImage" + generate_release_notes: true + draft: false + prerelease: ${{ github.event.inputs.prerelease == 'true' }} diff --git a/.github/workflows/appstream.yaml b/.github/workflows/appstream.yml similarity index 100% rename from .github/workflows/appstream.yaml rename to .github/workflows/appstream.yml diff --git a/src/protontricks/data/appimage/PKGBUILD-git b/src/protontricks/data/appimage/PKGBUILD-git index 7687ed9..bf21839 100644 --- a/src/protontricks/data/appimage/PKGBUILD-git +++ b/src/protontricks/data/appimage/PKGBUILD-git @@ -15,10 +15,10 @@ depends=( 'python-pillow' 'python-vdf' 'winetricks' - 'zenity' - 'yad' 'openjpeg2' 'libimagequant' + 'zenity' + 'yad' ) makedepends=( 'git' @@ -52,7 +52,7 @@ package() { install -vDm644 -t "$pkgdir/usr/share/doc/$pkgname" ./*.md # We already install the desktop entries, not needed - #rm -v "$pkgdir/usr/bin/protontricks-desktop-install" - #local site_packages=$(python -c "import site; print(site.getsitepackages()[0])") - #rm -vr "$pkgdir/$site_packages/protontricks/data/share" + rm -v "$pkgdir/usr/bin/protontricks-desktop-install" + local site_packages=$(python -c "import site; print(site.getsitepackages()[0])") + rm -vr "$pkgdir/$site_packages/protontricks/data/share" } diff --git a/src/protontricks/data/appimage/get-dependencies.sh b/src/protontricks/data/appimage/get-dependencies.sh index 67decea..19958b1 100755 --- a/src/protontricks/data/appimage/get-dependencies.sh +++ b/src/protontricks/data/appimage/get-dependencies.sh @@ -8,11 +8,11 @@ ARCH=$(uname -m) DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" wget --retry-connrefused --tries=30 "$DEBLOATED_PKGS" -O ./get-debloated-pkgs -chmod +x ./quick-sharun ./get-debloated-pkgs +chmod +x ./get-debloated-pkgs echo "Installing package dependencies..." echo "---------------------------------------------------------------" -pacman -Syu --noconfirm protontricks zenity yad +makepkg -p PKGBUILD-git -fsi --noconfirm echo "Installing debloated packages..." echo "---------------------------------------------------------------" diff --git a/src/protontricks/data/appimage/make-appimage.sh b/src/protontricks/data/appimage/make-appimage.sh index 2bbfcff..096f831 100755 --- a/src/protontricks/data/appimage/make-appimage.sh +++ b/src/protontricks/data/appimage/make-appimage.sh @@ -7,6 +7,9 @@ VERSION=$(pacman -Q protontricks | awk '{print $2; exit}') # example command to SHARUN="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/quick-sharun.sh" +#Remove leftovers +rm -rf AppDir dist + # ADD LIBRARIES wget --retry-connrefused --tries=30 "$SHARUN" -O ./quick-sharun chmod +x ./quick-sharun @@ -24,7 +27,7 @@ export DEPLOY_OPENGL=1 export DEPLOY_VULKAN=1 # Deploy dependencies -quick-sharun \ +./quick-sharun \ /usr/bin/*tricks* \ /usr/lib/libopenjp2.so* \ /usr/lib/libtiff.so* \ @@ -33,17 +36,6 @@ quick-sharun \ /usr/bin/yad echo 'unset VK_DRIVER_FILES' >> ./AppDir/.env -# Fix python symlinks to point to 3.11 which has the stdlib bundled -rm -f ./AppDir/shared/bin/python ./AppDir/shared/bin/python3 -ln -s python3.11 ./AppDir/shared/bin/python -ln -s python3.11 ./AppDir/shared/bin/python3 - -# Install protontricks and its Python dependencies into the AppDir's Python 3.11 -SITE_PACKAGES="$PWD/AppDir/lib/python3.11/site-packages" -python3.11 -m venv /tmp/protontricks-venv -/tmp/protontricks-venv/bin/pip install --target="$SITE_PACKAGES" --no-deps vdf Pillow -rsync -a --exclude='data/appimage' "$PWD/../../" "$SITE_PACKAGES/protontricks/" -rm -rf /tmp/protontricks-venv cc -shared -fPIC -O2 -o ./AppDir/lib/execve-sharun-hack.so execve-sharun-hack.c -ldl echo 'execve-sharun-hack.so' >> ./AppDir/.preload diff --git a/src/protontricks/data/share/applications/protontricks-launch.desktop b/src/protontricks/data/share/applications/protontricks-launch.desktop index 66cac55..ed9070d 100644 --- a/src/protontricks/data/share/applications/protontricks-launch.desktop +++ b/src/protontricks/data/share/applications/protontricks-launch.desktop @@ -5,5 +5,6 @@ Type=Application Terminal=false NoDisplay=true Categories=Utility +StartupWMClass=yad Icon=com.github.Matoking.protontricks MimeType=application/x-ms-dos-executable;application/x-msi;application/x-ms-shortcut; diff --git a/src/protontricks/data/share/applications/protontricks.desktop b/src/protontricks/data/share/applications/protontricks.desktop index bfd53c7..e3e2de0 100644 --- a/src/protontricks/data/share/applications/protontricks.desktop +++ b/src/protontricks/data/share/applications/protontricks.desktop @@ -5,5 +5,6 @@ Comment=A simple wrapper that does winetricks things for Proton enabled games Type=Application Terminal=false Categories=Utility; +StartupWMClass=yad Icon=com.github.Matoking.protontricks Keywords=Steam;Proton;Wine;Winetricks; From cbdab6ee6e94b6a83e5a4ec558217c46cabb130c Mon Sep 17 00:00:00 2001 From: Fatih Bakal Date: Fri, 26 Jun 2026 20:50:59 +0300 Subject: [PATCH 05/13] update actions versions a bit, fix error related to root --- .github/workflows/appimage.yml | 3 +-- .github/workflows/appstream.yml | 2 +- .github/workflows/tests.yml | 6 ++--- .../data/appimage/get-dependencies.sh | 24 ------------------- .../data/appimage/make-appimage.sh | 21 +++++++++------- .../data/appimage/src/protontricks | 1 + 6 files changed, 19 insertions(+), 38 deletions(-) delete mode 100755 src/protontricks/data/appimage/get-dependencies.sh create mode 160000 src/protontricks/data/appimage/src/protontricks diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 3e8f550..ac0b389 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -61,8 +61,7 @@ jobs: ls -lh cd src/protontricks/data/appimage pacman --noconfirm -U ./*.pkg.tar.zst - chmod +x ./get-dependencies.sh ./make-appimage.sh - ./get-dependencies.sh + chmod +x ./make-appimage.sh ./make-appimage.sh - name: Upload build artifacts diff --git a/.github/workflows/appstream.yml b/.github/workflows/appstream.yml index fb26a35..30d4690 100644 --- a/.github/workflows/appstream.yml +++ b/.github/workflows/appstream.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Install appstreamcli run: sudo apt install appstream diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bae4ee0..593b891 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,15 +9,15 @@ permissions: read-all jobs: test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: matrix: python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/src/protontricks/data/appimage/get-dependencies.sh b/src/protontricks/data/appimage/get-dependencies.sh deleted file mode 100755 index 19958b1..0000000 --- a/src/protontricks/data/appimage/get-dependencies.sh +++ /dev/null @@ -1,24 +0,0 @@ - -#!/bin/sh - -set -eu - -ARCH=$(uname -m) - -DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" -wget --retry-connrefused --tries=30 "$DEBLOATED_PKGS" -O ./get-debloated-pkgs - -chmod +x ./get-debloated-pkgs - -echo "Installing package dependencies..." -echo "---------------------------------------------------------------" -makepkg -p PKGBUILD-git -fsi --noconfirm - -echo "Installing debloated packages..." -echo "---------------------------------------------------------------" -./get-debloated-pkgs --add-common --prefer-nano - -# Comment this out if you need an AUR package -#make-aur-package PACKAGENAME - -# If the application needs to be manually built that has to be done down here diff --git a/src/protontricks/data/appimage/make-appimage.sh b/src/protontricks/data/appimage/make-appimage.sh index 096f831..0ea3ecc 100755 --- a/src/protontricks/data/appimage/make-appimage.sh +++ b/src/protontricks/data/appimage/make-appimage.sh @@ -4,17 +4,11 @@ set -eu ARCH=$(uname -m) VERSION=$(pacman -Q protontricks | awk '{print $2; exit}') # example command to get version of application here +export ARCH VERSION SHARUN="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/quick-sharun.sh" +DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" -#Remove leftovers -rm -rf AppDir dist - -# ADD LIBRARIES -wget --retry-connrefused --tries=30 "$SHARUN" -O ./quick-sharun -chmod +x ./quick-sharun - -export ARCH VERSION #export APPDIR="$PWD/AppDir" export OUTPATH=./dist export ADD_HOOKS="self-updater.bg.hook" @@ -26,6 +20,17 @@ export DEPLOY_PYTHON=1 export DEPLOY_OPENGL=1 export DEPLOY_VULKAN=1 +#Remove leftovers +rm -rf AppDir dist + +# ADD LIBRARIES +wget --retry-connrefused --tries=30 "$SHARUN" -O ./quick-sharun +wget --retry-connrefused --tries=30 "$DEBLOATED_PKGS" -O ./get-debloated-pkgs +chmod +x ./quick-sharun ./get-debloated-pkgs + +# Debloated pkgs +./get-debloated-pkgs --add-common --prefer-nano + # Deploy dependencies ./quick-sharun \ /usr/bin/*tricks* \ diff --git a/src/protontricks/data/appimage/src/protontricks b/src/protontricks/data/appimage/src/protontricks new file mode 160000 index 0000000..ff6b842 --- /dev/null +++ b/src/protontricks/data/appimage/src/protontricks @@ -0,0 +1 @@ +Subproject commit ff6b842af937478803cfdf786ac6ddd64954b545 From d19c655a38674bed29fb643fea702c402314577a Mon Sep 17 00:00:00 2001 From: Fatih Bakal Date: Fri, 26 Jun 2026 21:04:30 +0300 Subject: [PATCH 06/13] Just revert it as it causes breakage for python 3.7 (idk if the project is being supported on that version) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 593b891..6fc4e16 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ permissions: read-all jobs: test: - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 strategy: matrix: python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] From f1b49b24311ccc180bc6961ba2027e41f4840d88 Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:22:34 +0300 Subject: [PATCH 07/13] fix? --- src/protontricks/data/appimage/PKGBUILD-git | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protontricks/data/appimage/PKGBUILD-git b/src/protontricks/data/appimage/PKGBUILD-git index bf21839..a60fa18 100644 --- a/src/protontricks/data/appimage/PKGBUILD-git +++ b/src/protontricks/data/appimage/PKGBUILD-git @@ -30,7 +30,7 @@ makedepends=( ) checkdepends=('python-pytest') -source=("git+$url.git#branch=appimage") +source=("$pkgname::git+$url.git#branch=appimage") b2sums=('SKIP') build() { From 20e63e18ba8062c5e171af994956e895a5bd750e Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:29:40 +0300 Subject: [PATCH 08/13] Just add the env var --- src/protontricks/data/appimage/PKGBUILD-git | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/protontricks/data/appimage/PKGBUILD-git b/src/protontricks/data/appimage/PKGBUILD-git index a60fa18..a7a108c 100644 --- a/src/protontricks/data/appimage/PKGBUILD-git +++ b/src/protontricks/data/appimage/PKGBUILD-git @@ -30,7 +30,8 @@ makedepends=( ) checkdepends=('python-pytest') -source=("$pkgname::git+$url.git#branch=appimage") +export GIT_DISCOVERY_ACROSS_FILESYSTEM=1 +source=("git+$url.git#branch=appimage") b2sums=('SKIP') build() { From c1da8c70817d4e55fd44765a00478a961f162535 Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:36:11 +0300 Subject: [PATCH 09/13] try to fix (ill squash) --- src/protontricks/data/appimage/PKGBUILD-git | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/protontricks/data/appimage/PKGBUILD-git b/src/protontricks/data/appimage/PKGBUILD-git index a7a108c..471d13e 100644 --- a/src/protontricks/data/appimage/PKGBUILD-git +++ b/src/protontricks/data/appimage/PKGBUILD-git @@ -30,9 +30,12 @@ makedepends=( ) checkdepends=('python-pytest') -export GIT_DISCOVERY_ACROSS_FILESYSTEM=1 -source=("git+$url.git#branch=appimage") -b2sums=('SKIP') +source=() +b2sums=() + +prepare() { + git clone --depth 1 --branch appimage "$url.git" "$pkgname" +} build() { cd $pkgname From c501f6cabaca044d0c04c2007085911045382198 Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:48:31 +0300 Subject: [PATCH 10/13] Update appimage.yml --- .github/workflows/appimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index ac0b389..4fee5d3 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -68,7 +68,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: AppImage - path: "packaging/dist/*.AppImage" + path: "src/protontricks/data/appimage/dist/*.AppImage" archive: false - name: Create GitHub Release From 0154f7a3b5fadcf25d738f863bc8fdf2a6a0bd93 Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:48:51 +0300 Subject: [PATCH 11/13] Delete src/protontricks/data/appimage/src directory --- src/protontricks/data/appimage/src/protontricks | 1 - 1 file changed, 1 deletion(-) delete mode 160000 src/protontricks/data/appimage/src/protontricks diff --git a/src/protontricks/data/appimage/src/protontricks b/src/protontricks/data/appimage/src/protontricks deleted file mode 160000 index ff6b842..0000000 --- a/src/protontricks/data/appimage/src/protontricks +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ff6b842af937478803cfdf786ac6ddd64954b545 From 883c4c1d4ea5e79e92cbaaf50851f0e89b00750b Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:57:47 +0300 Subject: [PATCH 12/13] forgot about this one --- .github/workflows/appimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 4fee5d3..5a1af9b 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -77,7 +77,7 @@ jobs: with: tag_name: ${{ github.event.inputs.release_tag || github.ref_name }} name: ${{ github.event.inputs.release_tag || github.ref_name }} - files: "packaging/dist/*.AppImage" + files: "src/protontricks/data/appimage/dist/*.AppImage" generate_release_notes: true draft: false prerelease: ${{ github.event.inputs.prerelease == 'true' }} From fc089356af15d1fc3d6e61566f5c6d83c34fb811 Mon Sep 17 00:00:00 2001 From: Twig6943 <119701717+Twig6943@users.noreply.github.com> Date: Fri, 26 Jun 2026 22:05:05 +0300 Subject: [PATCH 13/13] Leftovers --- src/protontricks/data/appimage/make-appimage.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/protontricks/data/appimage/make-appimage.sh b/src/protontricks/data/appimage/make-appimage.sh index 0ea3ecc..ea062a9 100755 --- a/src/protontricks/data/appimage/make-appimage.sh +++ b/src/protontricks/data/appimage/make-appimage.sh @@ -9,10 +9,9 @@ export ARCH VERSION SHARUN="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/quick-sharun.sh" DEBLOATED_PKGS="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/get-debloated-pkgs.sh" -#export APPDIR="$PWD/AppDir" export OUTPATH=./dist export ADD_HOOKS="self-updater.bg.hook" -#export UPINFO="gh-releases-zsync|${GITHUB_REPOSITORY%/*}|${GITHUB_REPOSITORY#*/}|latest|*$ARCH.AppImage.zsync" +export UPINFO="gh-releases-zsync|${GITHUB_REPOSITORY%/*}|${GITHUB_REPOSITORY#*/}|latest|*$ARCH.AppImage.zsync" export ICON=/usr/share/icons/hicolor/scalable/apps/com.github.Matoking.protontricks.svg export DESKTOP=/usr/share/applications/protontricks.desktop export LIB_DIR=/usr/lib