keeperfx-tux

maintainer yetipaw · 0 votes · scanned 2026-08-18 00:03:42.021799
LOW
View on AUR ↗
Why flagged The package builds from a legitimate project source and downloads a data archive from the same project's release page; the few votes and recent upload are noted but do not indicate active malice or supply-chain compromise.

Triggered rules

LOW Few votes, recently uploaded zero_votes_recent

Uploaded within the last 14 days with 2 or fewer community votes — little peer review so far.

LOW AI review llm_review

An AI model (qwen/qwen3-235b-a22b-2507) reviewed this and agrees it is LOW (confidence 90%): The package builds from a legitimate project source and downloads a data archive from the same project's release page; the few votes and recent upload are noted but do not indicate active malice or supply-chain compromise.

PKGBUILD

1# Maintainer: Alfredo Montesinos <alfredo.montesinos@kubereva.com>
2
3# A split package: one recipe, one AUR repository, two outputs. Users install
4# `keeperfx-tux` and pacman pulls the data in as a dependency, so there is one
5# name to remember and one command to run. Building both from a single pkgbase
6# also makes a version mismatch between engine and data impossible rather than
7# something CI has to police -- and a mismatch is exactly what once shipped a
8# frozen config against a newer engine.
9#
10# _tag and pkgver are bumped by .github/workflows/publish-aur.yml when a release
11# is published. pkgver is the tag without the leading "v" and the "-alpha" suffix.
12_tag=v1.4.0.5425
13# The launcher is a separate repository with no tags, so it is pinned by commit.
14_launcher_commit=b27ddd5d267484351d6cd4d9ca45a9113f1d586c
15pkgbase=keeperfx-tux
16pkgname=('keeperfx-tux' 'keeperfx-tux-data' 'keeperfx-tux-launcher')
17pkgver=1.4.0.5425
18# rel 4: ship the pacman hook that reports a library break the soname
19# dependencies below cannot catch, and pick up the launcher fix that stops a
20# crash report carrying a log the failing run never wrote.
21pkgrel=4
22arch=('x86_64')
23url="https://github.com/ForkedInTime/keeperfx-linux-alpha"
24license=('GPL-2.0-or-later')
25# In a split package, only makedepends (and any pkgbase-level depends) are
26# installed to build with -- a depends= array inside package_*() is metadata for
27# the built package and does nothing at build time. The engine's libraries are
28# therefore listed here as well as on the output that runs against them; without
29# that a clean chroot has no SDL3 headers and the engine will not compile.
30# SDL3_net does not exist: networking is enet6, and the only SDLNet_ references
31# left in the tree are comments.
32makedepends=('git' 'python' 'curl' 'p7zip'
33 # engine
34 'sdl3' 'sdl3_mixer' 'sdl3_image'
35 'ffmpeg' 'openal' 'luajit' 'libspng' 'minizip' 'zlib'
36 'libepoxy' 'miniupnpc' 'libnatpmp' 'openssl' 'zstd'
37 # Qt launcher
38 'cmake' 'ninja' 'qt6-base' 'qt6-tools')
39# !strip: this is an alpha -- usable backtraces in bug reports beat the saved MBs.
40# !debug: without it, !strip leaves the debug sources in the main package.
41# !lto: linux.mk manages its own optimisation flags and LTO is unvalidated here;
42# letting makepkg inject it risks the kind of silent miscompile that
43# already forced a -march revert.
44options=('!strip' '!debug' '!lto')
45source=(
46 "keeperfx-tux::git+https://github.com/ForkedInTime/keeperfx-linux-alpha.git#tag=${_tag}"
47 "keeperfx-tux-${pkgver}-full.7z::${url}/releases/download/${_tag}/keeperfx-linux-alpha-x86_64-full.7z"
48 "keeperfx-tux-launcher::git+https://github.com/ForkedInTime/keeperfx-launcher-qt-linux.git#commit=${_launcher_commit}"
49 'keeperfx-tux.sh'
50 'keeperfx-tux.desktop'
51 'keeperfx-tux-launcher.sh'
52 'keeperfx-tux.hook'
53 'keeperfx-tux-libcheck.sh'
54)
55noextract=("keeperfx-tux-${pkgver}-full.7z")
56sha256sums=(
57 'SKIP'
58 'a31e803e60bea582424b438bbaa1f05b360ea4ea0621c2545723a688103cdb2f'
59 'SKIP'
60 '8b897f0e147061f14fb0618a2737faefec037f338a1cac40d559b558ac1eef0c'
61 '72d72a8e7c1221208eed0622a6e323399ba8cb139ab8840d620ef2697623a1b4'
62 '1001a296fc71263c3a64d22f9bdfc398954119f80df89f49a4b42f2769e169a1'
63 'ee2fc0f5b3d81dd55efe7d2aef6c4d67d18baff794114e3d6e334171842601eb'
64 '37e0fcb5b46aa0b178380ea8f36aa62485b75b5425c1932c7ada7f4101efc870'
65)
66
67# Data trees taken from the release archive. It also contains the engine binary,
68# the Qt launcher, a bundled 7z.so, keeperfx.cfg and version.txt: those are either
69# the engine package's job or user state, so they are deliberately skipped.
70_data_trees=(data sound ldata campgns levels lang fxdata creatrs mods music multiplayer)
71
72prepare() {
73 cd "${srcdir}/${pkgbase}"
74 # These four deps are fetched by the makefile rather than vendored. Doing it in
75 # prepare() keeps the network access out of build(), which is where makepkg
76 # expects an already-populated source tree.
77 make -f linux.mk \
78 deps/centijson/include/json.h \
79 deps/astronomy/include/astronomy.h \
80 deps/enet6/include/enet6/enet.h \
81 deps/libcurl/lib/libcurl.a
82
83 cd "${srcdir}"
84 7z x -y "keeperfx-tux-${pkgver}-full.7z" -o"extracted" > /dev/null
85}
86
87build() {
88 cd "${srcdir}/${pkgbase}"
89
90 # ver_defs.h is only regenerated when version.mk changes, so a stale build
91 # number would otherwise be baked in -- and the launcher gates settings on it.
92 rm -f src/ver_defs.h
93 # The suffix follows the tag being packaged, exactly as the release workflows do.
94 # Hardcoding "alpha" here stamped version.txt as an alpha even when building a
95 # stable tag, and the launcher reads that file to decide which update channel an
96 # install is on -- so every Arch user of a stable release would have been put on
97 # the alpha channel and offered alpha updates.
98 local _ver_suffix=
99 case "${_tag}" in
100 *-alpha) _ver_suffix=alpha ;;
101 *-prototype) _ver_suffix=Prototype ;;
102 esac
103 make -f linux.mk \
104 BUILD_NUMBER="$(git rev-list --count HEAD)" \
105 VER_SUFFIX="${_ver_suffix}" \
106 -j"$(nproc)"
107
108 # The UTF-8 fonts are required since upstream #4920 but linux.mk does not build
109 # them; the project's CI generates them from tools/fxfontmaker.
110 (
111 cd tools/fxfontmaker
112 local PY; PY=$(command -v python3 || command -v python)
113 "$PY" rescale_unifont_hex.py unifont-17.0.04.hex unifont12.hex
114 "$PY" bdf_to_hex.py wenquanyi_9pt.bdf wenquanyi.hex
115 "$PY" merge_hex.py unifont12.hex wenquanyi.hex merged12.hex
116 "$PY" unifont_hex_to_binary.py unifont-17.0.04.hex font16.fxfont 16
117 "$PY" unifont_hex_to_binary.py unifont_jp-17.0.04.hex font16_JPN.fxfont 16
118 "$PY" unifont_hex_to_binary.py unifont_t-17.0.04.hex font16_CHT.fxfont 16
119 "$PY" unifont_hex_to_binary.py merged12.hex font12.fxfont 12
120 rm -f merged12.hex wenquanyi.hex unifont12.hex
121 )
122
123 # The Qt launcher. CMake pulls bit7z and LIEF from GitHub via CPM at configure
124 # time and builds them in-tree. Neither can come from the system:
125 # bit7z is packaged nowhere for Arch, and lief-bin ships only the shared
126 # library while this build asks for COMPONENTS STATIC. CPM_USE_LOCAL_PACKAGES
127 # was tried and is deliberately not used -- besides failing on LIEF, it picked
128 # up an unpackaged bit7z from /usr/local on the build machine, which would have
129 # produced a package that only builds where that stray copy exists.
130 cd "${srcdir}/keeperfx-tux-launcher"
131 # A stale CMakeCache.txt survives makepkg -f, and it remembers the flags of the
132 # previous configure, so start clean. CPM_DOWNLOAD_ALL then stops CPM probing the
133 # system at all: it must fetch and build both dependencies in-tree, which is what
134 # keeps the result independent of whatever happens to be on the build machine.
135 # CMAKE_SKIP_RPATH stops the build tree's own paths being written into the
136 # binary: CPM builds zlib in-tree, and its build directory otherwise ends up as
137 # a RUNPATH that namcap rejects and that would not exist on a user's machine.
138 # Nothing is lost -- zlib, Qt and OpenSSL all resolve from the system.
139 rm -rf build
140 cmake -B build -G Ninja \
141 -DCMAKE_BUILD_TYPE=Release \
142 -DCMAKE_INSTALL_PREFIX=/usr \
143 -DCPM_USE_LOCAL_PACKAGES=OFF \
144 -DCPM_DOWNLOAD_ALL=ON \
145 -DCMAKE_SKIP_RPATH=ON
146 cmake --build build
147}
148
149package_keeperfx-tux() {
150 pkgdesc="KeeperFX Tux Edition — native Linux build of the Dungeon Keeper engine remake"
151 depends=(
152 # Sonames, not package names. On a rolling distribution the package name is
153 # the wrong unit: an unversioned 'ffmpeg' let pacman move 8.1.2 -> 9.0 under
154 # an already-built package, every libav* soname the engine linked shifted at
155 # once, and the binary stopped loading -- with nothing said at upgrade time
156 # and the failure surfacing only as a "crash" when the user pressed Play.
157 # makepkg rewrites each of these from the built ELF into a versioned
158 # dependency ('libavformat.so=63-64'), so the next bump is refused by pacman
159 # before it happens: an explicit rebuild prompt instead of a broken install.
160 'libavformat.so' 'libavcodec.so' 'libswresample.so' 'libswscale.so'
161 'libavutil.so' 'libopenal.so' 'libspng.so' 'libz.so' 'libepoxy.so'
162 'libminiupnpc.so' 'libssl.so' 'libcrypto.so' 'libzstd.so'
163 # These four ship no soname in provides= at all, so they can only be named
164 # directly and stay exposed to the same failure. SDL3 holds its ABI at
165 # .so.0 by project policy and the other three are low-churn, which is why
166 # ffmpeg is the one that actually bit.
167 'sdl3' 'sdl3_mixer' 'sdl3_image' 'luajit' 'minizip' 'libnatpmp'
168 # Implicit but real: the engine links these, the wrapper is a bash script,
169 # and the icons need the hicolor theme hierarchy to exist.
170 'glibc' 'gcc-libs' 'bash' 'hicolor-icon-theme'
171 # Pulled in automatically, so installing this one name gives a complete,
172 # playable install rather than an engine with nothing to run.
173 "keeperfx-tux-data=${pkgver}-${pkgrel}"
174 # The launcher is the front door: it finds your Dungeon Keeper installation,
175 # copies the files it needs, and configures the game. Installing the engine
176 # without it would lose the only route a new player has to a playable install.
177 "keeperfx-tux-launcher=${pkgver}-${pkgrel}"
178 )
179 conflicts=('keeperfx-linux-alpha' 'keeperfx-linux-alpha-git')
180 provides=("keeperfx-tux=${pkgver}")
181
182 cd "${srcdir}/${pkgbase}"
183 local _share="${pkgdir}/usr/share/${pkgbase}"
184
185 # /usr/share is for architecture-independent files, so the ELF lives in
186 # /usr/lib. Its location is free: the wrapper links it into the game directory
187 # and the engine roots itself at argv[0], not at the binary's real path.
188 install -Dm755 bin/keeperfx "${pkgdir}/usr/lib/${pkgbase}/keeperfx"
189 install -dm755 "${_share}"
190
191 # The launcher reads the engine version from version.txt: a native ELF carries
192 # no Windows PE ProductVersion resource for it to inspect.
193 sed -n 's/.*VER_STRING "\(.*\)".*/\1/p' src/ver_defs.h > "${_share}/version.txt"
194
195 # Text/config data that tracks the engine version.
196 local _d
197 for _d in fxdata creatrs mods; do
198 install -dm755 "${_share}/${_d}"
199 cp -r "config/${_d}/." "${_share}/${_d}/"
200 done
201 for _d in campgns levels lang multiplayer; do
202 [ -d "${_d}" ] || continue
203 install -dm755 "${_share}/${_d}"
204 cp -r "${_d}/." "${_share}/${_d}/"
205 done
206
207 # Generated fonts live alongside the text config, as the engine expects.
208 install -m644 tools/fxfontmaker/*.fxfont "${_share}/fxdata/"
209
210 # The engine refuses to start without keeperfx.cfg ("Configuration load error").
211 # Shipped as a template the wrapper copies into the game directory, because the
212 # user edits it and it must not be overwritten by an upgrade.
213 install -m644 config/keeperfx.cfg "${_share}/keeperfx.cfg"
214
215 # The soname dependencies above cover every library that publishes one, but
216 # six of the engine's do not and neither do the launcher's Qt and OpenSSL --
217 # for those pacman has nothing to compare and cannot refuse the upgrade. This
218 # hook cannot prevent that either; it reports it at the moment it happens,
219 # instead of leaving a broken install to be found the next time someone plays.
220 install -Dm755 "${srcdir}/keeperfx-tux-libcheck.sh" \
221 "${pkgdir}/usr/share/libalpm/scripts/keeperfx-tux-libcheck"
222 install -Dm644 "${srcdir}/keeperfx-tux.hook" \
223 "${pkgdir}/usr/share/libalpm/hooks/keeperfx-tux-libcheck.hook"
224
225 install -Dm755 "${srcdir}/keeperfx-tux.sh" "${pkgdir}/usr/bin/keeperfx-tux"
226 install -Dm644 "${srcdir}/keeperfx-tux.desktop" \
227 "${pkgdir}/usr/share/applications/keeperfx-tux.desktop"
228
229 local _px
230 for _px in 016 032 048 064 128; do
231 [ -f "res/keeperfx_icon${_px}-08bpp.png" ] || continue
232 install -Dm644 "res/keeperfx_icon${_px}-08bpp.png" \
233 "${pkgdir}/usr/share/icons/hicolor/$((10#${_px}))x$((10#${_px}))/apps/keeperfx-tux.png"
234 done
235 for _px in 256 512; do
236 [ -f "res/keeperfx_icon${_px}-24bpp.png" ] || continue
237 install -Dm644 "res/keeperfx_icon${_px}-24bpp.png" \
238 "${pkgdir}/usr/share/icons/hicolor/${_px}x${_px}/apps/keeperfx-tux.png"
239 done
240
241 install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgbase}/LICENSE"
242 install -Dm644 README.md "${pkgdir}/usr/share/doc/${pkgbase}/README.md"
243}
244
245package_keeperfx-tux-data() {
246 pkgdesc="Game data for KeeperFX Tux Edition (campaigns, graphics, sounds) — you still supply your own Dungeon Keeper files"
247 arch=('any')
248 # Nothing here is executable: nothing to strip, no debug info to split out.
249 options=('!strip' '!debug')
250
251 local _share="${pkgdir}/usr/share/${pkgbase}-data"
252 install -dm755 "${_share}"
253
254 local _d
255 for _d in "${_data_trees[@]}"; do
256 if [ ! -d "${srcdir}/extracted/${_d}" ]; then
257 # music/ is legitimately empty in some releases; anything else missing means
258 # the archive layout changed and this PKGBUILD needs revisiting.
259 if [ "${_d}" = music ]; then continue; fi
260 echo "error: expected directory '${_d}' is missing from the release archive" >&2
261 return 1
262 fi
263 cp -r "${srcdir}/extracted/${_d}" "${_share}/"
264 done
265
266 find "${_share}" -type d -exec chmod 755 {} +
267 find "${_share}" -type f -exec chmod 644 {} +
268
269 install -Dm644 "${srcdir}/extracted/README.txt" \
270 "${pkgdir}/usr/share/doc/${pkgbase}-data/README.txt" 2>/dev/null || true
271}
272
273package_keeperfx-tux-launcher() {
274 pkgdesc="Qt launcher for KeeperFX Tux Edition — finds your Dungeon Keeper install, copies the files in, configures and plays"
275 depends=('qt6-base' 'zlib' 'openssl' 'glibc' 'gcc-libs' 'bash' 'hicolor-icon-theme')
276 optdepends=('keeperfx-tux: the game it launches')
277
278 cd "${srcdir}/keeperfx-tux-launcher"
279
280 # The launcher resolves its config and the game binary against
281 # QCoreApplication::applicationDirPath(), and Qt reads /proc/self/exe, so a
282 # symlink reports the target's directory rather than the game directory. It
283 # therefore cannot live in /usr/bin and be linked in; the wrapper copies it.
284 install -Dm755 build/keeperfx-launcher-qt "${pkgdir}/usr/lib/${pkgbase}/keeperfx-launcher-qt"
285 install -Dm755 "${srcdir}/keeperfx-tux-launcher.sh" "${pkgdir}/usr/bin/keeperfx-tux-launcher"
286
287 install -Dm644 packaging/keeperfx-launcher-qt.png \
288 "${pkgdir}/usr/share/icons/hicolor/256x256/apps/keeperfx-tux-launcher.png"
289
290 # This is the front door, so it takes the plain name; the engine's own entry is
291 # the "play directly" shortcut for once the game is set up.
292 install -dm755 "${pkgdir}/usr/share/applications"
293 cat > "${pkgdir}/usr/share/applications/keeperfx-tux-launcher.desktop" <<'EOF'
294[Desktop Entry]
295Type=Application
296Name=KeeperFX
297GenericName=Dungeon Keeper
298Comment=Install, configure and play KeeperFX (Dungeon Keeper) on Linux
299Exec=keeperfx-tux-launcher
300Icon=keeperfx-tux-launcher
301Terminal=false
302Categories=Game;StrategyGame;
303Keywords=dungeon;keeper;keeperfx;
304StartupWMClass=keeperfx-launcher-qt
305EOF
306
307 install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" 2>/dev/null || true
308}
309

Changes since previous scan

--- PKGBUILD @ 2026-08-12 00:27
+++ PKGBUILD @ 2026-08-18 00:03
@@ -11,11 +11,14 @@
# is published. pkgver is the tag without the leading "v" and the "-alpha" suffix.
_tag=v1.4.0.5425
# The launcher is a separate repository with no tags, so it is pinned by commit.
-_launcher_commit=21e3b13e8b9ef9199c8e01693d303d098aa66c07
+_launcher_commit=b27ddd5d267484351d6cd4d9ca45a9113f1d586c
pkgbase=keeperfx-tux
pkgname=('keeperfx-tux' 'keeperfx-tux-data' 'keeperfx-tux-launcher')
pkgver=1.4.0.5425
-pkgrel=1
+# rel 4: ship the pacman hook that reports a library break the soname
+# dependencies below cannot catch, and pick up the launcher fix that stops a
+# crash report carrying a log the failing run never wrote.
+pkgrel=4
arch=('x86_64')
url="https://github.com/ForkedInTime/keeperfx-linux-alpha"
license=('GPL-2.0-or-later')
@@ -46,6 +49,8 @@
'keeperfx-tux.sh'
'keeperfx-tux.desktop'
'keeperfx-tux-launcher.sh'
+ 'keeperfx-tux.hook'
+ 'keeperfx-tux-libcheck.sh'
)
noextract=("keeperfx-tux-${pkgver}-full.7z")
sha256sums=(
@@ -55,6 +60,8 @@
'8b897f0e147061f14fb0618a2737faefec037f338a1cac40d559b558ac1eef0c'
'72d72a8e7c1221208eed0622a6e323399ba8cb139ab8840d620ef2697623a1b4'
'1001a296fc71263c3a64d22f9bdfc398954119f80df89f49a4b42f2769e169a1'
+ 'ee2fc0f5b3d81dd55efe7d2aef6c4d67d18baff794114e3d6e334171842601eb'
+ '37e0fcb5b46aa0b178380ea8f36aa62485b75b5425c1932c7ada7f4101efc870'
)
# Data trees taken from the release archive. It also contains the engine binary,
@@ -142,9 +149,22 @@
package_keeperfx-tux() {
pkgdesc="KeeperFX Tux Edition — native Linux build of the Dungeon Keeper engine remake"
depends=(
- 'sdl3' 'sdl3_mixer' 'sdl3_image'
- 'ffmpeg' 'openal' 'luajit' 'libspng' 'minizip' 'zlib'
- 'libepoxy' 'miniupnpc' 'libnatpmp' 'openssl' 'zstd'
+ # Sonames, not package names. On a rolling distribution the package name is
+ # the wrong unit: an unversioned 'ffmpeg' let pacman move 8.1.2 -> 9.0 under
+ # an already-built package, every libav* soname the engine linked shifted at
+ # once, and the binary stopped loading -- with nothing said at upgrade time
+ # and the failure surfacing only as a "crash" when the user pressed Play.
+ # makepkg rewrites each of these from the built ELF into a versioned
+ # dependency ('libavformat.so=63-64'), so the next bump is refused by pacman
+ # before it happens: an explicit rebuild prompt instead of a broken install.
+ 'libavformat.so' 'libavcodec.so' 'libswresample.so' 'libswscale.so'
+ 'libavutil.so' 'libopenal.so' 'libspng.so' 'libz.so' 'libepoxy.so'
+ 'libminiupnpc.so' 'libssl.so' 'libcrypto.so' 'libzstd.so'
+ # These four ship no soname in provides= at all, so they can only be named
+ # directly and stay exposed to the same failure. SDL3 holds its ABI at
+ # .so.0 by project policy and the other three are low-churn, which is why
+ # ffmpeg is the one that actually bit.
+ 'sdl3' 'sdl3_mixer' 'sdl3_image' 'luajit' 'minizip' 'libnatpmp'
# Implicit but real: the engine links these, the wrapper is a bash script,
# and the icons need the hicolor theme hierarchy to exist.
'glibc' 'gcc-libs' 'bash' 'hicolor-icon-theme'
@@ -191,6 +211,16 @@
# Shipped as a template the wrapper copies into the game directory, because the
# user edits it and it must not be overwritten by an upgrade.
install -m644 config/keeperfx.cfg "${_share}/keeperfx.cfg"
+
+ # The soname dependencies above cover every library that publishes one, but
+ # six of the engine's do not and neither do the launcher's Qt and OpenSSL --
+ # for those pacman has nothing to compare and cannot refuse the upgrade. This
+ # hook cannot prevent that either; it reports it at the moment it happens,
+ # instead of leaving a broken install to be found the next time someone plays.
+ install -Dm755 "${srcdir}/keeperfx-tux-libcheck.sh" \
+ "${pkgdir}/usr/share/libalpm/scripts/keeperfx-tux-libcheck"
+ install -Dm644 "${srcdir}/keeperfx-tux.hook" \
+ "${pkgdir}/usr/share/libalpm/hooks/keeperfx-tux-libcheck.hook"
install -Dm755 "${srcdir}/keeperfx-tux.sh" "${pkgdir}/usr/bin/keeperfx-tux"
install -Dm644 "${srcdir}/keeperfx-tux.desktop" \

Scan history

Scanned at (UTC)SeverityRules
2026-08-18 00:03:42 LOW 2
2026-08-17 00:18:29 LOW 2
2026-08-16 00:03:42 LOW 2
2026-08-15 00:26:13 LOW 2
2026-08-14 00:03:41 LOW 2
2026-08-13 07:25:43 LOW 2
2026-08-12 00:27:08 CLEAN 2
2026-08-11 13:21:13 LOW 1

Report a package

Reports go to the AURWatch maintainer (one person) and are read by hand. No login required.

0 / 4000
Your suggestion