keeperfx-tux-data
maintainer yetipaw
· 0 votes
· base
keeperfx-tux
· 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
15
pkgbase=keeperfx-tux
16
pkgname=('keeperfx-tux' 'keeperfx-tux-data' 'keeperfx-tux-launcher')
17
pkgver=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.
21
pkgrel=4
22
arch=('x86_64')
23
url="https://github.com/ForkedInTime/keeperfx-linux-alpha"
24
license=('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.
32
makedepends=('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.
44
options=('!strip' '!debug' '!lto')
45
source=(
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
)
55
noextract=("keeperfx-tux-${pkgver}-full.7z")
56
sha256sums=(
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
72
prepare() {
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
87
build() {
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
149
package_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
245
package_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
273
package_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]
295
Type=Application
296
Name=KeeperFX
297
GenericName=Dungeon Keeper
298
Comment=Install, configure and play KeeperFX (Dungeon Keeper) on Linux
299
Exec=keeperfx-tux-launcher
300
Icon=keeperfx-tux-launcher
301
Terminal=false
302
Categories=Game;StrategyGame;
303
Keywords=dungeon;keeper;keeperfx;
304
StartupWMClass=keeperfx-launcher-qt
305
EOF
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) | Severity | Rules |
|---|---|---|
| 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 |