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.
An IDE like Visual Studio, XCode or Eclipse will often handle dependencies for you, of course, but even if everybody in your organisation can be persuaded to use the same one, it’s not a solution for cross-platform work or when you need to distribute code to others who may not have the same tools.
There are a huge number of alternatives to make out there; the ant tool is popular with Java programmers, for example, but I wanted a more general solution. And after reading many articles detailing others’ experiences and recommendations, I opted to experiment with scons. And I’m loving it.
Scons is normally taken to be short for ‘software construct’, though the name didn’t quite evolve from that origin. But while it may lose out to make in the elegance of the name, it’s superior in almost every other way. Scons is written in Python, making it easy to install and run on most platforms, and easy to extend if you need new features. More importantly, the SConstruct files, the equivalent of Makefiles, are also valid Python, meaning that they’re very readable, and yet you have the full power of a programming language there if you need it. And not a ‘$$($(patsubst %‘ in sight!
I don’t want to go into too much more detail here about its merits, but if you’re dealing with make on a regular basis, you owe it to yourself to look at scons. Read ‘What makes Scons better?’ on the site’s front page. See what some users have to say about it. And then print a copy of the documentation to read on the train home, and check out the wiki.
That’s my recommendation, anyway. It’s true that the majority of the world uses make. It’s also true that the majority of the world used to use COBOL.