Bakefile Postmortem
What is this about?
Bakefile is, or was, an attempt to create a decent cross-platform build system for C++. It was started back in 2009 as a new and improved version of an earlier implementation of the same idea and, back then, we hoped to produce something that would be useful to the wider C++ community.
This clearly hasn't happened, but in spite of this, bakefile was used in a number of projects. But the last of them — to the extent of my knowledge — has just switched to a CMake-based build which implies the end of my involvement with the project and, in absence of any other maintainers, the de facto end of the project itself. And so today seems like an appropriate moment to look back at the project history.
What did we do right?
This will be a shorter section than the next one, but I still think that some of our choices have been correct. The first one was that we chose C-like syntax, which results in much more pleasant experience when writing build files, e.g. here is the "Hello world" example copied from the manual:
toolsets = gnu msvs;
program hello {
sources { hello.cpp } // could also have been "hello.c"
}
and it still seems much less alien than CMake.
The second choice which I still can't blame, even retrospectively, is making bakefile a pure build system generator and not a build system tool on its own. It is still great to be able to build projects using bakefile without installing anything (other than the standard build tools, like make). Not being able to rely on bakefile presence on the system where the project is built obviously imposes a number of limitations, but none of them is critical enough to justify forcing all users to install it.
What mistakes did we make?
The first and most obvious answer was "not be CMake". 20 years ago it was plausible but still didn't seem certain that CMake was going to become the standard C++ build tool. It turned out that the rise of "worse is better" was really inevitable and this was probably foreseeable even back then. Today, even if some alternative build systems still survive (although, with the possible exception of Meson, it seems hard to find any that are at least somewhat widespread), nothing comes close to CMake in terms of support and breadth of use and the only realistic way to use another build system is to switch from C++ to another language.
The choice of Python as implementation language was, at least subjectively, a mistake as well. One of its advantages was supposed to make bakefile more approachable and so attract more developers, but this hasn't happened. On the other hand, dynamic nature of Python made working on the project harder than it needed to be and performance was poor, which really shouldn't have been a concern for a system generating relatively small text files. And the transition from Python 2 to Python 3 was the final nail in the coffin.
A final major mistake that is obvious now was not to take the one good idea that CMake had (although maybe it didn't even have it yet, back in the "classic CMake" days): something that "modern" CMake does right is that each target defines its interface options that are applied to all other targets using it. This is a simple idea, but it would have many good consequences and we really should have supported it from the beginning.
However, all in all, implementing target-oriented approach and writing bakefile in C++ probably wouldn't have changed much because the first reason alone explains the failure of the project for 95%. So the main lesson that can be drawn from our experience is that competing with the most widespread software is hard, even when it is disliked by many, as is the case for CMake.