Skip to content

fix(linux): POSIX sh launch wrappers for all executables; load GL via system GLEW - #76

Merged
mcoliver merged 11 commits into
mainfrom
fix/linux-launch-and-mesa-gl
Oct 1, 2026
Merged

mcoliver merged 11 commits into
mainfrom
fix/linux-launch-and-mesa-gl

Conversation

@mcoliver

@mcoliver mcoliver commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #66. Fixes #68.

Linux builds couldn't run their own tools: the launch wrappers were lost in the rv → utv rename, and binaries linked OpenGL extension functions that Mesa's libGL doesn't export. This PR fixes both, and Linux CI now runs the full test suite against the result.

#66: Linux launch wrappers

  • rv_stage now wraps every Linux executable (renaming the binary to <name>.bin). It uses the target's own <target>.wrapper if present, otherwise the new generic src/bin/linux_wrapper.sh. Previously the <target>.wrapper lookup no longer matched the renamed utv* targets, so utvio, utvls, utvpkg, utvpush, utvshell, utvprof and utv had no wrapper.
  • The wrappers are POSIX sh (no tcsh dependency). They resolve symlinks (rv, rvio, …) with readlink -f and exec <name>.bin.
  • Library path: UTV's lib/, the bundled OpenSSL (unless RV_USE_SYSTEM_OPENSSL), and the dependency prefix (UTV_DEPS_ROOT, else Homebrew) using each formula's own opt/<formula>/lib[64].
  • The GL driver always comes from the system:
    • Homebrew's mesa, libglvnd, libdrm, llvm*, libpciaccess and libxshmfence are skipped.
    • The system libGL.so.1/libEGL.so.1 (found via ldconfig) are preloaded.
    • Without this, Homebrew's software Mesa, pulled in as a dependency of glew, replaced the system/GPU driver through library RUNPATHs.
    • UTV_NO_SYSTEM_GL_PRELOAD=1 disables the preload.
  • The main app keeps its extras (-d/--debug via gdb, padsp, unsetting QT_PLUGIN_PATH/LANG) in src/bin/apps/rv/utv.wrapper. The 16 per-tool tcsh wrappers are removed.

#68: OpenGL on Mesa

  • TWK_USE_GLEW on Linux: GL entry points are loaded through the system GLEW (shared libGLEW, one function table for all modules) instead of being linked directly (GL_GLEXT_PROTOTYPES), as Windows does with its bundled GLEW.
  • TWK_GLEW_INIT(proc) in TwkGLF/GL.h: glewInit(proc) for the bundled Windows GLEW. On Linux it calls glewInit() and treats GLEW_ERROR_NO_GLX_DISPLAY as success, so it works with GLEW 2.2 (distros) and 2.3 (Homebrew), under GLX and EGL/Wayland.
  • utvio's offscreen GLX device (FBOVideoDevice):
    • initializes GLEW;
    • sets CWBorderPixel (X rejects a window whose visual depth differs from the root's without it);
    • reports missing display/visual/context clearly;
    • installs an X error handler that logs and continues. The renderer issues a glXMakeCurrent from a second thread; GLX reports BadAccess, and Xlib's default handler was exiting the process.
  • Include order: GLEW is included before gl.h in the Linux paths that mix Qt/Python headers and GL (MuUICommands.cpp, PyUICommands.cpp, …).
  • OSMesa: TwkGLFMesa compiles with TWK_USE_MESA, which keeps GLEW out of it.

CI

  • The Linux ctest step no longer sets LD_LIBRARY_PATH (the wrappers do it) and no longer excludes LoadingSharedLibrariesTest or image-format-roundtrip. utvio is no longer an expected failure in cli-smoke.
  • It also runs one utvio render under Xvfb and prints the output, as a debugging aid.
  • Result: Linux 178/178 tests pass, including all 58 LoadingSharedLibrariesTest cases, cli-smoke, and the image format round-trip. macOS and Windows are green.

Known issues left open

🤖 Generated with Claude Code

… system GLEW

Two Linux runtime problems found by the new CI tests.

#66 -- launch wrappers
- The rv->utv target rename broke the <target>.wrapper lookup in
  rv_stage, so utvio, utvls, utvpkg, utvpush, utvshell, utvprof and the
  main app were staged without wrappers and could not find their
  libraries. The wrappers also required tcsh and hard-coded binary names.
- rv_stage now installs a wrapper for every Linux executable: the
  target's own <target>.wrapper if present, otherwise the new generic
  src/bin/linux_wrapper.sh. Both are POSIX sh, resolve symlinks (rv,
  rvio, ...) with readlink -f, exec <name>.bin, and put UTV's lib,
  bundled OpenSSL and the dependency prefix (UTV_DEPS_ROOT, or Homebrew
  incl. opt/*/lib) on LD_LIBRARY_PATH.
- The main app keeps its extras (-d/--debug via gdb, padsp, unsetting
  QT_PLUGIN_PATH/LANG) in src/bin/apps/rv/utv.wrapper; the 16 per-tool
  tcsh wrappers are removed.

#68 -- GL extension entry points on Mesa
- Linux linked GL extension functions directly (GL_GLEXT_PROTOTYPES),
  which Mesa's libGL does not export (e.g. glBlitFramebufferEXT), so
  binaries failed to load on AMD/Intel/software GL.
- Define TWK_USE_GLEW on Linux and load entry points through the system
  GLEW 2.x (shared libGLEW, already linked by TwkGLF), as Windows does
  with its bundled GLEW.
- New TWK_GLEW_INIT(proc) in TwkGLF/GL.h: glewInit(proc) for the bundled
  Windows GLEW; glewContextInit() on Linux, which does not require a GLX
  display and so also works with EGL (Qt on Wayland).
- Initialize GLEW in utvio's offscreen GLX context (FBOVideoDevice) and
  include GLEW before gl.h in the Linux paths that mix Qt and GL.

CI: the Linux ctest step no longer sets LD_LIBRARY_PATH or excludes
tests, and utvio is no longer an expected failure in cli-smoke.

Fixes #66
Fixes #68

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
TwkGLFMesa includes osmesa.h, which needs the GLAPI macro from Mesa's
gl.h; glew.h (pulled in through TwkGLF/GL.h now that Linux uses GLEW)
undefines it. Compile the library with TWK_USE_MESA, the existing switch
in GL.h for this case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
… GLEW

MuUICommands.cpp and PyUICommands.cpp included TwkGLF/GL.h first only on
Windows, so on Linux Qt/Python headers pulled in gl.h before glew.h.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
- FBOVideoDevice created its hidden GLX window with the visual's depth
  (32-bit ARGB on Mesa) under a 24-bit root without CWBorderPixel, which
  X rejects with BadMatch, killing utvio. Set border_pixel.
- format_roundtrip: report the "X Error" line for X11 protocol errors.
- Linux CI: exclude ApplicationTest and AudioRendererTest, which now load
  (#68) but crash in their test bodies (#78).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
- Launch wrappers added every Homebrew opt/*/lib (and the combined lib/)
  to LD_LIBRARY_PATH. Homebrew installs its own Mesa, libdrm and LLVM as
  glew dependencies, so its software libGL replaced the system driver:
  on CI that meant a 32-bit visual and X errors in utvio (BadMatch, then
  BadAccess), and on NVIDIA desktops it would have replaced the GPU
  driver. Use per-formula lib/lib64 directories only, skip mesa,
  libglvnd, libdrm, llvm*, libpciaccess and libxshmfence, and fall back
  to <prefix>/lib for a plain (non-Homebrew) UTV_DEPS_ROOT.
- Distro GLEW 2.2 (e.g. Ubuntu 24.04) doesn't export glewContextInit().
  TWK_GLEW_INIT now calls glewInit() and treats GLEW_ERROR_NO_GLX_DISPLAY
  (EGL context: GL entry points already loaded) as success, which works
  with GLEW 2.2 and 2.3 under GLX and EGL.

Verified locally in an Ubuntu 24.04 container: the utvio GLX setup under
Xvfb with the system Mesa gets a 24-bit visual, llvmpipe, a complete
RGBA16F FBO and reads back 4.0; the wrapper resolves rvio -> utvio.bin,
skips the GL stack kegs and preserves arguments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
TwkGLFMesa compiles with TWK_USE_MESA, which keeps glew.h out of
TwkGLF/GL.h; the inline helper referenced GLEW symbols there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
Removing Homebrew's Mesa from LD_LIBRARY_PATH wasn't enough: Homebrew
libraries (e.g. libGLEW, Qt) carry a RUNPATH to the Homebrew prefix, so
their libGL.so.1 dependency still resolved to Homebrew's software Mesa
(CI: X BadAccess in utvio under Xvfb). Preload the system libGL.so.1 and
libEGL.so.1 (found via ldconfig) so every reference uses the system
driver. UTV_NO_SYSTEM_GL_PRELOAD=1 disables it.

CI now logs which GL libraries utvio loads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
… render diagnostic

Xlib's default error handler exits the process, which turned any X
protocol error during utvio's offscreen rendering into a failed write
with only "X Error of failed request: BadAccess" to go on. Install a
handler in FBOVideoDevice that logs the error with its request codes and
continues (as Qt does). CI also runs one utvio render under Xvfb and
prints its output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
With utvio rendering working on Linux, 33 of 34 writable formats now
round-trip; reading back the FITS file segfaults. Track it with the
Windows FITS read-back failure in #67.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
It confirmed the launch wrappers load the system libGL; the one-render
diagnostic stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Signed-off-by: Michael Oliver <mcoliver@gmail.com>
@mcoliver
mcoliver marked this pull request as ready for review October 1, 2026 16:26
@mcoliver
mcoliver merged commit 4b73525 into main Oct 1, 2026
13 checks passed
@mcoliver mcoliver mentioned this pull request Oct 2, 2026
1 task done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant