Warning – geeky post ahead… I’ve been doing some coding this week…
Anyone who’s done any programming, at least if it’s outside the limited confines of an integrated development environment, will have come across the make utility, which was developed nearly 30 years ago at Bell Labs.
Make lets you list which bits of a program depend on which other bits, so that when you make a change, say, to one of your source code files, you can just type ‘make’ and the bits which need to be updated as a result all get rebuilt automatically.
People use it for other things, too; many years ago I had to produce Rose’s PhD thesis through a rather complicated process which started with floppies from a dedicated Panasonic wordprocessor, ran through a C program I wrote to decode the disk format, a Perl script to convert the files to LaTeX, and then Latex itself and finally dvi2ps to get the Postscript output for printing! Each stage generated different files, updated tables of contents etc, and when she fixed a typo on her Panasonic, I needed to ensure that it was propagated through the entire pipeline and made it into print. Make was good for that.
But anyone who’s built a project of any size will also know that make is far from perfect. It really hasn’t evolved much in its thirty years and the syntax, while elegant for very small projects, becomes unintelligible for large ones.
Here’s a small segment of a Makefile I was writing last week:
define PROGRAM_template $(1): $$($(patsubst %,%_OBJS, $(notdir $(1)))) \\ $$($(patsubst %,%_LIBS, $(notdir $(1)))) g++ -o $$@ $$^ $$($(patsubst %,%_LDFLAGS, $(notdir $(1)))) $(LDFLAGS) all:: $(1) $(foreach obj, $($(notdir $(1)_OBJS)), \\ $(eval $(call OBJECT_template, $(obj),$(notdir $(1)) )) ) endef # Build every program defined in PROGS $(foreach prog,$(PROGS),$(eval $(call PROGRAM_template, $(prog))))
Don’t bother trying to understand this. The point is that it’s pretty arcane stuff and I wasn’t trying to do anything too sophisticated here.
If you’ve written Makefiles before you probably know roughly what’s going on, but do you know exactly what’s going on? Would you have got the right number of $ signs in the right places? Could you say why $$^ is in here and not $$< ? Why I have to call things and then eval them? Then try and imagine what it’s like for somebody seeing a Makefile for the first time!
And here’s the worst bit: for this to work at all, the gap at the beginning of the ‘g++’ line must be a tab, not spaces. So simple code that looks perfectly correct may not actually work when you try to run it. It’s a nightmare.
So last week I decided that using make in the 21st century was probably ridiculous, and it was time to search for alternatives.