Library / SDK
empyreanx/pico_headers avatar
empyreanx/pico_headers

pico_headers: a shelf of single-header C libraries for game development

Single-header, cross-platform libraries for game development

566 stars37 forksCLicense varies

At a glance

What is it?
pico_headers is a collection of cross-platform single header libraries written in C, covering the parts of a game engine that get rewritten in every project: base64, an entity component system, a quadtree, 2D collision detection, maths, logging, a unit test framework and more. Each library carries its own version, and the ones below 1.0 come with an explicit warning that their API can change without warning.
Who is it for?
Adopt pico_headers if you are starting a C game project and want working ECS, quadtree, collision detection, maths, logging and unit testing pieces in a consistent style, each of which you can drop into your repository as a single file.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the project is

pico_headers is a collection of cross-platform single header libraries written in C, and that phrase carries the whole design in it.

Single-header means the library is one.h file that you copy into your project. There is no build system, no package manager step, no separate library to link, and no version to keep in sync with the rest of your dependencies. You include the header and the code is in your translation unit. For a game project, where the toolchain is often a hand-rolled Makefile or a premake script, and where every extra dependency is another thing to vendor, that is a real convenience rather than a stylistic preference.

Cross-platform is claimed and then qualified. The examples and tests compile and run on Linux with GCC, on Windows with MSYS2 and MinGW64, and on MacOS with Clang. The one exception is named: the Rogue demo only compiles and runs on Linux and MacOS. Naming the exception is a good sign, because a project that claims cross-platform support without mentioning its gaps is harder to plan around.

The README also states that the libraries are provided as-is, that suggestions for improvements or bug fixes are appreciated, and that an issue should be raised before a pull request with new features, while bug fixes are always welcome. That is a reasonable contribution policy for a set of libraries where a new feature can ripple through everybody's copy of the header.

The primary language is C, the licence field is not a standard identifier, the default branch is main, and the last push was on 2026-10-21 with the project not archived. The repository publishes no GitHub releases, so the version numbers in the table are the versioning scheme.

The library table, and what the version numbers mean

The README's table is the catalogue, and it lists twelve libraries with a documentation link, a description and a version.

pico_b64 at version 1.0 is a base64 encoding and decoding library. pico_bvh at 0.1 is a dynamic 2D bounding volume hierarchy. pico_ecs at 3.3 is described as a pure and simple ECS. pico_emitter at 0.1 is a minimal event emitter. pico_font at 0.1 is a simple, dynamic online font atlas. pico_gfx at 0.1 is a graphics library based on sokol_gfx. pico_hit at 0.4 is 2D collision detection using SAT plus ray casting. pico_log at 1.0 is a minimal and flexible logging framework. pico_math at 2.0 is a 2D math library for games. pico_qt at 1.1 is a simple quadtree library. pico_time at 0.1 is a simple time management library. And pico_unit at 1.2 is a bare-bones unit testing framework.

The version numbers are doing real work here, and the README explains exactly what they promise. The API of libraries with versions less than 1.0 is subject to changes without warning, and those changes might crash your code or cause other problems. Libraries at 1.0 or above are more stable and will generally only be changed when adding features or making bug fixes, though changes may still break the API, they will be limited in scope and should not introduce unpredictable behaviour at runtime.

So there is a clear tier structure. pico_ecs, the most mature library at 3.3, is the one you would build a project around. pico_b64, pico_log, pico_math, pico_qt and pico_unit are at or above 1.0 and are reasonably safe to depend on. And the ones at 0.1, which is pico_bvh, pico_emitter, pico_font, pico_gfx and pico_time, are experiments in the sense that their interfaces will move.

That distinction matters in practice. A quadtree at 1.1 and a font atlas at 0.1 are very different bets, and the table lets you tell them apart before you copy a header into a project that will live for years.

One library is described as based on another project rather than written from scratch. pico_gfx is a graphics library based on sokol_gfx, so it is a wrapper or an adaptation of an existing design rather than an original one.

Licensing, and the split between zlib and MIT

The licensing is stated in one line and it has a split worth understanding.

Most libraries are licensed under your choice of zlib or the public domain, and the remaining libraries are licensed under the MIT licence.

The dual zlib-or-public-domain option is a deliberate choice for code you are going to copy into your own repository. Public domain means no obligations at all. zlib is a permissive licence that requires you to keep the copyright notice and to note that the software is provided without warranty. Choosing between them is a decision the user makes per library, and the point of offering both is that some people will not take code with any attached conditions at all.

MIT for the remainder is a slightly stronger version of the same idea, and it is what the author applies to libraries where a copyright line is worth preserving.

Since you copy these headers into your project rather than depending on them, the licensing question is a question about what your own repository ends up containing. If you take a public domain header, that file carries nothing with it. If you take an MIT one, you carry the notice. Both are workable, and the dual option means you are not forced into a particular answer.

The project also keeps its deprecated libraries separately. pico_gl, pico_sat, pico_math 1.0 and pico_ecs 2.4 are described as deprecated libraries and are pointed at another repository, pico_headers_deprecated.

That is a good pattern for a header collection, because a header library that is copied rather than depended upon cannot easily be un-copied. Moving a deprecated implementation out of the main repository, and telling people where to find it, means the current headers stay clean and anyone still depending on an old version can still find it. The list also tells you something about the project's history: there was an OpenGL library and a separate SAT collision library before the current set.

The README also credits Randy Gaul for inspiration, for answering questions, and for the template the project was started from. The Gaul name is a familiar one in the C game development world, and acknowledging the template is a small courtesy that matters when a project is built on someone else's scaffolding.

The repository layout, and what the examples and tests directories tell you

The top-level listing is a single header per library, plus the directories that support them.

There is pico_b64.h, pico_bvh.h, pico_ecs.h, pico_emitter.h, pico_font.h, pico_gfx.h, pico_hit.h, pico_log.h, pico_math.h, pico_qt.h, pico_time.h and pico_unit.h, one per row of the table, with no subdirectories for the implementations. That is the single-header design taken literally: the entire library is that one file, and the file naming maps one-to-one onto the table.

Then there are the example directories, and they are named after the library they exercise: examples_pico_ecs, examples_pico_gfx, examples_pico_log and examples_pico_unit. And the test directories: tests_pico_b64, tests_pico_bvh, tests_pico_ecs, tests_pico_emitter, tests_pico_hit, tests_pico_math, tests_pico_qt and tests_pico_time.

The set of test directories is informative because it does not match the set of example directories exactly. There are tests for pico_b64, pico_bvh, pico_ecs, pico_emitter, pico_hit, pico_math, pico_qt and pico_time, but the examples are for pico_ecs, pico_gfx, pico_log and pico_unit. So pico_gfx, pico_log and pico_unit have examples without dedicated test directories, while pico_b64, pico_bvh, pico_emitter, pico_hit, pico_math, pico_qt and pico_time have tests without dedicated examples.

That asymmetry tells you where the author's attention has gone. The libraries with tests are the ones whose correctness is hard to eyeball: base64 encoding, a bounding volume hierarchy, an entity component system, collision detection, maths. The ones with examples are the ones where seeing it run teaches you more than reading an assertion would, which is true of a graphics library, a logging framework and a test framework.

There is also a build_pico_gfx_shader/ directory, which is specific to the graphics library, since shader compilation needs its own tooling, and a Doxyfile at the root, which is the configuration for the Doxygen documentation generator that produces the per-library documentation sites linked from the table.

The examples are not listed individually in the README, but the Rogue demo is named in the platform note as the one that only builds on Linux and MacOS, which is the kind of thing a visitor learns by looking at the directories.

How to evaluate it, and what to check first

There are four things to decide, and the first is whether the single-header model suits your project at all.

Because you copy the header, you are not adding a dependency, you are taking on a maintenance relationship. When the author changes a 0.x library, your copy does not change with it, so the change arrives whenever you next decide to re-copy. That is fine for a prototype and for a personal project. For a commercial game with a long life, it means the header becomes yours to maintain, and the question becomes whether the library is still worth using in two years when upstream has moved on.

Second, which libraries you actually want, and check the version tier before you commit. The 0.1 entries, which are the bounding volume hierarchy, the event emitter, the font atlas, the graphics library and the time management library, are explicitly unstable. The 1.0 and above entries, the ECS at 3.3, the maths library at 2.0, the quadtree at 1.1, the unit test framework at 1.2, base64 and logging at 1.0, are the ones you can build on. The collision detection library at 0.4 is in between, so read it carefully.

Third, the overlap with what you already have. This is a collection of general-purpose pieces, and most of them are things a project ends up writing for itself. pico_math at 2.0 for vector maths and pico_log at 1.0 for logging are the two that most often overlap with an existing engine or utility code, and pico_unit at 1.2 is a unit testing framework you would otherwise bring in as a separate dependency. Whether adopting them is a win depends on whether you value having one consistent style across those pieces more than having them maintained by somebody else.

Fourth, the graphics library specifically. pico_gfx is based on sokol_gfx rather than being original, and it is at 0.1, and it has a separate shader build directory. If you are considering it, read the header and the build script, because that combination tells you it is a thin layer over a design you could equally adopt directly.

What you get in exchange is a coherent set of pieces with a consistent naming scheme, per-library documentation generated from the headers, examples and tests for most of the library, and a licence choice that lets you take the code into your repository without a fuss. For a hobby project or a jam entry, that is a good deal. For a commercial title, the version tiers and the copying model are the two things to think hardest about.

Editorial conclusion

Adopt pico_headers if you are starting a C game project and want working ECS, quadtree, collision detection, maths, logging and unit testing pieces in a consistent style, each of which you can drop into your repository as a single file. Do not build on the libraries below version 1.0, which are the bounding volume hierarchy, event emitter, font atlas, graphics library and time management, because their APIs are stated to change without warning, and do not treat a copied header as a dependency you will receive updates for, because the copy in your repository is yours to maintain from the day you take it. Before you commit, check the version tier of each library you want, read the licence choice per library since most are zlib or public domain and the rest MIT, and decide whether the pieces overlap with code you already have, because adopting a consistent set of your own is usually worth more than mixing.

Frequently asked questions

What is pico_headers?

It is a collection of cross-platform single header libraries written in C, for game development. There are twelve libraries covering base64, a dynamic 2D bounding volume hierarchy, an entity component system, an event emitter, a font atlas, graphics, 2D collision detection, logging, 2D maths, a quadtree, time management and unit testing.

Which platforms does pico_headers support?

The examples and tests compile and run on Linux with GCC, on Windows with MSYS2 and MinGW64, and on MacOS with Clang. The one exception named is the Rogue demo, which only compiles and runs on Linux and MacOS.

What do the version numbers in the pico_headers table mean?

Libraries below 1.0 may have their API changed without warning, and such changes might crash your code. Libraries at 1.0 or above are more stable and generally only change when features are added or bugs fixed, though changes may still break the API in a limited scope. The versions run from 0.1 for the newest additions up to 3.3 for the entity component system.

How is pico_headers licensed?

Most of the libraries are licensed under your choice of zlib or the public domain, and the remaining ones under the MIT licence. Because you copy the headers into your project rather than depending on them, the choice affects what your own repository carries: a public domain header brings nothing with it, an MIT one requires you to keep the notice.

What happens to deprecated pico_headers libraries?

Deprecated libraries, which are pico_gl, pico_sat, pico_math 1.0 and pico_ecs 2.4, are kept in a separate repository called pico_headers_deprecated. The current headers stay clean while anyone still depending on an old version can still find it.

Does pico_headers have tests and examples?

Both, though not for every library. There are example directories for the entity component system, graphics, logging and unit testing, and test directories for base64, the bounding volume hierarchy, the entity component system, the event emitter, collision detection, maths, the quadtree and time management. The documentation links in the README are generated with Doxygen.

Official sources

  1. empyreanx/pico_headers on GitHub
  2. Issues
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/empyreanx-pico-headers.svg)](https://hysenlabs.com/projects/empyreanx-pico-headers)

Was this useful?