Teapot is an opinionated tool for building cross-platform software, with a primary focus on modern C++ code. It is designed from the ground up to encourage modular and reusable software components, with a minimal amount of configuration.

Teapot supports creative coding and collaboration by making it easy to create and fork existing code and including it in another project. Dependencies are automatically fetched and versioned using git, which helps to ensures that code behaves the same on all platforms.

Teapot uses the Ruby programming language for configuration files, which means that you will never be limited by Teapot itself. You can easily integrate external build systems along with teapot's own native build system for maximum flexibility.

Decentralised package management.

Teapot is a decentralised build tool. There is no central package listing or repository and no default behaviour. Most parts of the build process are structured as packages which fulfil some part of the build process - e.g. variants, platforms, compilers, libraries, applications, etc. Practically speaking, in order for teapot to compile code, you need packages to satisfy all parts of the build process.

This approach ensures that almost all of the build system can be versioned, including toolchain definitions and build rules. It also reduces the complexity of the code in the core implementation

Tell, don't ask.

Teapot doesn't specifically use any kind of autoconfiguration (but specific packages might do this, especially if they use an external build system). By design, teapot depends on standards compliant compilers and libraries and platform-specific packages.

Autoconfiguration is generally a slow process and in my experience can introduce consistency problems in large projects. Explicit configurations generally fail predictably, and a clear chain of responsibility ensures that enough information is available to debug the problem easily.

Where it all started.

Teapot was extracted from tooling which was used to build a game engine. The original code base suffered from a monolitic architecture - many dependencies were compiled directly into the project and this made it hard to maintain, test and use in isolation. Specifically, I found myself wanting to create many small example projects, libraries, and so on, but without good tools to do so. Monolithic designs force an all or nothing approach, which generally leads to bad layering, feature creep and difficulties sharing code between projects.