Create libtcod-headless fork for SDL-free builds #134

Closed
opened 2025-11-26 15:44:18 +00:00 by john · 2 comments
Owner

Overview

Create a fork of libtcod called libtcod-headless that builds without SDL dependencies. This fulfills a long-standing community request for "ASCII-only" or "SDL-free" libtcod, and since McRogueFace implements its own graphical layer via SFML, we are naturally positioned to provide and maintain this.

Key Discovery

libtcod 2.2.1 already has extensive NO_SDL compile-time guards!

When built with -DLIBTCOD_SDL3=disable, libtcod:

  • Compiles successfully with only libz, libstdc++, libm, libgcc_s, libc dependencies
  • Removes all SDL3 runtime dependencies
  • Still provides all core algorithms (FOV, pathfinding, BSP, noise, etc.)

Tested build:

cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON \
    -DCMAKE_TOOLCHAIN_FILE="" \
    -DLIBTCOD_SDL3=disable \
    -DLIBTCOD_LODEPNG=vendored \
    -DLIBTCOD_UTF8PROC=vendored \
    -DLIBTCOD_STB=vendored

# Output library dependencies (no SDL!):
#   NEEDED: libz.so.1, libstdc++.so.6, libm.so.6, libgcc_s.so.1, libc.so.6

Implementation Notes

Minimal Changes Required

The fork should be a "light-touch modification" that can be easily rebased on each libtcod release:

  1. CMakeLists.txt changes:

    • Change default: set(LIBTCOD_SDL3 "disable" CACHE STRING ...)
    • Or add a new top-level option: set(LIBTCOD_HEADLESS OFF CACHE BOOL ...)
  2. Documentation:

    • Update README to document headless mode
    • List disabled functionality (window creation, rendering contexts, input handling)
    • List retained functionality (FOV, pathfinding, BSP, noise, random, console manipulation)
  3. Build system:

    • Consider removing SDL-specific source files from compilation entirely when disabled
    • Files in src/libtcod/sdl2/ could be conditionally excluded

Files with NO_SDL Guards (already in libtcod 2.2.1)

src/libtcod/renderer_xterm.c
src/libtcod/context.c
src/libtcod/tileset_render.c
src/libtcod/console_init_.cpp
src/libtcod/console_.cpp
src/libtcod/console_rexpaint.c
src/libtcod/console_init.h
src/libtcod/tileset_render.h
src/libtcod/txtfield_c.c
src/libtcod/console_etc.h
src/libtcod/sdl2/event.cpp
src/libtcod/sys.h
src/libtcod/sys_sdl_img_bmp.c
src/libtcod/sys_sdl_img_png.c
src/libtcod/sys.cpp
src/libtcod/wrappers.h
src/libtcod/libtcod_int.h
src/libtcod/console_init.c

McRogueFace libtcod Usage (all headless-compatible)

McRogueFace only uses libtcod's algorithm APIs, all of which work in headless mode:

  • TCODMap - FOV computation
  • TCODDijkstra - Dijkstra pathfinding
  • TCODPath - A* pathfinding
  • TCODLine - Bresenham's line algorithm
  • TCOD_fov_algorithm_t enum constants

Upgrade Path: 1.24.0 → 2.2.1

Current McRogueFace uses libtcod 1.24.0. Upgrading to 2.2.1:

  • API should be compatible for the algorithms we use
  • 2.2.1 uses SDL3 by default (1.24.0 used SDL2), but this is irrelevant for headless
  • SOVERSION changes from 1 to 2

Tasks

  • Fork libtcod repository
  • Checkout tag 2.2.1 (ca8efa7)
  • Modify CMakeLists.txt to default to headless mode
  • Update README with headless documentation
  • Test build produces SDL-free library
  • Test with McRogueFace (verify FOV, pathfinding, line algorithms work)
  • Document merge/rebase process for future libtcod releases
  • Update McRogueFace submodule to use libtcod-headless

Benefits

  1. Simpler build: No libsdl2-dev/libsdl3-dev required
  2. Smaller dependency tree: Fewer transitive dependencies
  3. Community value: Provides what libtcod users have requested
  4. Natural fit: McRogueFace already uses SFML for graphics

References

## Overview Create a fork of libtcod called `libtcod-headless` that builds without SDL dependencies. This fulfills a long-standing community request for "ASCII-only" or "SDL-free" libtcod, and since McRogueFace implements its own graphical layer via SFML, we are naturally positioned to provide and maintain this. ## Key Discovery **libtcod 2.2.1 already has extensive `NO_SDL` compile-time guards!** When built with `-DLIBTCOD_SDL3=disable`, libtcod: - Compiles successfully with only `libz`, `libstdc++`, `libm`, `libgcc_s`, `libc` dependencies - Removes all SDL3 runtime dependencies - Still provides all core algorithms (FOV, pathfinding, BSP, noise, etc.) Tested build: ```bash cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON \ -DCMAKE_TOOLCHAIN_FILE="" \ -DLIBTCOD_SDL3=disable \ -DLIBTCOD_LODEPNG=vendored \ -DLIBTCOD_UTF8PROC=vendored \ -DLIBTCOD_STB=vendored # Output library dependencies (no SDL!): # NEEDED: libz.so.1, libstdc++.so.6, libm.so.6, libgcc_s.so.1, libc.so.6 ``` ## Implementation Notes ### Minimal Changes Required The fork should be a "light-touch modification" that can be easily rebased on each libtcod release: 1. **CMakeLists.txt changes**: - Change default: `set(LIBTCOD_SDL3 "disable" CACHE STRING ...)` - Or add a new top-level option: `set(LIBTCOD_HEADLESS OFF CACHE BOOL ...)` 2. **Documentation**: - Update README to document headless mode - List disabled functionality (window creation, rendering contexts, input handling) - List retained functionality (FOV, pathfinding, BSP, noise, random, console manipulation) 3. **Build system**: - Consider removing SDL-specific source files from compilation entirely when disabled - Files in `src/libtcod/sdl2/` could be conditionally excluded ### Files with `NO_SDL` Guards (already in libtcod 2.2.1) ``` src/libtcod/renderer_xterm.c src/libtcod/context.c src/libtcod/tileset_render.c src/libtcod/console_init_.cpp src/libtcod/console_.cpp src/libtcod/console_rexpaint.c src/libtcod/console_init.h src/libtcod/tileset_render.h src/libtcod/txtfield_c.c src/libtcod/console_etc.h src/libtcod/sdl2/event.cpp src/libtcod/sys.h src/libtcod/sys_sdl_img_bmp.c src/libtcod/sys_sdl_img_png.c src/libtcod/sys.cpp src/libtcod/wrappers.h src/libtcod/libtcod_int.h src/libtcod/console_init.c ``` ### McRogueFace libtcod Usage (all headless-compatible) McRogueFace only uses libtcod's algorithm APIs, all of which work in headless mode: - `TCODMap` - FOV computation - `TCODDijkstra` - Dijkstra pathfinding - `TCODPath` - A* pathfinding - `TCODLine` - Bresenham's line algorithm - `TCOD_fov_algorithm_t` enum constants ### Upgrade Path: 1.24.0 → 2.2.1 Current McRogueFace uses libtcod 1.24.0. Upgrading to 2.2.1: - API should be compatible for the algorithms we use - 2.2.1 uses SDL3 by default (1.24.0 used SDL2), but this is irrelevant for headless - SOVERSION changes from 1 to 2 ## Tasks - [ ] Fork libtcod repository - [ ] Checkout tag 2.2.1 (ca8efa7) - [ ] Modify CMakeLists.txt to default to headless mode - [ ] Update README with headless documentation - [ ] Test build produces SDL-free library - [ ] Test with McRogueFace (verify FOV, pathfinding, line algorithms work) - [ ] Document merge/rebase process for future libtcod releases - [ ] Update McRogueFace submodule to use libtcod-headless ## Benefits 1. **Simpler build**: No libsdl2-dev/libsdl3-dev required 2. **Smaller dependency tree**: Fewer transitive dependencies 3. **Community value**: Provides what libtcod users have requested 4. **Natural fit**: McRogueFace already uses SFML for graphics ## References - libtcod 2.2.1: https://github.com/libtcod/libtcod/releases/tag/2.2.1 - Commit: ca8efa7 - Existing NO_SDL infrastructure: ~1059 SDL references, most already guarded
Author
Owner

Initial Implementation Complete

Created 2.2.1-headless branch with commit 3b4b65dc:

Changes Made

CMakeLists.txt:

  • Disabled vcpkg toolchain file by default (commented out, can be re-enabled)

src/CMakeLists.txt:

  • LIBTCOD_SDL3"disable" (was "find_package")
  • LIBTCOD_LODEPNG"vendored" (was "find_package")
  • LIBTCOD_UTF8PROC"vendored" (was "vcpkg")
  • LIBTCOD_STB"vendored" (was "find_package")

Build Verification

cd modules/libtcod-headless
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
make -j$(nproc)

CMake output confirms vendored dependencies:

Will be vendored: LodePNG
Will be vendored: utf8proc
Will be vendored: stb

Library dependencies (no SDL!):

NEEDED: libz.so.1, libstdc++.so.6, libm.so.6, libgcc_s.so.1, libc.so.6

Remaining Tasks

  • Update McRogueFace to use libtcod-headless submodule
  • Test McRogueFace builds and runs with new libtcod
  • Update BUILD_FROM_SOURCE.md with simplified instructions
  • Push libtcod-headless to Gitea remote
## Initial Implementation Complete Created `2.2.1-headless` branch with commit `3b4b65dc`: ### Changes Made **CMakeLists.txt**: - Disabled vcpkg toolchain file by default (commented out, can be re-enabled) **src/CMakeLists.txt**: - `LIBTCOD_SDL3` → `"disable"` (was `"find_package"`) - `LIBTCOD_LODEPNG` → `"vendored"` (was `"find_package"`) - `LIBTCOD_UTF8PROC` → `"vendored"` (was `"vcpkg"`) - `LIBTCOD_STB` → `"vendored"` (was `"find_package"`) ### Build Verification ```bash cd modules/libtcod-headless mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON make -j$(nproc) ``` CMake output confirms vendored dependencies: ``` Will be vendored: LodePNG Will be vendored: utf8proc Will be vendored: stb ``` Library dependencies (no SDL!): ``` NEEDED: libz.so.1, libstdc++.so.6, libm.so.6, libgcc_s.so.1, libc.so.6 ``` ### Remaining Tasks - [ ] Update McRogueFace to use libtcod-headless submodule - [ ] Test McRogueFace builds and runs with new libtcod - [ ] Update BUILD_FROM_SOURCE.md with simplified instructions - [ ] Push libtcod-headless to Gitea remote
Author
Owner

Integration Complete

McRogueFace commit 8854d5b integrates libtcod-headless:

Changes in McRogueFace

  • .gitmodules: Points to git@github.com:jmccardle/libtcod-headless.git branch 2.2.1-headless
  • CMakeLists.txt: Added target_compile_definitions(mcrogueface PRIVATE NO_SDL)
  • Replaced modules/libtcod submodule with modules/libtcod-headless

Build Verification

$ ldd mcrogueface | grep -i sdl
(no output - no SDL dependencies!)

$ ./mcrogueface --headless -c "import mcrfpy; g = mcrfpy.Grid(grid_size=(10,10)); print(f'Grid: {g}')"
Grid: <Grid (x=0, y=0, w=160, h=160, center=(0, 0), zoom=1)>

Next Steps for Fresh Clone

After cloning McRogueFace with submodules:

# Set up deps symlink (one-time)
cd deps && ln -sf ../modules/libtcod-headless/src/libtcod libtcod

# Build libtcod-headless
cd ../modules/libtcod-headless && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
make -j4

# Copy to __lib
cp bin/libtcod.so* ../../../__lib/

This issue will auto-close when the commit is pushed/merged to master.

## Integration Complete McRogueFace commit `8854d5b` integrates libtcod-headless: ### Changes in McRogueFace - `.gitmodules`: Points to `git@github.com:jmccardle/libtcod-headless.git` branch `2.2.1-headless` - `CMakeLists.txt`: Added `target_compile_definitions(mcrogueface PRIVATE NO_SDL)` - Replaced `modules/libtcod` submodule with `modules/libtcod-headless` ### Build Verification ``` $ ldd mcrogueface | grep -i sdl (no output - no SDL dependencies!) $ ./mcrogueface --headless -c "import mcrfpy; g = mcrfpy.Grid(grid_size=(10,10)); print(f'Grid: {g}')" Grid: <Grid (x=0, y=0, w=160, h=160, center=(0, 0), zoom=1)> ``` ### Next Steps for Fresh Clone After cloning McRogueFace with submodules: ```bash # Set up deps symlink (one-time) cd deps && ln -sf ../modules/libtcod-headless/src/libtcod libtcod # Build libtcod-headless cd ../modules/libtcod-headless && mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON make -j4 # Copy to __lib cp bin/libtcod.so* ../../../__lib/ ``` This issue will auto-close when the commit is pushed/merged to master.
john closed this issue 2025-11-26 16:48:18 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: john/McRogueFace#134
No description provided.