This post is coming to you on my birthday! Yes, I’m still writing even today; I’m still filing bugs as well. I do have a personal request if somebody wishes to send me something: two £20 PSN cards (from UK). I bought Fallout 3 for PS3 “preowned” while I was in London earlier this month; two days ago the expansion packs were released in Europe, but the versions for UK or the rest of EU, including Italy, are not compatible. And of course to use the UK store I need a UK credit or debit card, or more easily UK PSN gift cards. So if you want to wish me an happy birthday, feel free to get the PSN card and mail me the redeem code, no shipment required. (Encrypt the mail if you do that though.)
Today’s post is not related to the tinderbox, since I know it might start sounding a bit boring to read exclusively about that. On the other hand it’s a topic that I did find interesting from the tinderbox itself, since that has shown me how this is a problem indeed. It’s about mistakes, mistakes with
Quite a few packages seems to think it’s a good idea to simply call the
-config scripts to find flags to use and libraries in the compile line for each source file, something like this:
CFLAGS = `sdl-config --cflags` LDLIBS = `sdl-config --libs` # or .c.o: $(CC) $(CFLAGS) `sdl-config --cflags` -c $< -o $@
Can you see the problem already? The way
make works, the command line is invoked through
system() each time;
sh is thus executed and it takes care of interpreting the command line; the
`` calls will be then sub-called and then substituted. This, though, will cause three commands to be executed:
sdl-config and finally
gcc to compile the file; per each source file. While the first and latter are part of the design, the latter is one more call, one more sub-process, called per each compilation that is not really useful.
Similarly this can become quite bothersome when instead of a single
sdl-config call you got something like three or four
pkg-config calls. While the executables and their libraries as well as the datafile they need will be kept hot in cache, this means they’ll also be kept in cache in expense of something else. And you can guess they are not that important.
One of the many solutions for this mistake is to use one GNU
make extension (
gmake is much better than others make for what concerns support extensions): the
$(shell ) function.
SDL_CFLAGS := $(shell sdl-config --cflags) SDL_LIBS := $(shell sdl-config --libs) CFLAGS = $(SDL_CFLAGS)
The first two lines in this example set (
:=, the simpler
= in make define a macro, but doesn’t set it “fixed”) the variables by calling, once and at global scope, the
sdl-config script. This way you don’t have to call it per translation unit. The side effect of this, beside adding the dependency over GNU make, is that the script will be called even when trying to clean the project, but there are more sophisticated ways to deal with that, for instance:
all-recursive: $(MAKE) SDL_CFLAGS="`sdl-config --cflags`" SDL_LIBS="`sdl-config --libs`" all CFLAGS = $(SDL_CFLAGS)
(Of course this is just a quick and dirty example, there are other things to take into consideration there.)
A similar problem happens when you got packages that allows users to “configure” compiler and flags by creating files with them: you end up with
`cat somefile` multiple times in a compile line. And that also means that you have to keep the files in cache; they might be small but they are still 4KiB of cache wasted for something that is not really useful: you can either set variables or set a configuration file that is then included by the main makefile.
Yes this might be smaller stuff, but when you got something like my tinderbox going, you probably want to spare even those process calls during a long build.