mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Add self-contained release packaging for Linux, macOS, and Windows.
Resolve asset/progress paths for AppImage and .app bundles, and ship GitHub Actions builds on version tags. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f55216b764
commit
f8e27e8b53
10 changed files with 711 additions and 18 deletions
125
.github/workflows/release.yml
vendored
Normal file
125
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
name: Linux AppImage
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y \
|
||||||
|
build-essential pkg-config curl \
|
||||||
|
libgtk-4-dev librsvg2-dev \
|
||||||
|
desktop-file-utils \
|
||||||
|
appstream
|
||||||
|
|
||||||
|
- name: Build AppImage
|
||||||
|
env:
|
||||||
|
VERSION: ${{ github.ref_name }}
|
||||||
|
run: |
|
||||||
|
chmod +x scripts/bundle-linux.sh
|
||||||
|
./scripts/bundle-linux.sh
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: maturita-linux
|
||||||
|
path: dist/maturita-linux-*.AppImage
|
||||||
|
|
||||||
|
windows:
|
||||||
|
name: Windows zip
|
||||||
|
runs-on: windows-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: UCRT64
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
make
|
||||||
|
zip
|
||||||
|
mingw-w64-ucrt-x86_64-gcc
|
||||||
|
mingw-w64-ucrt-x86_64-gtk4
|
||||||
|
mingw-w64-ucrt-x86_64-pkg-config
|
||||||
|
mingw-w64-ucrt-x86_64-make
|
||||||
|
|
||||||
|
- name: Build and bundle
|
||||||
|
run: |
|
||||||
|
make bundle
|
||||||
|
cd dist
|
||||||
|
zip -qry ../maturita-windows-x64.zip .
|
||||||
|
cd ..
|
||||||
|
mkdir -p dist-out
|
||||||
|
mv maturita-windows-x64.zip dist-out/
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: maturita-windows
|
||||||
|
path: dist-out/maturita-windows-x64.zip
|
||||||
|
|
||||||
|
macos:
|
||||||
|
name: macOS app
|
||||||
|
runs-on: macos-14
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
brew install gtk4 pkg-config dylibbundler
|
||||||
|
|
||||||
|
- name: Build .app zip
|
||||||
|
env:
|
||||||
|
VERSION: ${{ github.ref_name }}
|
||||||
|
run: |
|
||||||
|
chmod +x scripts/bundle-macos.sh
|
||||||
|
./scripts/bundle-macos.sh
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: maturita-macos
|
||||||
|
path: dist/maturita-macos-*.zip
|
||||||
|
|
||||||
|
publish:
|
||||||
|
name: Publish GitHub Release
|
||||||
|
needs: [linux, windows, macos]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: release-assets
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: List assets
|
||||||
|
run: find release-assets -type f -print
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
release-assets/maturita-linux-*.AppImage
|
||||||
|
release-assets/maturita-windows-x64.zip
|
||||||
|
release-assets/maturita-macos-*.zip
|
||||||
|
generate_release_notes: true
|
||||||
|
fail_on_unmatched_files: true
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
15
Makefile
15
Makefile
|
|
@ -23,11 +23,13 @@ TARGET = maturita.exe
|
||||||
LIBS += -mwindows
|
LIBS += -mwindows
|
||||||
WINDRES ?= windres
|
WINDRES ?= windres
|
||||||
RC_OBJ = maturita_rc.o
|
RC_OBJ = maturita_rc.o
|
||||||
|
UNAME_S :=
|
||||||
else
|
else
|
||||||
TARGET = maturita
|
TARGET = maturita
|
||||||
RC_OBJ =
|
RC_OBJ =
|
||||||
|
UNAME_S := $(shell uname -s 2>/dev/null)
|
||||||
# macOS Dock icon is set via AppKit (see macos_dock.c).
|
# macOS Dock icon is set via AppKit (see macos_dock.c).
|
||||||
ifeq ($(shell uname -s 2>/dev/null),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
LIBS += -framework AppKit -framework Foundation
|
LIBS += -framework AppKit -framework Foundation
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
@ -62,9 +64,7 @@ clean:
|
||||||
run: $(TARGET)
|
run: $(TARGET)
|
||||||
./$(TARGET)
|
./$(TARGET)
|
||||||
|
|
||||||
# Windows only: copy the executable and every non-system (MinGW/GTK) DLL it
|
# Self-contained package for the current platform into dist/.
|
||||||
# needs into dist/ so the app can be started by double-clicking, without an
|
|
||||||
# MSYS2 shell on PATH.
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
bundle: $(TARGET)
|
bundle: $(TARGET)
|
||||||
@rm -rf dist
|
@rm -rf dist
|
||||||
|
|
@ -77,9 +77,14 @@ bundle: $(TARGET)
|
||||||
@ldd $(TARGET) | grep -Ei '/(ucrt64|mingw64)/bin/' | awk '{print $$3}' \
|
@ldd $(TARGET) | grep -Ei '/(ucrt64|mingw64)/bin/' | awk '{print $$3}' \
|
||||||
| xargs -r -I{} cp -f {} dist/
|
| xargs -r -I{} cp -f {} dist/
|
||||||
@echo "Bundled into dist/ - run dist/$(TARGET)"
|
@echo "Bundled into dist/ - run dist/$(TARGET)"
|
||||||
|
else ifeq ($(UNAME_S),Darwin)
|
||||||
|
bundle:
|
||||||
|
@chmod +x scripts/bundle-macos.sh
|
||||||
|
@./scripts/bundle-macos.sh
|
||||||
else
|
else
|
||||||
bundle:
|
bundle:
|
||||||
@echo "make bundle is only needed on Windows (MSYS2/MinGW)."
|
@chmod +x scripts/bundle-linux.sh
|
||||||
|
@./scripts/bundle-linux.sh
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all clean run bundle
|
.PHONY: all clean run bundle
|
||||||
|
|
|
||||||
67
README.md
67
README.md
|
|
@ -123,6 +123,35 @@ GTK 4 interface.
|
||||||
- **Keyboard quit shortcuts** – `Super/Cmd+Q` or `Alt+F4` closes the app
|
- **Keyboard quit shortcuts** – `Super/Cmd+Q` or `Alt+F4` closes the app
|
||||||
- Modular C codebase split across several files, cross-platform (Linux, macOS and Windows)
|
- Modular C codebase split across several files, cross-platform (Linux, macOS and Windows)
|
||||||
|
|
||||||
|
### Downloads (prebuilt)
|
||||||
|
|
||||||
|
Precompiled, self-contained builds are published on the
|
||||||
|
**GitHub Releases** page of this project (enable Actions on a GitHub remote)
|
||||||
|
when a version tag (`v*`) is pushed. No compiler or GTK development packages
|
||||||
|
are required:
|
||||||
|
|
||||||
|
| Platform | Asset | How to run |
|
||||||
|
| -------- | ----- | ---------- |
|
||||||
|
| Linux (x86_64) | `maturita-linux-x86_64.AppImage` | `chmod +x` the file, then double-click or run it |
|
||||||
|
| macOS (Apple Silicon) | `maturita-macos-arm64.zip` | Unzip and open `Maturita.app` |
|
||||||
|
| Windows (x64) | `maturita-windows-x64.zip` | Unzip and run `maturita.exe` |
|
||||||
|
|
||||||
|
Progress and settings are saved next to the AppImage / `.app` / unzipped
|
||||||
|
folder in a `progress/` directory.
|
||||||
|
|
||||||
|
To cut a release yourself (needs a GitHub remote with Actions enabled):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag v1.0.0
|
||||||
|
git push origin v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
Local packaging (same scripts the CI uses):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make bundle # Linux AppImage, macOS .app zip, or Windows DLL folder
|
||||||
|
```
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
@ -373,7 +402,10 @@ hw.c computer-hardware path (10 nodes), units 1–3 slides
|
||||||
and quizzes (architecture, history, bit/byte)
|
and quizzes (architecture, history, bit/byte)
|
||||||
main.c application entry point and page wiring
|
main.c application entry point and page wiring
|
||||||
style.css GTK stylesheet (palette colors are injected at runtime)
|
style.css GTK stylesheet (palette colors are injected at runtime)
|
||||||
Makefile build & run targets (Linux, macOS, MSYS2); `make bundle` on Windows
|
Makefile build & run targets (Linux, macOS, MSYS2); `make bundle` packs a release
|
||||||
|
scripts/bundle-linux.sh Linux AppImage (linuxdeploy + GTK plugin)
|
||||||
|
scripts/bundle-macos.sh macOS Maturita.app with relocated GTK dylibs
|
||||||
|
.github/workflows/ GitHub Actions release on tag `v*`
|
||||||
CMakeLists.txt optional CMake build (Linux / macOS)
|
CMakeLists.txt optional CMake build (Linux / macOS)
|
||||||
build-windows.bat legacy MSVC build (requires Visual Studio + gvsbuild GTK)
|
build-windows.bat legacy MSVC build (requires Visual Studio + gvsbuild GTK)
|
||||||
run-windows.bat legacy launcher for the MSVC build with GTK DLLs on PATH
|
run-windows.bat legacy launcher for the MSVC build with GTK DLLs on PATH
|
||||||
|
|
@ -553,6 +585,34 @@ moderním GTK 4 rozhraním stylovaným přes CSS.
|
||||||
- **Klávesové zkratky pro ukončení** – `Super/Cmd+Q` nebo `Alt+F4`
|
- **Klávesové zkratky pro ukončení** – `Super/Cmd+Q` nebo `Alt+F4`
|
||||||
- Modulární C kód v několika souborech, multiplatformní (Linux, macOS i Windows)
|
- Modulární C kód v několika souborech, multiplatformní (Linux, macOS i Windows)
|
||||||
|
|
||||||
|
### Stažení (předkompilované)
|
||||||
|
|
||||||
|
Hotové self-contained buildy vycházejí na stránce
|
||||||
|
**GitHub Releases** tohoto projektu (Actions na GitHub remote)
|
||||||
|
při pushi tagu `v*`. Kompilátor ani vývojové balíčky GTK nejsou potřeba:
|
||||||
|
|
||||||
|
| Platforma | Soubor | Spuštění |
|
||||||
|
| --------- | ------ | -------- |
|
||||||
|
| Linux (x86_64) | `maturita-linux-x86_64.AppImage` | `chmod +x` a spustit / dvojklik |
|
||||||
|
| macOS (Apple Silicon) | `maturita-macos-arm64.zip` | Rozbalit a otevřít `Maturita.app` |
|
||||||
|
| Windows (x64) | `maturita-windows-x64.zip` | Rozbalit a spustit `maturita.exe` |
|
||||||
|
|
||||||
|
Postup a nastavení se ukládají vedle AppImage / `.app` / rozbalené složky
|
||||||
|
do adresáře `progress/`.
|
||||||
|
|
||||||
|
Vytvoření releasu (GitHub remote s Actions):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag v1.0.0
|
||||||
|
git push origin v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
Lokální balíček (stejné skripty jako CI):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make bundle # Linux AppImage, macOS .app zip, nebo Windows složka s DLL
|
||||||
|
```
|
||||||
|
|
||||||
### Instalace
|
### Instalace
|
||||||
|
|
||||||
#### Požadavky
|
#### Požadavky
|
||||||
|
|
@ -800,7 +860,10 @@ hw.c cesta technického vybavení (10 uzlů), jednotky 1–3
|
||||||
(architektura, historie, bit/byte + kvízy)
|
(architektura, historie, bit/byte + kvízy)
|
||||||
main.c vstupní bod aplikace a zapojení stránek
|
main.c vstupní bod aplikace a zapojení stránek
|
||||||
style.css GTK styl (barvy palety se vkládají za běhu)
|
style.css GTK styl (barvy palety se vkládají za běhu)
|
||||||
Makefile build & run (Linux, macOS, MSYS2); `make bundle` na Windows
|
Makefile build & run (Linux, macOS, MSYS2); `make bundle` vytvoří release balíček
|
||||||
|
scripts/bundle-linux.sh Linux AppImage (linuxdeploy + GTK plugin)
|
||||||
|
scripts/bundle-macos.sh macOS Maturita.app s přbalenými GTK dylibs
|
||||||
|
.github/workflows/ GitHub Actions release při tagu `v*`
|
||||||
CMakeLists.txt volitelný CMake build (Linux / macOS)
|
CMakeLists.txt volitelný CMake build (Linux / macOS)
|
||||||
build-windows.bat legacy MSVC build (vyžaduje Visual Studio + gvsbuild GTK)
|
build-windows.bat legacy MSVC build (vyžaduje Visual Studio + gvsbuild GTK)
|
||||||
run-windows.bat legacy spouštění MSVC buildu s GTK DLL na PATH
|
run-windows.bat legacy spouštění MSVC buildu s GTK DLL na PATH
|
||||||
|
|
|
||||||
4
cetba.c
4
cetba.c
|
|
@ -1090,7 +1090,7 @@ static UnitCtx lit_plot_unit;
|
||||||
|
|
||||||
GtkWidget *build_cetba1984_plot_page(void) {
|
GtkWidget *build_cetba1984_plot_page(void) {
|
||||||
lit_plot_unit.page = "cetba1984";
|
lit_plot_unit.page = "cetba1984";
|
||||||
lit_plot_unit.progress_file = "progress/cetba.conf";
|
lit_plot_unit.progress_file = app_progress_cetba;
|
||||||
return build_assembly(&lit_plot_unit, tr("lit_plot_title"),
|
return build_assembly(&lit_plot_unit, tr("lit_plot_title"),
|
||||||
"lit_plot_sub", 1, lit_plot_items,
|
"lit_plot_sub", 1, lit_plot_items,
|
||||||
lit_plot_meaning, 1);
|
lit_plot_meaning, 1);
|
||||||
|
|
@ -1119,7 +1119,7 @@ static const char *fuks_plot_meaning[] = {
|
||||||
|
|
||||||
GtkWidget *build_cetba_fuks_plot_page(void) {
|
GtkWidget *build_cetba_fuks_plot_page(void) {
|
||||||
lit_plot_unit.page = "cetbaFuks";
|
lit_plot_unit.page = "cetbaFuks";
|
||||||
lit_plot_unit.progress_file = "progress/cetba.conf";
|
lit_plot_unit.progress_file = app_progress_cetba;
|
||||||
return build_assembly(&lit_plot_unit, tr("lit_fuks_plot_title"),
|
return build_assembly(&lit_plot_unit, tr("lit_fuks_plot_title"),
|
||||||
"lit_fuks_plot_sub", 1, fuks_plot_items,
|
"lit_fuks_plot_sub", 1, fuks_plot_items,
|
||||||
fuks_plot_meaning, 1);
|
fuks_plot_meaning, 1);
|
||||||
|
|
|
||||||
4
main.c
4
main.c
|
|
@ -476,6 +476,10 @@ int main(int argc, char **argv) {
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
/* Resolve style.css / icons next to the binary (or AppImage / .app) and
|
||||||
|
* point progress files at a writable location before any I/O. */
|
||||||
|
setup_portable_paths();
|
||||||
|
|
||||||
/* Must run before GtkApplication so Wayland can resolve our .desktop
|
/* Must run before GtkApplication so Wayland can resolve our .desktop
|
||||||
* file / icons via the application id. */
|
* file / icons via the application id. */
|
||||||
setup_portable_share_dir();
|
setup_portable_share_dir();
|
||||||
|
|
|
||||||
26
maturita.h
26
maturita.h
|
|
@ -22,13 +22,24 @@
|
||||||
#define ICON_THEME_DIR_ALT "icons" /* next to the binary after install */
|
#define ICON_THEME_DIR_ALT "icons" /* next to the binary after install */
|
||||||
#define ICON_FILE_ALT "icons/hicolor/512x512/apps/maturita.png"
|
#define ICON_FILE_ALT "icons/hicolor/512x512/apps/maturita.png"
|
||||||
#define SHARE_DIR "share" /* portable Freedesktop data root */
|
#define SHARE_DIR "share" /* portable Freedesktop data root */
|
||||||
#define PROGRESS_DIR "progress"
|
/* Relative leaf names; absolute paths are filled by setup_portable_paths(). */
|
||||||
#define PROGRESS_U1 "progress/unit1.conf"
|
#define PROGRESS_DIR_NAME "progress"
|
||||||
#define PROGRESS_U2 "progress/unit2.conf"
|
extern char *app_progress_dir;
|
||||||
#define PROGRESS_U3 "progress/unit3.conf"
|
extern char *app_progress_u1;
|
||||||
#define SETTINGS_FILE "progress/settings.conf"
|
extern char *app_progress_u2;
|
||||||
#define PROGRESS_NET "progress/net.conf"
|
extern char *app_progress_u3;
|
||||||
#define PROGRESS_HW "progress/hw.conf"
|
extern char *app_settings_file;
|
||||||
|
extern char *app_progress_net;
|
||||||
|
extern char *app_progress_hw;
|
||||||
|
extern char *app_progress_mluvnice;
|
||||||
|
extern char *app_progress_cetba;
|
||||||
|
#define PROGRESS_DIR app_progress_dir
|
||||||
|
#define PROGRESS_U1 app_progress_u1
|
||||||
|
#define PROGRESS_U2 app_progress_u2
|
||||||
|
#define PROGRESS_U3 app_progress_u3
|
||||||
|
#define SETTINGS_FILE app_settings_file
|
||||||
|
#define PROGRESS_NET app_progress_net
|
||||||
|
#define PROGRESS_HW app_progress_hw
|
||||||
#define NODE_SIZE 88.0
|
#define NODE_SIZE 88.0
|
||||||
#define PATH_SPAC 240.0
|
#define PATH_SPAC 240.0
|
||||||
#define ROAD_MX 150.0 /* horizontal canvas margin */
|
#define ROAD_MX 150.0 /* horizontal canvas margin */
|
||||||
|
|
@ -779,6 +790,7 @@ void draw_stats_icon(GtkDrawingArea *area, cairo_t *cr,
|
||||||
int width, int height, gpointer data);
|
int width, int height, gpointer data);
|
||||||
GtkWidget *icon_area_new(GtkDrawingAreaDrawFunc fn,
|
GtkWidget *icon_area_new(GtkDrawingAreaDrawFunc fn,
|
||||||
double r, double g, double b, int px);
|
double r, double g, double b, int px);
|
||||||
|
void setup_portable_paths(void);
|
||||||
char *normalize_answer(const char *input);
|
char *normalize_answer(const char *input);
|
||||||
void shuffle_indices(int *arr, int n);
|
void shuffle_indices(int *arr, int n);
|
||||||
void flow_clear(GtkFlowBox *fb);
|
void flow_clear(GtkFlowBox *fb);
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ void mluvnice_init(void) {
|
||||||
mluv_unit.sub_key = "Cvičení z mluvnice – styl maturita / "
|
mluv_unit.sub_key = "Cvičení z mluvnice – styl maturita / "
|
||||||
"přijímačky z ČJL";
|
"přijímačky z ČJL";
|
||||||
mluv_unit.back_target = "czechmap";
|
mluv_unit.back_target = "czechmap";
|
||||||
mluv_unit.progress_file = "progress/mluvnice.conf";
|
mluv_unit.progress_file = app_progress_mluvnice;
|
||||||
mluv_unit.n_ex = MLUV_N_EX;
|
mluv_unit.n_ex = MLUV_N_EX;
|
||||||
for (int i = 0; i < MLUV_N_EX; i++)
|
for (int i = 0; i < MLUV_N_EX; i++)
|
||||||
mluv_unit.ex_names[i + 1] = mluv_names[i];
|
mluv_unit.ex_names[i + 1] = mluv_names[i];
|
||||||
|
|
|
||||||
116
scripts/bundle-linux.sh
Executable file
116
scripts/bundle-linux.sh
Executable file
|
|
@ -0,0 +1,116 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build a self-contained Linux AppImage (x86_64).
|
||||||
|
# Requires: make, pkg-config, GTK4, curl, and fuse/appimagetool (pulled as needed).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64|amd64) ARCH=x86_64 ;;
|
||||||
|
aarch64|arm64) ARCH=aarch64 ;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported architecture: $ARCH" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
OUT_NAME="maturita-linux-${ARCH}.AppImage"
|
||||||
|
APPDIR="$ROOT/dist/AppDir"
|
||||||
|
TOOLS="$ROOT/dist/tools"
|
||||||
|
ICON_DST="assets/icons/hicolor/512x512/apps/maturita.png"
|
||||||
|
|
||||||
|
echo "==> Building maturita"
|
||||||
|
make -C "$ROOT" clean
|
||||||
|
make -C "$ROOT"
|
||||||
|
|
||||||
|
echo "==> Preparing AppDir"
|
||||||
|
rm -rf "$APPDIR"
|
||||||
|
mkdir -p "$APPDIR/usr/bin" \
|
||||||
|
"$APPDIR/usr/share/applications" \
|
||||||
|
"$APPDIR/usr/share/icons/hicolor/512x512/apps" \
|
||||||
|
"$APPDIR/icons/hicolor/512x512/apps" \
|
||||||
|
"$APPDIR/share"
|
||||||
|
|
||||||
|
cp -f "$ROOT/maturita" "$APPDIR/usr/bin/maturita"
|
||||||
|
cp -f "$ROOT/style.css" "$APPDIR/style.css"
|
||||||
|
cp -f "$ROOT/$ICON_DST" "$APPDIR/icons/hicolor/512x512/apps/maturita.png"
|
||||||
|
cp -f "$ROOT/$ICON_DST" "$APPDIR/usr/share/icons/hicolor/512x512/apps/maturita.png"
|
||||||
|
cp -f "$ROOT/$ICON_DST" "$APPDIR/maturita.png"
|
||||||
|
cp -R "$ROOT/share/." "$APPDIR/share/"
|
||||||
|
cp -R "$ROOT/share/." "$APPDIR/usr/share/"
|
||||||
|
cp -f "$ROOT/share/applications/org.maturita.Maturita.desktop" \
|
||||||
|
"$APPDIR/usr/share/applications/org.maturita.Maturita.desktop"
|
||||||
|
# AppImage desktop entry must live at AppDir root and Exec= must be AppRun-compatible.
|
||||||
|
cp -f "$ROOT/share/applications/org.maturita.Maturita.desktop" \
|
||||||
|
"$APPDIR/org.maturita.Maturita.desktop"
|
||||||
|
# linuxdeploy expects Icon= without path and a matching PNG at AppDir root.
|
||||||
|
sed -i.bak 's|^Exec=.*|Exec=maturita|' "$APPDIR/org.maturita.Maturita.desktop"
|
||||||
|
sed -i.bak 's|^Icon=.*|Icon=maturita|' "$APPDIR/org.maturita.Maturita.desktop"
|
||||||
|
rm -f "$APPDIR/org.maturita.Maturita.desktop.bak"
|
||||||
|
|
||||||
|
mkdir -p "$TOOLS"
|
||||||
|
LINUXDEPLOY="$TOOLS/linuxdeploy-${ARCH}.AppImage"
|
||||||
|
GTK_PLUGIN="$TOOLS/linuxdeploy-plugin-gtk.sh"
|
||||||
|
|
||||||
|
if [[ ! -x "$LINUXDEPLOY" ]]; then
|
||||||
|
echo "==> Downloading linuxdeploy"
|
||||||
|
curl -fsSL -o "$LINUXDEPLOY" \
|
||||||
|
"https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${ARCH}.AppImage"
|
||||||
|
chmod +x "$LINUXDEPLOY"
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$GTK_PLUGIN" ]]; then
|
||||||
|
echo "==> Downloading linuxdeploy-plugin-gtk"
|
||||||
|
curl -fsSL -o "$GTK_PLUGIN" \
|
||||||
|
"https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh"
|
||||||
|
chmod +x "$GTK_PLUGIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract linuxdeploy if FUSE is unavailable (common on CI).
|
||||||
|
run_linuxdeploy() {
|
||||||
|
if "$LINUXDEPLOY" --appimage-help >/dev/null 2>&1; then
|
||||||
|
"$LINUXDEPLOY" "$@"
|
||||||
|
else
|
||||||
|
local extract_dir="$TOOLS/linuxdeploy-extracted"
|
||||||
|
rm -rf "$extract_dir"
|
||||||
|
cd "$TOOLS"
|
||||||
|
"$LINUXDEPLOY" --appimage-extract >/dev/null
|
||||||
|
mv squashfs-root "$extract_dir"
|
||||||
|
cd "$ROOT"
|
||||||
|
"$extract_dir/AppRun" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "==> Bundling GTK libraries into AppDir"
|
||||||
|
export LDAI_OUTPUT="$ROOT/dist/$OUT_NAME"
|
||||||
|
export LINUXDEPLOY_OUTPUT_VERSION="${VERSION:-continuous}"
|
||||||
|
# Place plugin on PATH so linuxdeploy can find it.
|
||||||
|
export PATH="$TOOLS:$PATH"
|
||||||
|
cp -f "$GTK_PLUGIN" "$TOOLS/linuxdeploy-plugin-gtk.sh"
|
||||||
|
|
||||||
|
run_linuxdeploy \
|
||||||
|
--appdir "$APPDIR" \
|
||||||
|
--executable "$APPDIR/usr/bin/maturita" \
|
||||||
|
--desktop-file "$APPDIR/org.maturita.Maturita.desktop" \
|
||||||
|
--icon-file "$APPDIR/maturita.png" \
|
||||||
|
--plugin gtk \
|
||||||
|
--output appimage
|
||||||
|
|
||||||
|
# linuxdeploy may write the AppImage into the cwd; normalise the name/location.
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$ROOT"/*.AppImage "$ROOT/dist"/*.AppImage; do
|
||||||
|
case "$(basename "$f")" in
|
||||||
|
linuxdeploy*|appimagetool*) continue ;;
|
||||||
|
esac
|
||||||
|
mv -f "$f" "$ROOT/dist/$OUT_NAME"
|
||||||
|
done
|
||||||
|
shopt -u nullglob
|
||||||
|
|
||||||
|
if [[ ! -f "$ROOT/dist/$OUT_NAME" ]]; then
|
||||||
|
echo "AppImage was not created" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod +x "$ROOT/dist/$OUT_NAME"
|
||||||
|
echo "Created dist/$OUT_NAME"
|
||||||
169
scripts/bundle-macos.sh
Executable file
169
scripts/bundle-macos.sh
Executable file
|
|
@ -0,0 +1,169 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build a self-contained macOS .app with GTK dylibs relocated into the bundle.
|
||||||
|
# Requires: make, pkg-config, GTK4 (Homebrew), dylibbundler (brew install dylibbundler).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$ARCH" in
|
||||||
|
arm64|aarch64) ARCH_TAG=arm64 ;;
|
||||||
|
x86_64) ARCH_TAG=x86_64 ;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported architecture: $ARCH" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
APP_NAME="Maturita.app"
|
||||||
|
APP="$ROOT/dist/$APP_NAME"
|
||||||
|
MACOS="$APP/Contents/MacOS"
|
||||||
|
RES="$APP/Contents/Resources"
|
||||||
|
FW="$APP/Contents/Frameworks"
|
||||||
|
ICON_DST="assets/icons/hicolor/512x512/apps/maturita.png"
|
||||||
|
OUT_ZIP="maturita-macos-${ARCH_TAG}.zip"
|
||||||
|
|
||||||
|
if ! command -v dylibbundler >/dev/null 2>&1; then
|
||||||
|
echo "dylibbundler not found. Install with: brew install dylibbundler" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Building maturita"
|
||||||
|
make -C "$ROOT" clean
|
||||||
|
make -C "$ROOT"
|
||||||
|
|
||||||
|
echo "==> Creating $APP_NAME"
|
||||||
|
rm -rf "$APP"
|
||||||
|
mkdir -p "$MACOS" "$RES/icons/hicolor/512x512/apps" "$RES/share" "$FW"
|
||||||
|
|
||||||
|
cp -f "$ROOT/maturita" "$MACOS/maturita-bin"
|
||||||
|
cp -f "$ROOT/style.css" "$RES/style.css"
|
||||||
|
cp -f "$ROOT/$ICON_DST" "$RES/icons/hicolor/512x512/apps/maturita.png"
|
||||||
|
cp -R "$ROOT/share/." "$RES/share/"
|
||||||
|
|
||||||
|
# Bundle Homebrew / MacPorts GTK stack next to the binary.
|
||||||
|
echo "==> Relocating dylibs with dylibbundler"
|
||||||
|
dylibbundler -od -b \
|
||||||
|
-x "$MACOS/maturita-bin" \
|
||||||
|
-d "$FW" \
|
||||||
|
-p "@executable_path/../Frameworks"
|
||||||
|
|
||||||
|
# Copy GLib / GTK runtime data (schemas, modules, icons themes used by GTK).
|
||||||
|
copy_pkg_share() {
|
||||||
|
local prefix
|
||||||
|
prefix="$(pkg-config --variable=prefix "$1" 2>/dev/null || true)"
|
||||||
|
[[ -n "$prefix" && -d "$prefix/share" ]] || return 0
|
||||||
|
mkdir -p "$RES/share"
|
||||||
|
# Copy only the subtrees GTK needs at runtime.
|
||||||
|
for sub in glib-2.0 gtk-4.0 icons themes locale; do
|
||||||
|
if [[ -d "$prefix/share/$sub" ]]; then
|
||||||
|
rsync -a "$prefix/share/$sub" "$RES/share/" 2>/dev/null \
|
||||||
|
|| cp -R "$prefix/share/$sub" "$RES/share/"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_pkg_share gtk4
|
||||||
|
copy_pkg_share glib-2.0
|
||||||
|
|
||||||
|
# gdk-pixbuf loaders (PNG may be built-in; copy others for GIF/SVG/etc.).
|
||||||
|
PIXBUF_DIR="$(pkg-config --variable=gdk_pixbuf_moduledir gdk-pixbuf-2.0 2>/dev/null || true)"
|
||||||
|
LOADERS_DST="$RES/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||||
|
if [[ -n "$PIXBUF_DIR" && -d "$PIXBUF_DIR" ]]; then
|
||||||
|
mkdir -p "$LOADERS_DST"
|
||||||
|
# Homebrew keeps loaders as relative symlinks into Cellar — dereference.
|
||||||
|
if command -v rsync >/dev/null 2>&1; then
|
||||||
|
rsync -aL "$PIXBUF_DIR"/ "$LOADERS_DST"/
|
||||||
|
else
|
||||||
|
cp -R -L "$PIXBUF_DIR"/. "$LOADERS_DST"/
|
||||||
|
fi
|
||||||
|
# Drop broken leftovers and relocate real loader modules.
|
||||||
|
find "$LOADERS_DST" -type l ! -exec test -e {} \; -delete 2>/dev/null || true
|
||||||
|
shopt -s nullglob
|
||||||
|
for loader in "$LOADERS_DST"/*; do
|
||||||
|
[[ -f "$loader" ]] || continue
|
||||||
|
dylibbundler -od -b -x "$loader" -d "$FW" -p "@executable_path/../Frameworks" || true
|
||||||
|
done
|
||||||
|
shopt -u nullglob
|
||||||
|
if command -v gdk-pixbuf-query-loaders >/dev/null 2>&1; then
|
||||||
|
export GDK_PIXBUF_MODULEDIR="$LOADERS_DST"
|
||||||
|
gdk-pixbuf-query-loaders > "$RES/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compile GSettings schemas if glib-compile-schemas is available.
|
||||||
|
if [[ -d "$RES/share/glib-2.0/schemas" ]] && command -v glib-compile-schemas >/dev/null 2>&1; then
|
||||||
|
glib-compile-schemas "$RES/share/glib-2.0/schemas" || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Launcher sets GTK search paths then execs the real binary.
|
||||||
|
cat > "$MACOS/maturita" <<'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
export DYLD_LIBRARY_PATH="$ROOT/Frameworks${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
|
||||||
|
export XDG_DATA_DIRS="$ROOT/Resources/share${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"
|
||||||
|
export GSETTINGS_SCHEMA_DIR="$ROOT/Resources/share/glib-2.0/schemas"
|
||||||
|
export GDK_PIXBUF_MODULEDIR="$ROOT/Resources/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||||
|
if [[ -f "$ROOT/Resources/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" ]]; then
|
||||||
|
export GDK_PIXBUF_MODULE_FILE="$ROOT/Resources/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
||||||
|
fi
|
||||||
|
export GTK_DATA_PREFIX="$ROOT/Resources"
|
||||||
|
export GTK_EXE_PREFIX="$ROOT"
|
||||||
|
# Adwaita / hicolor icons for GTK widgets.
|
||||||
|
export XDG_DATA_HOME="$ROOT/Resources"
|
||||||
|
exec "$ROOT/MacOS/maturita-bin" "$@"
|
||||||
|
EOF
|
||||||
|
chmod +x "$MACOS/maturita"
|
||||||
|
|
||||||
|
# Info.plist
|
||||||
|
cat > "$APP/Contents/Info.plist" <<EOF
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>maturita.c</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>maturita.c</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.maturita.Maturita</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>${VERSION:-1.0}</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>${VERSION:-1.0}</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>maturita</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>AppIcon</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Optional .icns from PNG if iconutil / sips available.
|
||||||
|
if command -v sips >/dev/null 2>&1 && command -v iconutil >/dev/null 2>&1; then
|
||||||
|
ICONSET="$RES/AppIcon.iconset"
|
||||||
|
mkdir -p "$ICONSET"
|
||||||
|
for sz in 16 32 64 128 256 512; do
|
||||||
|
sips -z "$sz" "$sz" "$ROOT/$ICON_DST" --out "$ICONSET/icon_${sz}x${sz}.png" >/dev/null
|
||||||
|
sips -z $((sz * 2)) $((sz * 2)) "$ROOT/$ICON_DST" \
|
||||||
|
--out "$ICONSET/icon_${sz}x${sz}@2x.png" >/dev/null
|
||||||
|
done
|
||||||
|
iconutil -c icns -o "$RES/AppIcon.icns" "$ICONSET" && rm -rf "$ICONSET" || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Zipping"
|
||||||
|
rm -f "$ROOT/dist/$OUT_ZIP"
|
||||||
|
(
|
||||||
|
cd "$ROOT/dist"
|
||||||
|
zip -qry "$OUT_ZIP" "$APP_NAME"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Created dist/$OUT_ZIP"
|
||||||
201
util.c
201
util.c
|
|
@ -1,9 +1,208 @@
|
||||||
#include "maturita.h"
|
#include "maturita.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Utilities */
|
/* Portable data / progress paths */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
char *app_progress_dir;
|
||||||
|
char *app_progress_u1;
|
||||||
|
char *app_progress_u2;
|
||||||
|
char *app_progress_u3;
|
||||||
|
char *app_settings_file;
|
||||||
|
char *app_progress_net;
|
||||||
|
char *app_progress_hw;
|
||||||
|
char *app_progress_mluvnice;
|
||||||
|
char *app_progress_cetba;
|
||||||
|
|
||||||
|
static char *dup_dirname(const char *path) {
|
||||||
|
char *tmp = g_strdup(path);
|
||||||
|
char *dir;
|
||||||
|
|
||||||
|
if (!tmp)
|
||||||
|
return NULL;
|
||||||
|
dir = g_path_get_dirname(tmp);
|
||||||
|
g_free(tmp);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Absolute path of this process's executable, or NULL. */
|
||||||
|
static char *executable_path(void) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
wchar_t wbuf[MAX_PATH];
|
||||||
|
DWORD n = GetModuleFileNameW(NULL, wbuf, MAX_PATH);
|
||||||
|
char *out;
|
||||||
|
|
||||||
|
if (n == 0 || n >= MAX_PATH)
|
||||||
|
return NULL;
|
||||||
|
out = g_utf16_to_utf8((const gunichar2 *)wbuf, -1, NULL, NULL, NULL);
|
||||||
|
return out;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
char *buf;
|
||||||
|
uint32_t size = 0;
|
||||||
|
|
||||||
|
_NSGetExecutablePath(NULL, &size);
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
buf = g_malloc(size);
|
||||||
|
if (_NSGetExecutablePath(buf, &size) != 0) {
|
||||||
|
g_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char *real = g_canonicalize_filename(buf, NULL);
|
||||||
|
|
||||||
|
g_free(buf);
|
||||||
|
return real ? real : NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return g_file_read_link("/proc/self/exe", NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean dir_has_stylesheet(const char *dir) {
|
||||||
|
char *css;
|
||||||
|
gboolean ok;
|
||||||
|
|
||||||
|
if (!dir || !dir[0])
|
||||||
|
return FALSE;
|
||||||
|
css = g_build_filename(dir, CSS_FILE, NULL);
|
||||||
|
ok = g_file_test(css, G_FILE_TEST_IS_REGULAR);
|
||||||
|
g_free(css);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *macos_resources_dir(const char *exe) {
|
||||||
|
char *macos_dir;
|
||||||
|
char *contents;
|
||||||
|
char *resources;
|
||||||
|
|
||||||
|
if (!exe)
|
||||||
|
return NULL;
|
||||||
|
macos_dir = dup_dirname(exe);
|
||||||
|
if (!macos_dir)
|
||||||
|
return NULL;
|
||||||
|
if (!g_str_has_suffix(macos_dir, "MacOS")) {
|
||||||
|
g_free(macos_dir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
contents = dup_dirname(macos_dir);
|
||||||
|
g_free(macos_dir);
|
||||||
|
if (!contents)
|
||||||
|
return NULL;
|
||||||
|
resources = g_build_filename(contents, "Resources", NULL);
|
||||||
|
g_free(contents);
|
||||||
|
if (!dir_has_stylesheet(resources)) {
|
||||||
|
g_free(resources);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Directory next to Foo.app when exe is .../Foo.app/Contents/MacOS/maturita. */
|
||||||
|
static char *macos_app_parent_dir(const char *exe) {
|
||||||
|
char *macos_dir;
|
||||||
|
char *contents;
|
||||||
|
char *app_bundle;
|
||||||
|
char *parent;
|
||||||
|
|
||||||
|
if (!exe)
|
||||||
|
return NULL;
|
||||||
|
macos_dir = dup_dirname(exe);
|
||||||
|
if (!macos_dir || !g_str_has_suffix(macos_dir, "MacOS")) {
|
||||||
|
g_free(macos_dir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
contents = dup_dirname(macos_dir);
|
||||||
|
g_free(macos_dir);
|
||||||
|
if (!contents)
|
||||||
|
return NULL;
|
||||||
|
app_bundle = dup_dirname(contents);
|
||||||
|
g_free(contents);
|
||||||
|
if (!app_bundle)
|
||||||
|
return NULL;
|
||||||
|
parent = dup_dirname(app_bundle);
|
||||||
|
g_free(app_bundle);
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_progress_paths(const char *write_root) {
|
||||||
|
g_free(app_progress_dir);
|
||||||
|
g_free(app_progress_u1);
|
||||||
|
g_free(app_progress_u2);
|
||||||
|
g_free(app_progress_u3);
|
||||||
|
g_free(app_settings_file);
|
||||||
|
g_free(app_progress_net);
|
||||||
|
g_free(app_progress_hw);
|
||||||
|
g_free(app_progress_mluvnice);
|
||||||
|
g_free(app_progress_cetba);
|
||||||
|
|
||||||
|
app_progress_dir = g_build_filename(write_root, PROGRESS_DIR_NAME, NULL);
|
||||||
|
app_progress_u1 = g_build_filename(app_progress_dir, "unit1.conf", NULL);
|
||||||
|
app_progress_u2 = g_build_filename(app_progress_dir, "unit2.conf", NULL);
|
||||||
|
app_progress_u3 = g_build_filename(app_progress_dir, "unit3.conf", NULL);
|
||||||
|
app_settings_file = g_build_filename(app_progress_dir, "settings.conf", NULL);
|
||||||
|
app_progress_net = g_build_filename(app_progress_dir, "net.conf", NULL);
|
||||||
|
app_progress_hw = g_build_filename(app_progress_dir, "hw.conf", NULL);
|
||||||
|
app_progress_mluvnice = g_build_filename(app_progress_dir, "mluvnice.conf", NULL);
|
||||||
|
app_progress_cetba = g_build_filename(app_progress_dir, "cetba.conf", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resolve read-only asset root, chdir there, and point progress at a writable
|
||||||
|
* location (next to the AppImage / .app, or beside the binary / source tree). */
|
||||||
|
void setup_portable_paths(void) {
|
||||||
|
const char *appdir = g_getenv("APPDIR");
|
||||||
|
const char *appimage = g_getenv("APPIMAGE");
|
||||||
|
char *exe = executable_path();
|
||||||
|
char *exe_dir = exe ? dup_dirname(exe) : NULL;
|
||||||
|
char *data_dir = NULL;
|
||||||
|
char *write_root = NULL;
|
||||||
|
char *cwd;
|
||||||
|
|
||||||
|
if (appdir && dir_has_stylesheet(appdir))
|
||||||
|
data_dir = g_strdup(appdir);
|
||||||
|
if (!data_dir)
|
||||||
|
data_dir = macos_resources_dir(exe);
|
||||||
|
if (!data_dir && exe_dir && dir_has_stylesheet(exe_dir))
|
||||||
|
data_dir = g_strdup(exe_dir);
|
||||||
|
|
||||||
|
cwd = g_get_current_dir();
|
||||||
|
if (!data_dir && dir_has_stylesheet(cwd))
|
||||||
|
data_dir = g_strdup(cwd);
|
||||||
|
if (!data_dir && cwd)
|
||||||
|
data_dir = g_strdup(cwd);
|
||||||
|
|
||||||
|
if (appimage && appimage[0])
|
||||||
|
write_root = dup_dirname(appimage);
|
||||||
|
if (!write_root)
|
||||||
|
write_root = macos_app_parent_dir(exe);
|
||||||
|
if (!write_root && exe_dir)
|
||||||
|
write_root = g_strdup(exe_dir);
|
||||||
|
if (!write_root && data_dir)
|
||||||
|
write_root = g_strdup(data_dir);
|
||||||
|
if (!write_root)
|
||||||
|
write_root = g_strdup(".");
|
||||||
|
|
||||||
|
set_progress_paths(write_root);
|
||||||
|
|
||||||
|
if (data_dir && g_chdir(data_dir) != 0)
|
||||||
|
g_warning("Could not chdir to data directory '%s'", data_dir);
|
||||||
|
|
||||||
|
g_free(cwd);
|
||||||
|
g_free(write_root);
|
||||||
|
g_free(data_dir);
|
||||||
|
g_free(exe_dir);
|
||||||
|
g_free(exe);
|
||||||
|
}
|
||||||
|
|
||||||
char *normalize_answer(const char *input) {
|
char *normalize_answer(const char *input) {
|
||||||
GString *pre = g_string_new(NULL);
|
GString *pre = g_string_new(NULL);
|
||||||
GString *out = g_string_new(NULL);
|
GString *out = g_string_new(NULL);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue