# Ludo is a libretro frontend written in Go, and it is still a work in progress

> Ludo gives libretro cores a desktop user interface built in Go, with GLFW and OpenGL for video, OpenAL for audio, and subsystem directories for menus, playlists, scanners and save states. The README calls it a work in progress, states that it can launch most non GL libretro cores, and the build is a plain go build.

**libretro/ludo** — A libretro frontend written in golang

- Repository: https://github.com/libretro/ludo
- Website: https://ludo.libretro.com/
- Stars: 706 · Forks: 75
- Language: Go
- License: GPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/libretro-ludo

## A frontend shell for libretro cores, written in Go

Ludo is described plainly in the README as a work in progress libretro frontend written in Go, and the project hosts a homepage at ludo.libretro.com. The interesting part of that description is the word frontend. A libretro core is a single emulated system exposed as a shared library with a documented API. A frontend is the part that loads such a library, opens a window, routes input, plays audio and gives the user a way to choose content.

Ludo claims it is able to launch most non GL libretro cores, which is the single most important constraint in the project. A GL core wants to draw through a modern graphics path, and this frontend does not provide that. Everything else about it is ordinary frontend work, done in a language that is not the usual choice for this corner of the emulation world.

The supported platforms are OSX, Linux, Linux ARM and Windows, and the README points to GitHub releases for downloads. The project also carries a CI badge and a GoDoc badge, which tells you the code is expected to be read as a library as well as run, and the topics attached to the repository list libretro-api, libretro-frontend, opengl, openal, glfw and golang, matching the dependency set.

## The core list is hardcoded in the Makefile, and it varies by architecture

The Makefile at the root of the repository holds a CORES variable listing the libretro cores the project ships against. The list is long and specific: atari800, bluemsx, swanstation, fbneo, fceumm, gambatte, gearsystem, genesis_plus_gx, handy, lutro, mednafen_ngp, mednafen_pce, mednafen_pce_fast, mednafen_pcfx, mednafen_psx, mednafen_saturn, mednafen_supergrafx, mednafen_vb, mednafen_wswan, mgba, melonds, mupen64plus_next, np2kai, o2em, pcsx_rearmed, picodrive, pokemini, prosystem, snes9x, stella2014, vecx and virtualjaguar.

The same Makefile then filters that list per architecture, and this is where the project starts to show its seams. For arm builds it removes swanstation, mupen64plus_next, mednafen_pcfx, mednafen_saturn and melonds. For arm64 it removes mednafen_saturn, mupen64plus_next and picodrive.

The filtered cores are turned into library names by suffixing each one, so a core named fceumm becomes fceumm_libretro.so on Linux, fceumm_libretro.dylib on macOS and fceumm_libretro.dll on Windows. The Makefile computes all three lists in one step, which means the build has a single source of truth for what it expects to find at runtime.

## Installing the GLFW, OpenGL and OpenAL stack on four platforms

The dependencies are short: GLFW 3.3, OpenGL 2.1 or newer, and OpenAL. What varies is how you get them, and the README covers four platforms separately.

On macOS the README tells you to install OpenAL Soft and to follow the instructions about exporting PKG_CONFIG.

```bash
    brew install openal-soft
```

On Debian or Ubuntu the package list includes the Go toolchain itself.

```bash
    sudo apt-get install libopenal-dev xorg-dev golang
```

On Raspbian the list is shorter, but the README adds a hardware condition that matters more than the packages: you need to enable the experimental VC4 OpenGL support, described as Full KMS, in raspi-config.

```bash
    sudo apt-get install libopenal-dev xorg-dev
```

On Alpine and postmarketOS the dependency list is the longest, pulling in musl headers, the compiler, the OpenAL development package and the X11 development libraries, ending with mesa-dev.

```bash
    sudo apk add musl-dev gcc openal-soft-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev mesa-dev
```

On Windows there is no package manager step at all. You set up the OpenAL headers and DLL in the mingw-w64 include and lib folders by hand, which is the point where a Windows build of this project stops being a package install and starts being a setup task.

## go build is the whole build, with an X11 tag on Linux

The build instructions are three commands, and the recursive clone is not optional because the repository carries a .gitmodules file.

```bash
    git clone --recursive https://github.com/libretro/ludo.git
    cd ludo
    go build
```

The Makefile wraps that in a target that adds a build tag on Linux, driven by a DISPDRIVER variable that defaults to x11. The same file carries APP, ARCH and VERSION variables that combine into a bundle name, and a BUILDBOTURL_BASE pointing at the libretro buildbot nightly tree, with per platform and per architecture paths for OSX, Linux, arm, arm64 and Windows. The intent is a packaged artefact with a name like Ludo-Linux-x11-x86_64-dev rather than a bare binary.

The dependency picture is visible in the module file. It requires a GLFW binding, an OpenGL binding, freetype for text rendering, go-colorful, a tweening library, an imaging library, a TOML parser, a wav reader and an archives library for handling compressed content. The GLFW binding is not the upstream one: the module file replaces it with a fork, which tells you the project needs GLFW behaviour that the standard binding does not provide. The module targets Go 1.25.0.

## One directory per frontend subsystem

The top level of the repository reads like a table of contents for a frontend. There are audio/ and video/ for output, input/ for controllers, menu/ for the interface, options/ for settings, playlists/ for collections, savefiles/ and savestates/ for persistence, scanner/ for content detection, database and dat/ for the game metadata, history/ for recent play, state/ for the frontend's own state, notifications/ for messages, settings/ for configuration, patch/ for core patches, pkg/ and utils/ for shared helpers, assets for resources and libretro/ for the API binding itself.

Two entries are less obvious. The patch/ directory suggests the project carries modifications for cores, which is a common need when a core needs a small fix to behave under a frontend. The scanner/ directory, next to database and dat, points to automatic content detection, so the frontend is expected to scan a directory and identify what is in it rather than rely entirely on the user naming files.

This layout is the most reusable thing in the project. Each subsystem sits in its own package, which means a developer interested in one part of a frontend, say the scanner or the save state handling, can read that directory in isolation and understand the conventions the project follows.

## The limits are stated: non GL cores, manual Windows setup, work in progress

Three limits are worth taking at face value. The first is the non GL core restriction, which is a capability boundary rather than a bug, and it rules out a large set of modern and accuracy-focused cores for anyone evaluating the project.

The second is the Raspbian requirement for experimental VC4 OpenGL support with Full KMS enabled in raspi-config. That is a request to run a driver configuration that the distribution itself labels experimental, and the project's own frontend is a good deal less demanding than the games it exists to run. On a Raspberry Pi, the front end is the least of the risks.

The third is the Windows build path, where OpenAL headers and libraries have to be placed manually in mingw-w64 folders, with no package manager step to lean on. A project that describes itself as a work in progress can afford rough edges like this, but they are real costs that land on the person building it.

There is also a question of scope. Ludo is a full shell, with menus, playlists, a scanner, save states and a database, and it hardcodes which cores it expects. Writing your own program against the libretro API gives you a smaller surface and full control over the interface, at the cost of building the parts yourself.

## Release tags, nightly builds and a recent push

The published tags are v0.22.4 on 2026-04-22 and v0.22.5 on 2026-05-17, plus a v0.22.5-pacing-test tag from 2026-08-19, which suggests the tag namespace is used for trial builds as well as releases. The last push to the master branch was on 2026-10-19, so the branch is moving faster than the tag list.

Alongside the tags, the Makefile points at a nightly buildbot tree for each platform and architecture, so a fresh binary is expected to be continuously available even when the release tags are old. The two mechanisms cover different needs: tags for reproducible downloads, nightlies for the current state of the branch.

The project is licensed under GPL-3.0, and the COPYING file at the root carries the terms. For a frontend that loads core libraries as separate files, that licence has a practical consequence worth thinking about before you distribute a build: the frontend and the cores are separate works, and how they are packaged and shipped together is the question to settle, not the frontend's licence alone. The README does not address that question, so it is one you have to answer yourself.

## Conclusion

Ludo fits a developer who wants a Go libretro frontend, a scripted build or a place to read how frontend subsystems are laid out, and it does not fit a player who wants a finished emulator front end or one who needs GL based cores. Before adopting it, check the core list in the Makefile against the cores you actually own, because the frontend is limited to non GL cores, and expect to hit the fact that the project publishes v0.22.5 tags while describing itself as a work in progress.

## FAQ

### What is Ludo and what can it run?

Ludo is a libretro frontend written in Go that the README describes as a work in progress. It is able to launch most non GL libretro cores, and it works on OSX, Linux, Linux ARM and Windows.

### How do I build Ludo from source?

Clone the repository recursively so that submodules are fetched, then run go build inside the checkout. The README points to the continuous delivery config for more detailed build steps, and the Makefile adds a display driver build tag on Linux.

### What are the dependencies for Ludo?

The README lists GLFW 3.3, OpenGL 2.1 or newer and OpenAL. Package commands are given for macOS, Debian or Ubuntu, Raspbian and Alpine, while on Windows the OpenAL headers and DLL have to be set up by hand in the mingw-w64 include and lib folders.

### Does Ludo work on Raspberry Pi?

The README covers Raspbian and says you need to enable the experimental VC4 OpenGL support, described as Full KMS, in raspi-config before installing the OpenAL and X11 development packages.

## Sources

- [libretro/ludo on GitHub](https://github.com/libretro/ludo)
- [License: GPL-3.0](https://github.com/libretro/ludo/blob/master/LICENSE)
- [Project website](https://ludo.libretro.com/)
- [README](https://github.com/libretro/ludo/blob/master/README.md)
- [Releases](https://github.com/libretro/ludo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/libretro-ludo
