From 9a6c0e2bcd4bc3fb0987c1f9691d11eb90b00c19 Mon Sep 17 00:00:00 2001 From: Matt Jolly Date: Wed, 5 Aug 2026 18:24:32 +1000 Subject: [PATCH] games-strategy/freeciv: add 3.2.5 Bug: https://bugs.gentoo.org/971045 Closes: https://bugs.gentoo.org/959677 Signed-off-by: Matt Jolly --- games-strategy/freeciv/Manifest | 1 + .../files/freeciv-3.2.5-sdl2-include.patch | 117 ++++++++++ .../freeciv/freeciv-3.2.3-r1.ebuild | 216 ++++++++++++++++++ games-strategy/freeciv/freeciv-3.2.5.ebuild | 215 +++++++++++++++++ games-strategy/freeciv/freeciv-9999.ebuild | 4 +- 5 files changed, 551 insertions(+), 2 deletions(-) create mode 100644 games-strategy/freeciv/files/freeciv-3.2.5-sdl2-include.patch create mode 100644 games-strategy/freeciv/freeciv-3.2.3-r1.ebuild create mode 100644 games-strategy/freeciv/freeciv-3.2.5.ebuild diff --git a/games-strategy/freeciv/Manifest b/games-strategy/freeciv/Manifest index e31cc910bc38b..e5e64bec29d4e 100644 --- a/games-strategy/freeciv/Manifest +++ b/games-strategy/freeciv/Manifest @@ -1,2 +1,3 @@ DIST freeciv-3.1.4.tar.gz 128914453 BLAKE2B 60a371692e74434e8f8a0311b3c4732cb4a0199ea426f06eaac87d0f5982239f9bec069441f5897921907edafe6e5ab4492dd525b606eaeb3a4de1976d6c5766 SHA512 1a94861e4298e6fa81347a5625ae5d9fea1f2ee0195265a8b53a1c2255d1b02010140d3f48fc3474ae4aa188db16f12b84b7a112d37e2ed7bd474f250a50a97a DIST freeciv-3.2.3.tar.gz 142109424 BLAKE2B 3d5c3c7379c646231da9c6d482fad0ac802d0a04a244e76fe76a855372687e403011f88708f1777c47f68c5e0e61fcf7c81351bd069e9ee29a0d8ac29acc6e8f SHA512 04a468f17ef42a2cacd8eb59153ade17c0445545574be66c08c833b88da057ef9780540657b256a9661f493eec3a4e9731a315f4aab3159593fcc49559f0cd24 +DIST freeciv-3.2.5.tar.gz 142217384 BLAKE2B 679f520a1213aec8ec7515e0d7ce1b9e67680dec9313f0c42808dcde9d57f5521f5024e09511b06f7635a72711ca9c8460f5168a1d4fbb83336fff8219f946c5 SHA512 ce35ba50d52d98ac24e2d370d7eb6f7d2b0a47f9a460d10468b55d165cb76edf65f645ea24d99293308b13dfbf3873ed11bfdf7854da02bdd6c0bfbfb061c01c diff --git a/games-strategy/freeciv/files/freeciv-3.2.5-sdl2-include.patch b/games-strategy/freeciv/files/freeciv-3.2.5-sdl2-include.patch new file mode 100644 index 0000000000000..92d849ec4ee1e --- /dev/null +++ b/games-strategy/freeciv/files/freeciv-3.2.5-sdl2-include.patch @@ -0,0 +1,117 @@ +From 4e6a5716cb133c2a220acf206c440f457af36538 Mon Sep 17 00:00:00 2001 +From: Matt Jolly +Date: Wed, 5 Aug 2026 19:06:32 +1000 +Subject: [PATCH] Guard SDL2-only client includes and fix SDL3 exit audio loop + +The gtk3.22, gtk4, and qt clients previously unconditionally included +SDL2, resulting in compilation failures on a system that successfully +configured for SDL3 audio. + +Additionally, client/audio.c now uses audio_stop_usage() during shutdown +to prevent music-finished callbacks from restarting looping tracks on +exit. + +Bug: https://bugs.gentoo.org/971045 +Bug: RM #2121 +Signed-off-by: Matt Jolly +--- + client/audio.c | 5 +++-- + client/gui-gtk-3.22/gui_main.c | 9 +++------ + client/gui-gtk-4.0/gui_main.c | 9 +++------ + client/gui-qt/gui_main.cpp | 9 +++------ + 4 files changed, 12 insertions(+), 20 deletions(-) + +diff --git a/client/audio.c b/client/audio.c +index 2b8687f50a..17aa086423 100644 +--- a/client/audio.c ++++ b/client/audio.c +@@ -657,8 +657,9 @@ void audio_set_volume(double volume) + **************************************************************************/ + void audio_shutdown(bool play_quit_tag) + { +- /* Avoid infinite loop at end of game */ +- audio_stop(); ++ /* Prevent music-finished callback from starting another looping track ++ * while exit waits for current audio to drain. */ ++ audio_stop_usage(); + + if (play_quit_tag) { + audio_play_sound("e_client_quit", NULL, NULL); +diff --git a/client/gui-gtk-3.22/gui_main.c b/client/gui-gtk-3.22/gui_main.c +index fcc70d2e9b..b62b67547e 100644 +--- a/client/gui-gtk-3.22/gui_main.c ++++ b/client/gui-gtk-3.22/gui_main.c +@@ -15,17 +15,14 @@ + #include + #endif + +-#ifdef AUDIO_SDL +-/* Though it would happily compile without this include, +- * it is needed for sound to work. +- * It defines "main" macro to rename our main() so that +- * it can install SDL's own. */ ++#if defined(AUDIO_SDL) && !defined(AUDIO_SDL3) ++/* SDL2 audio backend requires this include so SDL can rewrite main(). */ + #ifdef SDL2_PLAIN_INCLUDE + #include + #else /* PLAIN_INCLUDE */ + #include + #endif /* PLAIN_INCLUDE */ +-#endif /* AUDIO_SDL */ ++#endif /* AUDIO_SDL && !AUDIO_SDL3 */ + + #ifdef HAVE_LOCALE_H + #include +diff --git a/client/gui-gtk-4.0/gui_main.c b/client/gui-gtk-4.0/gui_main.c +index aec8ba524d..78cf24a248 100644 +--- a/client/gui-gtk-4.0/gui_main.c ++++ b/client/gui-gtk-4.0/gui_main.c +@@ -15,17 +15,14 @@ + #include + #endif + +-#ifdef AUDIO_SDL +-/* Though it would happily compile without this include, +- * it is needed for sound to work. +- * It defines "main" macro to rename our main() so that +- * it can install SDL's own. */ ++#if defined(AUDIO_SDL) && !defined(AUDIO_SDL3) ++/* SDL2 audio backend requires this include so SDL can rewrite main(). */ + #ifdef SDL2_PLAIN_INCLUDE + #include + #else /* PLAIN_INCLUDE */ + #include + #endif /* PLAIN_INCLUDE */ +-#endif /* AUDIO_SDL */ ++#endif /* AUDIO_SDL && !AUDIO_SDL3 */ + + #ifdef HAVE_LOCALE_H + #include +diff --git a/client/gui-qt/gui_main.cpp b/client/gui-qt/gui_main.cpp +index 50bb12b70f..620252b735 100644 +--- a/client/gui-qt/gui_main.cpp ++++ b/client/gui-qt/gui_main.cpp +@@ -15,17 +15,14 @@ + #include + #endif + +-#ifdef AUDIO_SDL +-/* Though it would happily compile without this include, +- * it is needed for sound to work. +- * It defines "main" macro to rename our main() so that +- * it can install SDL's own. */ ++#if defined(AUDIO_SDL) && !defined(AUDIO_SDL3) ++/* SDL2 audio backend requires this include so SDL can rewrite main(). */ + #ifdef SDL2_PLAIN_INCLUDE + #include + #else // PLAIN_INCLUDE + #include + #endif // PLAIN_INCLUDE +-#endif // AUDIO_SDL ++#endif // AUDIO_SDL && !AUDIO_SDL3 + + #include + +-- +2.55.0 + diff --git a/games-strategy/freeciv/freeciv-3.2.3-r1.ebuild b/games-strategy/freeciv/freeciv-3.2.3-r1.ebuild new file mode 100644 index 0000000000000..9c32c711738eb --- /dev/null +++ b/games-strategy/freeciv/freeciv-3.2.3-r1.ebuild @@ -0,0 +1,216 @@ +# Copyright 1999-2026 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +LUA_COMPAT=( lua5-4 ) + +inherit lua-single meson xdg + +DESCRIPTION="Multiplayer strategy game (Civilization Clone)" +HOMEPAGE="https://www.freeciv.org/ https://github.com/freeciv/freeciv/" + +if [[ ${PV} == 9999 ]] ; then + inherit git-r3 + EGIT_REPO_URI="https://github.com/freeciv/freeciv/" +else + MY_PV="R${PV//./_}" + SRC_URI="https://github.com/freeciv/freeciv/archive/refs/tags/${MY_PV}.tar.gz -> ${P}.tar.gz" + if [[ ${PV} != *_beta* ]]; then + KEYWORDS="~amd64 ~arm64" + fi + MY_P="${PN}-${MY_PV}" + S="${WORKDIR}/${MY_P}" +fi + +LICENSE="GPL-2+" +SLOT="0" +IUSE="dedicated gtk3 gtk4 json mapimg modpack nls qt6" +IUSE+=" readline rule-editor +sdl3 +server +sound svg +system-lua web-server" + +REQUIRED_USE=" + !dedicated? ( || ( gtk3 gtk4 qt6 sdl3 ) ) + dedicated? ( !gtk3 !gtk4 !mapimg !nls !qt6 !sdl3 !sound ) + sound? ( sdl3 ) + system-lua? ( ${LUA_REQUIRED_USE} ) +" + +RDEPEND=" + app-arch/bzip2 + app-arch/xz-utils + app-arch/zstd:= + dev-build/libtool + dev-db/sqlite:3 + dev-libs/icu:= + net-misc/curl + virtual/zlib:= + !dedicated? ( + media-libs/libpng + gtk3? ( x11-libs/gtk+:3 ) + gtk4? ( gui-libs/gtk:4 ) + mapimg? ( media-gfx/imagemagick:= ) + nls? ( virtual/libintl ) + qt6? ( dev-qt/qtbase:6[gui,widgets] ) + sdl3? ( + media-libs/libsdl3 + media-libs/sdl3-ttf + media-libs/sdl3-image[png] + ) + sound? ( + media-libs/libsdl3 + >=media-libs/sdl3-mixer-3.1.2_rc1[vorbis] + ) + ) + json? ( dev-libs/jansson:= ) + readline? ( sys-libs/readline:= ) + system-lua? ( + ${LUA_DEPS} + ) +" +DEPEND="${RDEPEND} + !dedicated? ( x11-base/xorg-proto ) +" +# Calls gzip during build +BDEPEND=" + app-arch/gzip + virtual/pkgconfig + nls? ( sys-devel/gettext ) +" + +pkg_setup() { + use system-lua && lua-single_pkg_setup + use svg && use !qt6 && einfo "SVG flags only supported in qt6 client, ignoring" +} + +PATCHES=( + "${FILESDIR}/${P}-widget_id-truncation.patch" + "${FILESDIR}/${PN}-3.2.5-sdl2-include.patch" +) + +src_prepare() { + # Upstream's meson.build is not very friendly to our needs + sed -i -e "s:doc/freeciv:doc/${PF}:" meson.build || die + sed -i -e "/custom_target('gzip_ChangeLog/,+6d" meson.build || die + default +} + +src_configure() { + # Docs here: https://github.com/freeciv/freeciv/blob/main/doc/INSTALL.meson + local myclient=() emesonargs=() myfcmp=() + + if use dedicated || use server ; then + emesonargs+=( -Dserver=enabled ) + elif use web-server; then + emesonargs+=( -Dserver=freeciv-web ) + else + emesonargs+=( -Dserver=disabled ) + fi + + # Select any client backends that we want enabled; dedicated server shouldn't build a UI + # for sanity we'll build the modpack bin with the same UIs as the client. + # 'fcmp' = freeciv modpack (client) - gtk3, qt, cli, gtk4 + freeciv_enable_ui() { + local flag=$1 + local client_name=${2:-${flag}} + local fcmp_name=${3:-${client_name}} + + if use ${flag} ; then + myclient+=( ${client_name} ) + # Avoid duplicate `cli` entries; meson will complain + if use modpack && [[ ! " ${myfcmp[*]} " =~ " ${fcmp_name} " ]]; then + myfcmp+=( ${fcmp_name} ) + fi + fi + } + + if ! use dedicated ; then + # there's no SDL modpack backend; rather than incidentally pull in GTK3 (as is default) + # let's explicitly set the backend to CLI + freeciv_enable_ui sdl3 sdl3 cli + freeciv_enable_ui gtk3 gtk3.22 gtk3 + freeciv_enable_ui gtk4 + freeciv_enable_ui qt6 qt + use qt6 && emesonargs+=( -Dqtver=qt6 ) + use qt6 && emesonargs+=( $(meson_use svg svgflags) ) + else + if use modpack ; then + myfcmp+=( cli ) + fi + fi + + # the client and fpmc arrays are now populated (or not for dedicated); let's add them to emesonargs + emesonargs+=( + -Dclients="$(meson-format-array "${myclient[*]}")" + -Dfcmp="$(meson-format-array "${myfcmp[*]}")" + ) + + if use sound; then + emesonargs+=( -Daudio=sdl3 ) + else + # We don't want any audio support; probably a dedicated server + emesonargs+=( -Daudio=none ) + fi + + # If we're building a live ebuild, we want to include the git revision in the version string + if [[ ${PV} == 9999 ]] ; then + emesonargs+=( -Dgitrev=true ) + fi + + local tools=( manual ) # We always want this + # ruleup is the rule-updater; if you're building the editor you probably want this too + # default-enabled upstream + use rule-editor && tools+=( ruledit ruleup ) + emesonargs+=( + -Dtools="$(meson-format-array "${tools[*]}")" + ) + + # Anything that can be trivially set by meson_use goes here + emesonargs+=( + $(meson_use json json-protocol) + $(meson_use mapimg mwand) + $(meson_use nls) + $(meson_use readline) + $(meson_use system-lua syslua) + ) + + meson_src_configure +} + +src_install() { + + meson_src_install + # Create and install the html manual and then cleanup the tool because it's useless. + # TODO: for proper localisation this should be run during postinst but + # that would require a lot of work to avoid orphan files. + # freeciv-manual only supports one ruleset argument at a time. + elog "Generating html manual..." + for RULESET in alien civ1 civ2 civ2civ3 classic multiplayer sandbox + do + $(find "${WORKDIR}" -type d -maxdepth 1 -mindepth 1 -iname '*-build')/freeciv-manual -r ${RULESET} || + die "Unable to generate HTML output for ${RULESET}" + docinto html/rulesets/${RULESET} + dodoc ${RULESET}*.html + done + + find "${ED}" -name "freeciv-manual*" -delete || die "Failed to remove freeciv-manual" + + if use dedicated ; then + elog "Tidying up dedicated server installation..." + find "${ED}"/usr/share/man/man6/ \ + -not \( -name 'freeciv.6' -o -name 'freeciv-ruledit.6' \ + -o -name 'freeciv-ruleup.6' -o -name 'freeciv-server.6' \) -mindepth 1 -delete || die + fi + +} + +pkg_postinst() { + xdg_pkg_postinst + + if [[ -z ${REPLACING_VERSIONS} ]]; then + einfo "There are a number of supported authentication backends." + einfo "sqlite3 is the default, however dedicated servers may wish to" + einfo "use another supported backend; please consult the documentation" + einfo "to configure freeciv for a particular backend:" + einfo "https://github.com/freeciv/freeciv/blob/main/doc/README.fcdb" + fi +} diff --git a/games-strategy/freeciv/freeciv-3.2.5.ebuild b/games-strategy/freeciv/freeciv-3.2.5.ebuild new file mode 100644 index 0000000000000..8525188f750ea --- /dev/null +++ b/games-strategy/freeciv/freeciv-3.2.5.ebuild @@ -0,0 +1,215 @@ +# Copyright 1999-2026 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +LUA_COMPAT=( lua5-4 ) + +inherit lua-single meson xdg + +DESCRIPTION="Multiplayer strategy game (Civilization Clone)" +HOMEPAGE="https://www.freeciv.org/ https://github.com/freeciv/freeciv/" + +if [[ ${PV} == 9999 ]] ; then + inherit git-r3 + EGIT_REPO_URI="https://github.com/freeciv/freeciv/" +else + MY_PV="R${PV//./_}" + SRC_URI="https://github.com/freeciv/freeciv/archive/refs/tags/${MY_PV}.tar.gz -> ${P}.tar.gz" + if [[ ${PV} != *_beta* ]]; then + KEYWORDS="~amd64 ~arm64" + fi + MY_P="${PN}-${MY_PV}" + S="${WORKDIR}/${MY_P}" +fi + +LICENSE="GPL-2+" +SLOT="0" +IUSE="dedicated gtk3 gtk4 json mapimg modpack nls qt6" +IUSE+=" readline rule-editor +sdl3 +server +sound svg +system-lua web-server" + +REQUIRED_USE=" + !dedicated? ( || ( gtk3 gtk4 qt6 sdl3 ) ) + dedicated? ( !gtk3 !gtk4 !mapimg !nls !qt6 !sdl3 !sound ) + sound? ( sdl3 ) + system-lua? ( ${LUA_REQUIRED_USE} ) +" + +RDEPEND=" + app-arch/bzip2 + app-arch/xz-utils + app-arch/zstd:= + dev-build/libtool + dev-db/sqlite:3 + dev-libs/icu:= + net-misc/curl + virtual/zlib:= + !dedicated? ( + media-libs/libpng + gtk3? ( x11-libs/gtk+:3 ) + gtk4? ( gui-libs/gtk:4 ) + mapimg? ( media-gfx/imagemagick:= ) + nls? ( virtual/libintl ) + qt6? ( dev-qt/qtbase:6[gui,widgets] ) + sdl3? ( + media-libs/libsdl3 + media-libs/sdl3-ttf + media-libs/sdl3-image[png] + ) + sound? ( + media-libs/libsdl3 + >=media-libs/sdl3-mixer-3.1.2_rc1[vorbis] + ) + ) + json? ( dev-libs/jansson:= ) + readline? ( sys-libs/readline:= ) + system-lua? ( + ${LUA_DEPS} + ) +" +DEPEND="${RDEPEND} + !dedicated? ( x11-base/xorg-proto ) +" +# Calls gzip during build +BDEPEND=" + app-arch/gzip + virtual/pkgconfig + nls? ( sys-devel/gettext ) +" + +PATCHES=( + "${FILESDIR}/${P}-sdl2-include.patch" +) + +pkg_setup() { + use system-lua && lua-single_pkg_setup + use svg && use !qt6 && einfo "SVG flags only supported in qt6 client, ignoring" +} + +src_prepare() { + # Upstream's meson.build is not very friendly to our needs + sed -i -e "s:doc/freeciv:doc/${PF}:" meson.build || die + sed -i -e "/custom_target('gzip_ChangeLog/,+6d" meson.build || die + default +} + +src_configure() { + # Docs here: https://github.com/freeciv/freeciv/blob/main/doc/INSTALL.meson + local myclient=() emesonargs=() myfcmp=() + + if use dedicated || use server ; then + emesonargs+=( -Dserver=enabled ) + elif use web-server; then + emesonargs+=( -Dserver=freeciv-web ) + else + emesonargs+=( -Dserver=disabled ) + fi + + # Select any client backends that we want enabled; dedicated server shouldn't build a UI + # for sanity we'll build the modpack bin with the same UIs as the client. + # 'fcmp' = freeciv modpack (client) - gtk3, qt, cli, gtk4 + freeciv_enable_ui() { + local flag=$1 + local client_name=${2:-${flag}} + local fcmp_name=${3:-${client_name}} + + if use ${flag} ; then + myclient+=( ${client_name} ) + # Avoid duplicate `cli` entries; meson will complain + if use modpack && [[ ! " ${myfcmp[*]} " =~ " ${fcmp_name} " ]]; then + myfcmp+=( ${fcmp_name} ) + fi + fi + } + + if ! use dedicated ; then + # there's no SDL modpack backend; rather than incidentally pull in GTK3 (as is default) + # let's explicitly set the backend to CLI + freeciv_enable_ui sdl3 sdl3 cli + freeciv_enable_ui gtk3 gtk3.22 gtk3 + freeciv_enable_ui gtk4 + freeciv_enable_ui qt6 qt + use qt6 && emesonargs+=( -Dqtver=qt6 ) + use qt6 && emesonargs+=( $(meson_use svg svgflags) ) + else + if use modpack ; then + myfcmp+=( cli ) + fi + fi + + # the client and fpmc arrays are now populated (or not for dedicated); let's add them to emesonargs + emesonargs+=( + -Dclients="$(meson-format-array "${myclient[*]}")" + -Dfcmp="$(meson-format-array "${myfcmp[*]}")" + ) + + if use sound; then + emesonargs+=( -Daudio=sdl3 ) + else + # We don't want any audio support; probably a dedicated server + emesonargs+=( -Daudio=none ) + fi + + # If we're building a live ebuild, we want to include the git revision in the version string + if [[ ${PV} == 9999 ]] ; then + emesonargs+=( -Dgitrev=true ) + fi + + local tools=( manual ) # We always want this + # ruleup is the rule-updater; if you're building the editor you probably want this too + # default-enabled upstream + use rule-editor && tools+=( ruledit ruleup ) + emesonargs+=( + -Dtools="$(meson-format-array "${tools[*]}")" + ) + + # Anything that can be trivially set by meson_use goes here + emesonargs+=( + $(meson_use json json-protocol) + $(meson_use mapimg mwand) + $(meson_use nls) + $(meson_use readline) + $(meson_use system-lua syslua) + ) + + meson_src_configure +} + +src_install() { + + meson_src_install + # Create and install the html manual and then cleanup the tool because it's useless. + # TODO: for proper localisation this should be run during postinst but + # that would require a lot of work to avoid orphan files. + # freeciv-manual only supports one ruleset argument at a time. + elog "Generating html manual..." + for RULESET in alien civ1 civ2 civ2civ3 classic multiplayer sandbox + do + $(find "${WORKDIR}" -type d -maxdepth 1 -mindepth 1 -iname '*-build')/freeciv-manual -r ${RULESET} || + die "Unable to generate HTML output for ${RULESET}" + docinto html/rulesets/${RULESET} + dodoc ${RULESET}*.html + done + + find "${ED}" -name "freeciv-manual*" -delete || die "Failed to remove freeciv-manual" + + if use dedicated ; then + elog "Tidying up dedicated server installation..." + find "${ED}"/usr/share/man/man6/ \ + -not \( -name 'freeciv.6' -o -name 'freeciv-ruledit.6' \ + -o -name 'freeciv-ruleup.6' -o -name 'freeciv-server.6' \) -mindepth 1 -delete || die + fi + +} + +pkg_postinst() { + xdg_pkg_postinst + + if [[ -z ${REPLACING_VERSIONS} ]]; then + einfo "There are a number of supported authentication backends." + einfo "sqlite3 is the default, however dedicated servers may wish to" + einfo "use another supported backend; please consult the documentation" + einfo "to configure freeciv for a particular backend:" + einfo "https://github.com/freeciv/freeciv/blob/main/doc/README.fcdb" + fi +} diff --git a/games-strategy/freeciv/freeciv-9999.ebuild b/games-strategy/freeciv/freeciv-9999.ebuild index c58ea93ec1b5d..1ff7691339974 100644 --- a/games-strategy/freeciv/freeciv-9999.ebuild +++ b/games-strategy/freeciv/freeciv-9999.ebuild @@ -17,7 +17,7 @@ else MY_PV="R${PV//./_}" SRC_URI="https://github.com/freeciv/freeciv/archive/refs/tags/${MY_PV}.tar.gz -> ${P}.tar.gz" if [[ ${PV} != *_beta* ]]; then - KEYWORDS="~amd64 ~ppc64 ~x86" + KEYWORDS="~amd64 ~arm64 ~ppc64 ~x86" fi MY_P="${PN}-${MY_PV}" S="${WORKDIR}/${MY_P}" @@ -179,7 +179,7 @@ src_install() { # that would require a lot of work to avoid orphan files. # freeciv-manual only supports one ruleset argument at a time. elog "Generating html manual..." - for RULESET in alien civ1 civ2 civ2civ3 classic goldkeep multiplayer sandbox + for RULESET in alien civ1 civ2 civ2civ3 classic multiplayer sandbox do $(find "${WORKDIR}" -type d -maxdepth 1 -mindepth 1 -iname '*-build')/freeciv-manual -r ${RULESET} || die "Unable to generate HTML output for ${RULESET}"