“Yet another one”.
Let me begin by saying that the reply that follows is in no way an attempt to change your mind. Build systems may be just about the most controversial topic amongst C/C++ coders, and anyone who’s been around long enough has made up his mind about them. And that’s fine with me.
Instead, let me try to answer the obvious and often asked question:
“Why yet another build system”
Not because I didn’t know other build systems. I have used plenty over the years (make, cmake, premake, meson, rake, colcon, bazel), and some I even enjoyed working with.
Not because other build systems don’t work or are badly designed. All of the aforementioned tools have been used in plenty of projects and they generally work just fine.
But most importantly: Not because I think anyone should stop using what they are using. If you have a build system that works, and you are happy with it, stick with it.
So why then?
The reason is simple: a few years ago I had to create a custom build system. I ended up liking it so much that I didn’t want to go back. It turned out I wasn’t the only one, and so I decided to fork it off into its own project.
Bake is quite different from any of the other C/C++ build systems. Bake projects have a well-defined structure which aligns with best C/C++ practices. That means you don’t have to reinvent the wheel for every new project, which is great, but it pays off in a lot of other ways too:
- Unlike make, you don’t have to tell bake how to translate a source file into an object file, and how to translate object files into binaries. It already knows how to do this out of the box.
- Unlike cmake you don’t need to tell bake what your project looks like. It already knows where to find your source files and headers are, how to run your tests and where to store the binaries, keeping project config minimal.
- Projects from different developers all have the same structure, making it very easy to share code.
- Bake can automatically apply optimizations that make your build faster, like enabling precompiled headers, because it knows which headers to precompile.
- Bake has a built-in template engine, and because each project is formatted the same way, it is very easy to create useful template projects.
- Bake can automatically add
#includestatements for your project’s dependencies, so that the only thing you need to worry about is adding a dependency to the project configuration.
But perhaps the feature that makes the biggest difference is the bake environment. Bake automatically keeps track of the projects you’ve built, so that when you need to depend on them you can just use their logical name.
There are countless ways in which the bake environment has made my life easier. To name a few:
- No need to install projects to a global location like /usr/local before I can use it as a dependency. Bake can find any dependency that is stored in the bake environment, and the bake environment is conveniently located in the home directory.
- No need for “meta” configuration that ensures different projects are built in the right order. Bake automatically finds the dependencies and figures out the correct build order every time you do a build.
- Bake can recursively build projects and their dependencies with a single command (bake -r), in the right configuration (debug, release, etc).
- Bake can run a project from any directory, simply by using its logical name. If an application is in the bake environment, it can be ran from anywhere.
- Bake automatically builds and stores binaries for different configurations, and ensures you’ll never mix binaries from release builds with, for example debug builds.
- Resource files (images, HTML, …) are stored in the bake environment in well-known locations, so that applications, and more importantly, dependencies of applications can find these files regardless of the current working directory of an application.
- If I want to distribute binaries for a project with lots of dependencies, I can simply zip up the bake environment.
- I can get an overview of all the built binaries on my machine with a single command (“bake list”).
It is hard to convey how much time these features have saved me, and I don’t expect you to take my word for it either. All I can say is that it has made my coding life a hell of a lot easier. What should also be pointed out is that none of these features require any sort of configuration. Everything is seamlessly integrated in the bake workflow.
And this is just the tip of the iceberg. Some other tricks bake can do:
- Build all projects in any directory in the right order with a single command.
- Clone a project and all its dependencies with the “bake clone” command.
- After running tests with “bake test”, use “bake coverage” to see the coverage achieved by the test cases.
- Automatically export a configurable set of environment variables
I probably didn’t convince you that bake is a good idea. You may think that these features have been addressed in one way or another with other build systems, or that these features should not be part of a build system at all!
And that’s okay. I will keep using bake because I like it and think it’s the easiest thing out there. You will keep using autotools because you like it and think its the easiest thing out there. No need to get upset about it :-)