11#! /usr/bin/env bash
2- set -euo pipefail
3-
4- VERSION=" ${1:- 0.0.0} "
5- APP_NAME=" Asante Typing"
6- APP_BIN_NAME=" asante-typing" # launcher name
2+ # package_deb.sh — Build a Linux Release, system-install for testing,
3+ # stage files into pkgroot, and produce a Debian .deb with fpm.
4+ # This script encodes the exact working sequence you confirmed.
5+
6+ set -Eeuo pipefail
7+
8+ # ---- Config you may tweak ----------------------------------------------------
9+ APP_NAME=" asante-typing" # Debian package name
10+ BINARY_NAME=" asante_typing" # Installed binary name
11+ INSTALL_PREFIX=" /usr" # FHS system install prefix
12+ BUILD_TYPE=" Release"
13+ PKG_BUILD_DIR=" build/linux/x64/release/pkg/cmake"
714BUNDLE_DIR=" build/linux/x64/release/bundle"
8- ICON_SRC=" assets/icon/app_icon.png" # Path to the icon in the repository
9-
10- # Check if icon exists
11- if [[ ! -f " $ICON_SRC " ]]; then
12- echo " Icon file not found: $ICON_SRC " >&2
13- exit 1
14- fi
15-
16- if [[ ! -d " $BUNDLE_DIR " ]]; then
17- echo " Bundle not found: $BUNDLE_DIR " >&2
18- exit 1
19- fi
20-
21- WORK=" dist/linux/pkg"
22- DEB_OUT=" dist/linux"
23- mkdir -p " $WORK /DEBIAN" " $WORK /usr/bin" " $WORK /opt/$APP_BIN_NAME " " $WORK /usr/share/applications" " $WORK /usr/share/pixmaps"
24-
25- if [[ ! -d " $WORK /DEBIAN" ]]; then
26- echo " Failed to create directory: $WORK /DEBIAN" >&2
27- exit 1
28- fi
29-
30- # Copy built files
31- cp -a " $BUNDLE_DIR /." " $WORK /opt/$APP_BIN_NAME /"
32-
33- if [[ ! -f " $WORK /opt/$APP_BIN_NAME /asante_typing" ]]; then
34- echo " Main binary not found in $WORK /opt/$APP_BIN_NAME /asante_typing" >&2
35- exit 1
36- fi
37-
38- # Copy icon
39- cp " $ICON_SRC " " $WORK /usr/share/pixmaps/$APP_BIN_NAME .png"
40- chmod 0644 " $WORK /usr/share/pixmaps/$APP_BIN_NAME .png"
41-
42- # Simple launcher wrapper
43- cat > " $WORK /usr/bin/$APP_BIN_NAME " << 'EOF '
44- #!/usr/bin/env bash
45- DIR="/opt/asante-typing"
46- exec "$DIR/asante_typing" "$@"
47- EOF
48- chmod +x " $WORK /usr/bin/$APP_BIN_NAME "
49-
50- # .desktop entry
51- cat > " $WORK /usr/share/applications/${APP_BIN_NAME} .desktop" << EOF
52- [Desktop Entry]
53- Name=$APP_NAME
54- Exec=$APP_BIN_NAME
55- Icon=$APP_BIN_NAME
56- Type=Application
57- Categories=Utility;Education;
58- Terminal=false
59- EOF
60-
61- # Control file
62- cat > " $WORK /DEBIAN/control" << EOF
63- Package: ${APP_BIN_NAME}
64- Version: ${VERSION}
65- Section: utils
66- Priority: optional
67- Architecture: amd64
68- Maintainer: John Francis Mukulu SJ <john.f.mukulu@gmail.com>
69- Homepage: https://mukulu.org/asante-typing
70- Vcs-Git: https://github.com/mukulu/asante-typing.git
71- Description: $APP_NAME - typing tutor
72- Asante Typing is an open-source typing tutor designed to help users improve
73- their typing speed and accuracy. Featuring interactive lessons and customizable
74- settings, it supports multiple keyboard layouts and provides real-time feedback
75- to enhance touch-typing skills. Ideal for beginners and advanced users alike.
76- EOF
77-
78- # Copyright file
79- cat > " $WORK /DEBIAN/copyright" << EOF
80- Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
81- Upstream-Name: $APP_NAME
82- Upstream-Contact: John Francis Mukulu SJ <john.f.mukulu@gmail.com>
83- Source: https://github.com/mukulu/asante-typing
84-
85- Files: *
86- Copyright: 2025 John Francis Mukulu SJ
87- License: GPL-3.0
88- This program is free software: you can redistribute it and/or modify
89- it under the terms of the GNU General Public License as published by
90- the Free Software Foundation, version 3.
91- .
92- This program is distributed in the hope that it will be useful,
93- but WITHOUT ANY WARRANTY; without even the implied warranty of
94- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95- GNU General Public License for more details.
96- .
97- You should have received a copy of the GNU General Public License
98- along with this program. If not, see <https://www.gnu.org/licenses/>.
99-
100- License: GPL-3.0
101- On Debian systems, the complete text of the GNU General Public
102- License version 3 can be found in "/usr/share/common-licenses/GPL-3".
103- EOF
104-
105- mkdir -p " $DEB_OUT "
106-
107- # --- FIX: normalise DEBIAN/ perms to satisfy dpkg-deb ---
108- # Some filesystems create dirs with g+s (2775). dpkg-deb requires 0755–0775.
109- chmod -R ug-s " $WORK /DEBIAN"
110- find " $WORK /DEBIAN" -type d -exec chmod 0755 {} \;
111- # control, copyright, conffiles, etc. must be readable (0644)
112- find " $WORK /DEBIAN" -maxdepth 1 -type f -not -name ' preinst' -not -name ' postinst' -not -name ' prerm' -not -name ' postrm' -exec chmod 0644 {} \;
113- # Maintainer scripts must be executable (0755) if present
114- for f in preinst postinst prerm postrm; do
115- [ -f " $WORK /DEBIAN/$f " ] && chmod 0755 " $WORK /DEBIAN/$f "
116- done
117- # --- END FIX ---
118-
119- # Debug: List permissions
120- ls -lR " $WORK /DEBIAN"
121-
122- # Check for dpkg-deb
123- if ! command -v dpkg-deb > /dev/null; then
124- echo " dpkg-deb is not installed. Please install it (e.g., sudo apt install dpkg)." >&2
125- exit 1
15+ PKGROOT=" $( pwd) /pkgroot"
16+
17+ # Version: use env APPVER if set, else read pubspec.yaml, else fallback.
18+ APPVER=" ${APPVER:- $(awk -F' : *' ' /^version:/{print $2; exit}' pubspec.yaml 2>/ dev/ null || echo ' 0.1.0' )} "
19+ ARCH=" amd64"
20+
21+ VENDOR=" John Francis Mukulu <john.f.mukulu@gmail.com>"
22+ HOMEPAGE=" https://mukulu.org"
23+ LICENSE=" MIT"
24+ DESCRIPTION=" Asante Typing – learn touch-typing with interactive lessons."
25+ # -----------------------------------------------------------------------------
26+
27+ echo " ==> Cleaning workspace"
28+ git clean -xfd || true
29+ flutter clean
30+ flutter pub get
31+
32+ echo " ==> Flutter Release build (bundle)"
33+ flutter build linux --release
34+
35+ echo " ==> Configure CMake (packaging/FHS mode)"
36+ rm -rf " ${PKG_BUILD_DIR} "
37+ cmake -S linux -B " ${PKG_BUILD_DIR} " \
38+ -DCMAKE_BUILD_TYPE=" ${BUILD_TYPE} " \
39+ -DCMAKE_INSTALL_PREFIX=" ${INSTALL_PREFIX} " \
40+ -DASANTE_SYSTEM_INSTALL=ON
41+
42+ echo " ==> Build native runner"
43+ cmake --build " ${PKG_BUILD_DIR} " --config " ${BUILD_TYPE} "
44+
45+ echo " ==> System install for local test (needs sudo)"
46+ sudo cmake --install " ${PKG_BUILD_DIR} "
47+
48+ echo " ==> Refresh desktop/icon caches (needs sudo)"
49+ sudo update-desktop-database || true
50+ sudo gtk-update-icon-cache -f /usr/share/icons/hicolor || true
51+
52+ echo " ==> Stage files into pkgroot exactly as they'd be installed"
53+ sudo rm -rf " ${PKGROOT} "
54+ sudo mkdir -p " ${PKGROOT} "
55+ # NOTE: using sudo here mirrors your working sequence and avoids permission hiccups
56+ sudo DESTDIR=" ${PKGROOT} " cmake --install " ${PKG_BUILD_DIR} "
57+
58+ echo " ==> Remove any existing ${APP_NAME} *.deb (per your workflow)"
59+ sudo rm -f ${APP_NAME} * .deb || true
60+
61+ echo " ==> Ensure fpm is available (ruby-dev, rubygems, build-essential required)"
62+ if ! command -v fpm > /dev/null 2>&1 ; then
63+ echo " !! fpm not found. Installing (needs sudo) ..."
64+ sudo apt-get update
65+ sudo apt-get install -y ruby-dev rubygems build-essential
66+ sudo gem install --no-document fpm
12667fi
12768
128- dpkg-deb --build " $WORK " " ${DEB_OUT} /${APP_BIN_NAME} _${VERSION} _amd64.deb"
129- echo " Built ${DEB_OUT} /${APP_BIN_NAME} _${VERSION} _amd64.deb"
69+ echo " ==> Build .deb with fpm (using sudo as you did)"
70+ sudo fpm -s dir -t deb \
71+ -n " ${APP_NAME} " -v " ${APPVER} " -a " ${ARCH} " \
72+ --description " ${DESCRIPTION} " \
73+ --license " ${LICENSE} " \
74+ --url " ${HOMEPAGE} " \
75+ --vendor " ${VENDOR} " \
76+ -C " ${PKGROOT} " .
77+
78+ echo " ==> Install the freshly built package (needs sudo)"
79+ DEB_FILE=" ${APP_NAME} _${APPVER} _${ARCH} .deb"
80+ sudo apt install ./" ${DEB_FILE} "
81+
82+ echo " ==> Make the .deb world-writable (per your convenience workflow)"
83+ sudo chmod a+rwx ${APP_NAME} * .deb || true
84+
85+ echo
86+ echo " ✅ Done."
87+ echo " Package: ${DEB_FILE} "
88+ echo " Binary : ${INSTALL_PREFIX} /bin/${BINARY_NAME} "
89+ echo
90+ echo " Tip: Launch via '${BINARY_NAME} ' or from your app menu (icon: org.mukulu.asante_typing)."
0 commit comments