In Praise of Drop-In Libraries

As I grow older, grumpier and lazier, my level of tolerance for certain things in software development becomes lower. I've become less interested in learning tools and languages as opposed to theory and general concepts. I see every hour spent learning the details of an API or a language as an unfortunate tax, imposed on me by the authors of the tool, for being able to use their tool.

Because of that, I've grown to really appreciate a certain type of libraries. I refer to them as "drop-in" libraries. It's a bit hard to characterize with one phrase, but they all seem to follow a few general principles:

Kicking the build system out of the way

A drop-in library will never impose a build system on you. It will never make you go through some song and dance of "./configure && make", and of course, it will never ever make you download and install some new fancy build system. It might use one for its own needs (like building tests and whatnot), but you won't be required to use it.

It's not just about having to learn about yet another build system. I've had the experience of dealing with project(s) that had multiple dependencies with different build systems. It's just not a very pleasant situation, and I've decided I'd rather not be in it again. For my personal stuff, I actively avoid anything that isn't either drop-in or CMake-based (since I use CMake myself).

Satisfying the build system requirement is really important for the next principle, which is...

Being self-contained

The source code of a drop-in library can be simply added to your project (hence the name "drop-in"). No separately built binaries, no .lib files, no DLLs, none of that. Just add the library code to your project and you're done.

This property is desirable because it simplifies your build process considerably, makes debugging easier and possibly introduces more opportunities for whole-program optimization.

Being simple to use

Drop-in libraries don't come at you with towering architectures or complex APIs that require careful study before they can be used efficiently. You also don't have to learn all of the library - just the part that does that one thing you want.

This reduces your cognitive load and frees your mind up to do other useful things.

Expose a C interface

This one is optional if all you're going to be doing is C++. It pains me to say this as someone who genuinely likes C++, but even C++ name mangling isn't standardized across different compilers, let alone exceptions or newer stuff like lambdas/closures. This means that it's friggin' hard to call C++ code directly from any other environment (or even from other C++ code built by a different compiler). By contrast, C functions can be called from virtually everywhere. If you have a project in a language that is neither C nor C++, it's usually more straightforward to use a C interface.

Some Examples

Here are some examples to illustrate the points above.

  • STB Libraries - It would be a sin to not mention Sean Barrett's libraries in this post. I remember the first time I tried to use libpng, it scared me off so much that I went and wrote my own TGA loader and used TGAs instead PNGs in my game until I stumbled upon Sean's "STB Image" library. It's just one file, can be dropped straight into your project,implements loading multiple image formats and is straightforward to use. Other STB libraries are in the same vein.

  • Lua - I can't praise the folks behind Lua enough. They could've used bison, flex or yacc. They could've shipped a bloated standard library with a kitchen sink as a requirement. They didn't do any of that. The entire thing is a dozen C files. Drop them into your project and boom - you have a full fledged scripting language embedded into your app, and it's easy to make calls from it to native code and vice versa. It makes my heart sing.

  • dear imgui, by Omar Cornut - two cpp files, some three headers and you have a toolkit for building a nice-looking UI into your graphics application, with various controls, ability to draw graphs and shapes, and text. It's intended for things like UI for built-in debug tools in games, but honestly, I think it could totally work for player-facing UI in an indie game or something.

  • Secret Rabbit Code - it's a library for resampling audio. If you download the source package, it looks like it wants you to use autotools, but you could actually just rip out the few C files from src/ and use them directly.

  • glm - this one is quite widely known, a header-only graphics-specific math library often used in OpenGL applications. Also, check out gli by the same author - for dealing with compressed textures in KTX and DDS formats

  • miniz - a data compression library by Rich Geldreich

  • Honorary mention - Boost. Yeah, you heard me right :-) Boost tends to get some flak because of how complex some of its components can be. To be honest, I haven't used Boost in years and I don't see myself using it again any time soon. But one thing I always did like about it was how it had all these header-only libraries that you could just use without dragging in the rest of it or dealing with Boost.Jam. I guess those count as drop-in.

Like this post? Follow this blog on Twitter for more!