Software, technology, sysadmin war stories, and more. Feed
Monday, July 11, 2011

Moving beyond make to build C++ programs

Why do we still have Makefiles? Why do we have to wrangle files which say "this thing builds this thing, and this other thing goes here"? Why isn't there some build system which will just figure it out for normal cases and still have a way to handle exceptional ones?

What if it could be done? It would look a bit like this:

$ ls
tool.cc  util.cc  util.h
$ cat tool.cc
#include "util.h"
int main(int argc, char** argv) {
  Util util;
  return 0;
$ cat util.cc
#include "util.h"
#include <stdio.h>
Util::Util() { }
Util::~Util() { }
void Util::Run() {
  printf("Run is running.\n");
$ cat util.h
class Util {
  void Run();
$ magic-build-thingy tool
C++ library: tool: OK
C++ library: util: OK
C++ binary: tool: OK
$ ./tool
Run is running.

What if it already was possible? How much would you pay for it?

Let's look at this in terms of a Makefile-driven build. This example is pretty dumb, but it's worthy of investigation because it is revealing.

tool: tool.cc util.cc

Right? Wrong. There's a bug in that already. It should be this:

tool: tool.cc util.cc util.h

You really want to rebuild tool if util.h changes. If you miss that, you've just introduced a development environment bug.

There's more to this. Let's say you have a class called T which uses some external library, like MySQL. Any time you use it, you have to supply some special linker flags to make your binaries come together. Without those flags, you get a bunch of spew and it fails to link. Maybe you need something like "-L/usr/lib64/mysql -lmysqlclient".

The way things are right now, you have to plumb this end-to-end all by yourself. Class T uses MySQL? Better track down everything which uses T and make sure it includes the magic flags. Don't just cram it into the top-level LDFLAGS, either, since that leads to binary bloat!

What if that Just Worked, too? Now how much would you pay?