Revive the Linux (SDL2 / GTK3) build - #67
Merged
Merged
Conversation
morozov
force-pushed
the
linux-sdl-gtk-build
branch
from
August 8, 2026 00:29
d713d16 to
c4f57d3
Compare
Member
Author
|
The failure is unrelated. The workflow pulls an unpinned libspectrum dependency: fusex/.github/workflows/build_windows.yml Lines 12 to 14 in 2a8006a The commit that breaks the build: fuse-emulator/libspectrum@9b0aa02. The upstream commit that fixes the build: fuse-emulator/libspectrum@a45ca72. UPD: fixed by #69. |
rzx.h declares functions returning GSList* but includes only libspectrum.h. Since 2003 libspectrum's public header has deliberately not pulled in <glib.h> -- upstream commit "Don't include <glib.h> in libspectrum.h; makes it easy to include from other projects" -- so every consumer that uses a glib type is expected to include <glib.h> itself, as event.h, keyboard.c, tape.c and friends already do under HAVE_LIB_GLIB. rzx.h never got that include. The omission has been latent in upstream Fuse for years, masked by include ordering (most translation units reach rzx.h only after something else has already pulled in glib). It surfaces on a real-GLib libspectrum build (as required by the GTK UI) via a unit that reaches rzx.h first -- e.g. peripherals/joystick.c -- which then fails with "unknown type name 'GSList'". Add the guarded include, following the established convention.
sdljoystick.c is shared with the GTK build via a textual #include of the .c file. Its include of "ui.h" -- upstream spells it "ui/ui.h", as the very next line already does for "ui/uijoystick.h" -- resolves against the source file's own directory, ui/sdl/, where no ui.h exists, so the GTK build fails with "ui.h: No such file or directory". Restore the upstream include path.
FuseX defines a per-UI macro for every user interface it builds (UI_WIN32, UI_GTK, UI_SDL, ...) except the Cocoa app, whose Xcode target sets no UI macro at all. That left shared core code unable to tell the Cocoa build apart from the portable autotools builds, so it leaned on "not Win32" as a proxy for "is Cocoa" -- which silently swept in the SDL/GTK/Xlib builds and broke them. Define UI_COCOA in the Cocoa build's config.h so those call sites can name the Cocoa build positively, and convert the first of them: machine.c gated its SetEmulationHz stub on __APPLE__, which excluded the stub from autotools builds on macOS as well and left them unable to link, the real implementation being in fusepb/FuseMenus.m. It also enables the two commits that follow.
FuseX renamed the emulator entry from upstream's main() to old_main() for every non-Win32 build, so its Cocoa app could supply its own main(). That also stripped main() from the autotools UIs (SDL, GTK, Xlib, ...), which then failed to link with "undefined reference to main". Select old_main() via UI_COCOA rather than "everything that is not Win32": Win32 keeps fuse_main() (called from WinMain), the Cocoa build keeps old_main() (unused there, as Cocoa drives the emulator itself), and every other build gets main() as upstream intended.
Upstream references the 32-bit scaler routines (scaler_Normal1x_32, ...) directly in the scaler table. FuseX wrapped that column in a SCALER32() macro that expands to the real routine only under _WIN32 and to NULL otherwise, because its Cocoa Xcode project compiles only scalers16.o and the _32 symbols do not exist there. The autotools build always links scalers32.o, and FuseX's GTK display renders at 32bpp and calls scaler_proc32, so on Linux that NULL was a guaranteed crash the moment a frame was drawn. Gate the macro on UI_COCOA instead: the real routines are used everywhere they are compiled, and only the 16bpp-only Cocoa build (which never calls scaler_proc32) keeps NULL. Also stub uidisplay_set_next_hotswap_reason in scalerexpandtest, alongside the ui_error and uidisplay_hotswap_gfx_mode stubs already there. The test links ui/scaler/scaler.c without ui.c, and FuseX's hotswap call in scaler_select_scaler left it undefined; since the test is in noinst_PROGRAMS, that broke plain "make" on every autotools platform.
Upstream Fuse ships a single, portable settings generator (settings.pl, libxml2/INI backed). FuseX rewrote it to emit Objective-C backed by NSUserDefaults for the Cocoa app, which cannot compile anywhere else -- the autotools build's settings.c pulled in <Foundation/...> and failed immediately. Rather than fork a third, parallel generator for Linux, teach the existing settings.pl both dialects behind a --cocoa flag: with it, the Objective-C used by the Cocoa app (fusepb now passes --cocoa); without it, portable C for the autotools builds (the default the Makefile.am rule already invokes). The parts driven by settings.dat alone -- the defaults table, settings_init, the getopt_long option set, settings_copy, settings_get_rom_setting and settings_set_string -- are emitted once and shared by both dialects; only the config file I/O, the string ownership rules and the Cocoa-only ROM array bridging are emitted per mode. The Cocoa output changes only in the #line directives the shared sections now emit and in --no-banner moving from 444 to 256. The portable build gains --no-banner, which until now existed only in the Cocoa output. The portable read_config_file also keeps upstream 1.9.1's behaviour of parsing into a scratch copy and warning rather than failing: an unreadable or unparseable config file leaves the defaults in place instead of aborting startup. The portable INI reader recognises the settings that only the Cocoa build stores, rather than reporting them as unknown, and bounds that report to the offending line, since utils_read_file does not NUL terminate the buffer. --no-banner takes the reserved getopt_long value 256, leaving the generated options to run from 257 where they cannot collide with it.
Two FuseX menu additions never accounted for the widget/GTK UIs:
* "Help/Check for Updates..." is wired to menu_help_check_for_updates,
which only exists in the Win32 WinSparkle backend. The widget and GTK
builds failed to link. Gate the menu entry to UI_WIN32 (the Cocoa app
drives updates from its own XIB menus, not menu_data.dat).
* menu_machine_debuglog did (void)action; but the GTK MENU_CALLBACK
signature has no action parameter, so the GTK build failed to compile.
Drop the line -- other no-op callbacks (e.g. menu_machine_nmi) already
leave the body empty.
The whole xfs filesystem lived behind BUILD_SPECTRANET, but the GDB vfile debugger feature -- compiled unconditionally and used by gdbserver.c -- depends on the RAM-backed xfs engine. With Spectranet off (the default when pthreads/sockets are unavailable) the link failed on xfs_ram_engine and xfs_reset. Split xfs: the core (xfs.c, xfs_worker.c, xfs_fs.c) is now always built, while only the network engines (xfs_https.c) and their HTTP/TLS/SSH stack stay Spectranet-only. The http/https branches of the mount dispatcher in xfs.c are guarded by BUILD_SPECTRANET so it references those engines only when they are compiled.
morozov
force-pushed
the
linux-sdl-gtk-build
branch
from
August 8, 2026 16:18
c4f57d3 to
153ee31
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The portable
./configure && makeUIs had stopped building: FuseX's macOS/Windows additions were made without accounting for them. This gets GTK 3 and SDL 2 compiling and running again on Linux (a 48K image boots to BASIC under both), without adding any Linux-only machinery — each fix restores upstream behaviour or teaches an existing mechanism to cover the portable builds. Commits are split into upstream-Fuse fixes first, FuseX-specific fixes on top.Upstream-Fuse
rzx.h— include<glib.h>for theGSListdeclarations (libspectrum.hno longer pulls it in).ui/sdl/sdljoystick.c— fix the include (ui.h→ui/ui.h).FuseX-specific
These gate on a
UI_COCOAmacro rather than "not Win32":fusepb/config.h— add theUI_COCOAmacro.fuse.c— keepmain()for the portable UIs;old_main()only under Cocoa.ui/scaler/scaler.c— build the 32-bit scalers everywhere except Cocoa (GTK renders at 32bpp and was crashing on a NULL scaler).settings.pl— emit portable C by default, Objective-C only under--cocoa.menu_data.dat/menu.c— gate the WinSparkle "Check for Updates" item to Win32 and fix the GTK debug-log callback.peripherals/fs/xfs.c+Makefile.am— always build the xfs RAM engine (the GDBvfilefeature needs it); keep only the network engines Spectranet-only.Building on Linux