Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 55 additions & 2 deletions .github/workflows/linux-verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ jobs:
steps:
- uses: actions/checkout@v6

- uses: actions/setup-python@v6
with:
python-version: '3.12'

- name: Install pinned Meson
run: python -m pip install meson==1.9.1

- name: Install i686 Meson build dependencies
run: |
sudo dpkg --add-architecture i386
Expand All @@ -74,19 +81,28 @@ jobs:
gcc-multilib \
g++-multilib \
glslang-tools \
cmake \
libdbus-1-dev:i386 \
libegl-dev:i386 \
libc6-dev-i386 \
libgl-dev:i386 \
libpipewire-0.3-dev:i386 \
libudev-dev:i386 \
libwayland-dev:i386 \
libx11-dev:i386 \
libxcursor-dev:i386 \
libxext-dev:i386 \
libxi-dev:i386 \
libxkbcommon-dev:i386 \
libxrandr-dev:i386 \
libxxf86dga-dev:i386 \
libxxf86vm-dev:i386 \
linux-libc-dev:i386 \
mesa-common-dev:i386 \
meson \
ninja-build \
pkg-config \
python3
python3 \
wayland-protocols

- name: Build dependency-isolated i686 dedicated server
run: |
Expand Down Expand Up @@ -129,3 +145,40 @@ jobs:

- name: Run complete i686 regression suite
run: meson test -C .tmp/meson-linux-renderers --print-errorlogs

- name: Build bundled SDL3 i686 client
run: |
meson setup .tmp/meson-linux-sdl \
--cross-file misc/meson/linux-x86.ini \
--buildtype=debugoptimized \
--force-fallback-for=sdl3,fontstash \
-Daudio-tests=false \
-Dbuild-client=true \
-Dbuild-server=false \
-Dcurl=disabled \
-Dglx-tests=false \
-Dogg-vorbis=false \
-Drenderer-dlopen=false \
-Drenderer-default=glx \
-Dsdl=enabled
meson compile -C .tmp/meson-linux-sdl fnql
file .tmp/meson-linux-sdl/fnql | grep -F 'ELF 32-bit LSB'
file .tmp/meson-linux-sdl/fnql | grep -F 'Intel 80386'

- name: Build CMake i686 dedicated server
run: |
cmake -S . -B .tmp/cmake-linux-server -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS=-m32 \
-DCMAKE_CXX_FLAGS=-m32 \
-DCMAKE_EXE_LINKER_FLAGS=-m32 \
-DCMAKE_SHARED_LINKER_FLAGS=-m32 \
-DFNQL_AUDIO_LOOPBACK_TESTS=OFF \
-DFNQL_GLX_LOGIC_TESTS=OFF \
-DUSE_CURL=OFF \
-DUSE_OGG_VORBIS=OFF \
-DUSE_SDL=OFF \
-DUSE_SYSTEM_JPEG=OFF
cmake --build .tmp/cmake-linux-server --parallel 2 --target fnql.ded
file .tmp/cmake-linux-server/fnql.ded | grep -F 'ELF 32-bit LSB'
file .tmp/cmake-linux-server/fnql.ded | grep -F 'Intel 80386'
2 changes: 1 addition & 1 deletion .install/README.html
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ <h3>Native Linux dedicated server</h3>
</ol>
</article>
</div>
<p class="footer">Official releases support the Windows Win32/x86 retail client and Linux i686 dedicated server. Retail ships no native Linux client/UI modules and no macOS game, client, UI, or QVM modules, so FnQL publishes no macOS package and makes no native macOS retail-play claim.</p>
<p class="footer">Official releases support the Windows Win32/x86 retail client and Linux i686 dedicated server. Retail <code>bin.pk3</code> includes native <code>qagamei386.so</code> and <code>qagamex64.so</code> server modules, so the Linux server loads the i386 ELF directly rather than attempting to load the Win32 PE DLL. Retail ships no native Linux client/UI modules and no macOS game, client, UI, or QVM modules, so FnQL publishes no macOS package and makes no native macOS retail-play claim.</p>
<p class="footer">FnQL locates conventional Steam libraries automatically. For a custom library, start it with <code>+set fs_steampath "&lt;Quake Live folder&gt;"</code>. Steam and WebUI features fail safely when optional runtime components are unavailable.</p>
<p class="footer">To compile FnQL yourself, use the <a href="https://github.com/themuffinator/FnQL/blob/main/BUILD.md">Build Guide</a>.</p>
</section>
Expand Down
25 changes: 24 additions & 1 deletion BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ Linux has two distinct compatibility surfaces:

- Native dedicated servers load the retail `qagamei386.so` from
`baseq3/bin.pk3`; FnQL does not build or validate the x86_64 alternative.
- The same retail archive also contains `qagamex64.so` and the Win32
`qagamex86.dll`, `cgamex86.dll`, and `uix86.dll`. Native Linux i686 uses
`qagamei386.so`; `dlopen` cannot load PE32 DLLs, so the Linux server does not
rename or emulate the Windows module.
- Retail Quake Live does not ship native Linux `cgame` or UI modules; those
modules and the retained Awesomium WebUI runtime are Win32-only. Native Linux
client builds are maintained engine/platform development targets, but are not
Expand Down Expand Up @@ -192,9 +196,13 @@ legacy X11 backend using system development packages while Meson fetches only
missing wrap fallbacks (including the required pinned FontStash source):

```sh
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install gcc-multilib g++-multilib libc6-dev-i386 \
linux-libc-dev:i386 git meson ninja-build pkg-config python3
libgl-dev:i386 libx11-dev:i386 libxext-dev:i386 \
libxrandr-dev:i386 libxxf86dga-dev:i386 libxxf86vm-dev:i386 \
linux-libc-dev:i386 mesa-common-dev:i386 \
git glslang-tools meson ninja-build pkg-config python3
meson setup meson/build-linux-x86 \
--cross-file misc/meson/linux-x86.ini \
--buildtype=debugoptimized -Dsdl=disabled -Dcurl=disabled \
Expand All @@ -208,6 +216,21 @@ OpenAL, cURL, JPEG, Ogg/Vorbis, and X11 development packages. The release
workflow is the canonical dependency baseline when distribution package names
differ.

The bundled SDL3 fallback additionally needs its Linux platform dependencies.
On Ubuntu 24.04, install them and exercise the same i686 path used by Linux CI:

```sh
sudo apt install libdbus-1-dev:i386 libegl-dev:i386 \
libpipewire-0.3-dev:i386 libudev-dev:i386 libwayland-dev:i386 \
libxcursor-dev:i386 libxi-dev:i386 libxkbcommon-dev:i386 wayland-protocols
meson setup meson/build-linux-sdl-x86 \
--cross-file misc/meson/linux-x86.ini \
--force-fallback-for=sdl3,fontstash \
-Dbuild-server=false -Dcurl=disabled -Dogg-vorbis=false \
-Drenderer-dlopen=false -Drenderer-default=glx -Dsdl=enabled
meson compile -C meson/build-linux-sdl-x86 fnql
```

Stage a build without writing into the Steam library, verify it, and then copy
the whole flat runtime root together:

Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,11 @@ Retail Quake Live ships native Linux server modules, but its client and WebUI
modules are Win32-only. The native Linux client executable is therefore an
engine/platform development target, not a supported retail-play path. Use the
Win32/x86 package for retail client play and the Linux i686 package for native
dedicated hosting. FnQL does not support or build macOS because retail ships no
macOS game, client, UI, or QVM modules, and FnQL will not reconstruct them.
dedicated hosting. Retail `bin.pk3` contains `qagamei386.so` and
`qagamex64.so`; the i686 server loads the former directly and does not try to
load or rename the Win32 PE DLLs. FnQL does not support or build macOS because
retail ships no macOS game, client, UI, or QVM modules, and FnQL will not
reconstruct them.
FnQL discovers conventional Steam
libraries on each supported OS; for a custom library use
`+set fs_steampath "<Quake Live folder>"`. Optional Steam and WebUI services
Expand Down
27 changes: 26 additions & 1 deletion code/rendererrtx/shaders/spirv/shader_reflection.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schema": "q3rtx.rendererrtx.shader_reflection.v1",
"generator": "code/rendererrtx/shaders/build_shaders.py",
"shader_count": 88,
"shader_count": 89,
"shaders": [
{
"symbol": "color_vert_spv",
Expand Down Expand Up @@ -415,6 +415,31 @@
"push_constants": []
}
},
{
"symbol": "menu_blur_frag_spv",
"source": "menu_blur.frag",
"stage": "frag",
"defines": [],
"byte_size": 1532,
"reflection": {
"descriptor_bindings": [
{
"name": "texture0",
"set": 0,
"binding": 0,
"storage_class": "UniformConstant",
"descriptor_class": "combined_image_sampler",
"descriptor_count": 1
}
],
"push_constants": [
{
"name": "pc",
"size_bytes": 16
}
]
}
},
{
"symbol": "motion_blur_frag_spv",
"source": "motion_blur.frag",
Expand Down
1 change: 1 addition & 0 deletions code/unix/linux_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ char *strlwr (char *s);

// signals.c
void InitSig(void);
void Sys_HandlePendingSignals(void);

#ifdef __cplusplus
}
Expand Down
56 changes: 45 additions & 11 deletions code/unix/linux_signals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#endif

static qboolean signalcaught = qfalse;
static volatile sig_atomic_t pendingShutdownSignal = 0;

extern void NORETURN Sys_Exit( int code );

static void signal_handler( int sig )
static void shutdown_signal_handler( int sig )
{
pendingShutdownSignal = sig;
}


static void fatal_signal_handler( int sig )
{
char msg[32];

Expand Down Expand Up @@ -72,16 +79,43 @@ static void signal_handler( int sig )
}


void Sys_HandlePendingSignals( void )
{
const int sig = pendingShutdownSignal;
char msg[32];

if ( sig == 0 )
{
return;
}

pendingShutdownSignal = 0;
printf( "Received signal %d, exiting...\n", sig );
Com_sprintf( msg, sizeof( msg ), "Signal caught (%d)", sig );
VM_Forced_Unload_Start();
#ifndef DEDICATED
CL_Shutdown( msg, qtrue );
#endif
SV_Shutdown( msg );
VM_Forced_Unload_Done();
Sys_Exit( 0 );
}


void InitSig( void )
{
signal( SIGINT, SIG_IGN );
signal( SIGHUP, signal_handler );
signal( SIGQUIT, signal_handler );
signal( SIGILL, signal_handler );
signal( SIGTRAP, signal_handler );
signal( SIGIOT, signal_handler );
signal( SIGBUS, signal_handler );
signal( SIGFPE, signal_handler );
signal( SIGSEGV, signal_handler );
signal( SIGTERM, signal_handler );
/* Keep interactive dedicated servers manageable from a normal terminal.
* Retail's Linux signal setup does not ignore SIGINT, and treating Ctrl+C
* like the existing service-stop signals gives FnQL a chance to shut down
* the retail game module and server state cleanly. */
signal( SIGINT, shutdown_signal_handler );
signal( SIGHUP, shutdown_signal_handler );
signal( SIGQUIT, shutdown_signal_handler );
signal( SIGTERM, shutdown_signal_handler );
signal( SIGILL, fatal_signal_handler );
signal( SIGTRAP, fatal_signal_handler );
signal( SIGIOT, fatal_signal_handler );
signal( SIGBUS, fatal_signal_handler );
signal( SIGFPE, fatal_signal_handler );
signal( SIGSEGV, fatal_signal_handler );
}
2 changes: 2 additions & 0 deletions code/unix/unix_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,8 @@ int main( int argc, const char* argv[] )

while (1)
{
Sys_HandlePendingSignals();

#ifdef __linux__
Sys_ConfigureFPU();
#endif
Expand Down
7 changes: 5 additions & 2 deletions docs/templates/README.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,11 @@ Retail Quake Live ships native Linux server modules, but its client and WebUI
modules are Win32-only. The native Linux client executable is therefore an
engine/platform development target, not a supported retail-play path. Use the
Win32/x86 package for retail client play and the Linux i686 package for native
dedicated hosting. FnQL does not support or build macOS because retail ships no
macOS game, client, UI, or QVM modules, and FnQL will not reconstruct them.
dedicated hosting. Retail `bin.pk3` contains `qagamei386.so` and
`qagamex64.so`; the i686 server loads the former directly and does not try to
load or rename the Win32 PE DLLs. FnQL does not support or build macOS because
retail ships no macOS game, client, UI, or QVM modules, and FnQL will not
reconstruct them.
FnQL discovers conventional Steam
libraries on each supported OS; for a custom library use
`+set fs_steampath "<Quake Live folder>"`. Optional Steam and WebUI services
Expand Down
2 changes: 1 addition & 1 deletion docs/templates/install-readme.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@
</ol>
</article>
</div>
<p class="footer">Official releases support the Windows Win32/x86 retail client and Linux i686 dedicated server. Retail ships no native Linux client/UI modules and no macOS game, client, UI, or QVM modules, so FnQL publishes no macOS package and makes no native macOS retail-play claim.</p>
<p class="footer">Official releases support the Windows Win32/x86 retail client and Linux i686 dedicated server. Retail <code>bin.pk3</code> includes native <code>qagamei386.so</code> and <code>qagamex64.so</code> server modules, so the Linux server loads the i386 ELF directly rather than attempting to load the Win32 PE DLL. Retail ships no native Linux client/UI modules and no macOS game, client, UI, or QVM modules, so FnQL publishes no macOS package and makes no native macOS retail-play claim.</p>
<p class="footer">FnQL locates conventional Steam libraries automatically. For a custom library, start it with <code>+set fs_steampath "&lt;Quake Live folder&gt;"</code>. Steam and WebUI features fail safely when optional runtime components are unavailable.</p>
<p class="footer">To compile FnQL yourself, use the <a href="https://github.com/themuffinator/FnQL/blob/main/BUILD.md">Build Guide</a>.</p>
</section>
Expand Down
3 changes: 3 additions & 0 deletions misc/meson/linux-x86.ini
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ pkg_config_libdir = ['/usr/lib/i386-linux-gnu/pkgconfig', '/usr/share/pkgconfig'

[host_machine]
system = 'linux'
# The bundled SDL3 Meson fallback queries subsystem() while selecting HID
# sources; Meson cannot infer this value for a Linux cross build.
subsystem = 'linux'
cpu_family = 'x86'
cpu = 'i686'
endian = 'little'
19 changes: 19 additions & 0 deletions tests/ci_regression_workflow_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ def test_every_pull_request_runs_the_complete_i686_meson_suite(self) -> None:
workflow,
)

def test_linux_ci_keeps_sdl3_and_cmake_on_the_i686_target(self) -> None:
workflow = (ROOT / ".github" / "workflows" / "linux-verification.yml").read_text(
encoding="utf-8"
)

self.assertIn("Build bundled SDL3 i686 client", workflow)
self.assertIn("actions/setup-python@v6", workflow)
self.assertIn("python -m pip install meson==1.9.1", workflow)
self.assertIn("libxcursor-dev:i386", workflow)
self.assertIn("libxi-dev:i386", workflow)
self.assertIn("--force-fallback-for=sdl3,fontstash", workflow)
self.assertIn("-Dsdl=enabled", workflow)
self.assertIn("meson-linux-sdl fnql", workflow)
self.assertIn("Build CMake i686 dedicated server", workflow)
self.assertIn("-DCMAKE_C_FLAGS=-m32", workflow)
self.assertIn("-DCMAKE_CXX_FLAGS=-m32", workflow)
self.assertIn("--target fnql.ded", workflow)
self.assertNotIn("x86_64", workflow)

def test_release_source_validation_uses_recursive_pytest_discovery(self) -> None:
workflow = (ROOT / ".github" / "workflows" / "release.yml").read_text(
encoding="utf-8"
Expand Down
Loading
Loading