A C++ tool for building C++ code
My fifth C++ example is a fledgling build tool intended to remove some of the insanity of using "make". I wanted to see if I could come up with something which would just be able to figure out what to compile and link together without having to explicitly list all of the dependencies.
I wrote a little about it last summer, but didn't get much into the specifics. Since then, it's evolved a little, but not much. It's not a priority project, in other words.
Here's how it works. First, you set up your code as a "depot", where all of your projects are in a single tree of directories. This is good for sharing bits of code. It might look like this:
- http/cookies.h
- http/cookies.cc
- scanner/listcalls.cc
Let's say the target we want to build is scanner/listcalls. It depends on the class contained in http/cookies.{cc,h}, and so it has this somewhere in the top of scanner/listcalls.cc, as you would expect:
#include "http/cookies.h"
That's enough for my tool to find it. The rule is simple enough: if you include foo/bar.h, then there's a foo/bar.cc, and together they will become foo/bar.o.
It gets better, though. If foo/bar.cc or foo/bar.h then #include more targets in the tree, it'll pick them up and compile them into .o files.
Finally, the actual target's .cc file, like scanner/listcalls.cc, gets compiled into scanner/listcalls.o.
With everything compiled into object files, it's time to link. All of the object files which were discovered during this process are linked together to make the target, which is the actual file scanner/listcalls.
This also does the smart thing and doesn't rebuild things if the inputs haven't changed. Still, if you edit a dependency, it'll recompile that dependency's object file and then re-link the target with that new object file.
Finally, it's smart about the funky compiler and linker flags you normally need to deal with certain libs on your system. Maybe you need to do some -I magic to compile against libmysqlclient. I've set a rule so that including <mysql/mysql.h> will make it use that -I switch when compiling that particular source file.
Also, if there are linker flags like "-L/usr/local/something/or/other -lfoo", they'll be picked up and will migrate to anything which then uses that dependency.
Here's why this matters. Let's say I change http/cookie.cc so it now depends on some external library. In a Makefile world, I now have to track down every place where http/cookie.o is used -- directly or indirectly -- and amend the build rule accordingly. This stinks!
I bet some people just find the missing stuff by running "make" and seeing what complains. Then they just twiddle the Makefiles until it stops yelling. That's just messy.
This tool is still in its larval stages, but it should be interesting to see where it goes. If it just gets people to take a new look at the way we build things on Unix systems, even that will be a win.
March 28, 2012: This post has an update.