Skip to content

Comment on Do More and `make` Less with GNU Make and Less.js

Comments

This example seems to have a few issues with ordering and what should/shouldn't have their own rules. In general, a good rule of thumb is that any file which is generated should have a coresponding rule to generate it, whether or not that's a generic rule or a specefic rule. Also important, rules should only generate the file they claim to generate (IE. If a rule generates '%.c' and also happens to generate '%.d', it definitely shouldn't act like it only generates '%.c' - An exception can be made for temporary files, but in general if they're not going to stick around you should remove them when the rule is run anyway, or give them a proper rule if they're sticking around). The biggest reasons for these rules is so that your rules are honest about what they create (And this makes 'make clean' much easier to implement), and the second is that at some point you'll need that generated file somewhere else and won't have a rule to generate it on it's own.

The examples break these rules more then a couple of times. Their very last examples won't work, because they generate the %.d file in the same rule that is only supposed to generate the %.css file. Because of this, 'make' has no way of figuring out what rule to run to create the %.d file, so the -include will fail from the .d files not existing in the first run (-include and include-file generation happen before the default rule is started, because it happens at parsing time). Providing a separate %.d rule would fix this issue (And also fix the issue that every time you compile your dependency info will be generated again, even if it hasn't changed.). For example, if you wrote a 'make clean' which only cleaned the %.css files, all of the %.d files would be generated again when you generate the %.css files, even though it's not nessisary. There's also a small error that 'all' isn't the default rule to run, the default is simply the first rule in the file. It's common to see 'all' defined high-up in a Makefile as something like 'all: real-all', where 'real-all' is defined below after other various things take place, and it does the actual heavy lifting of kicking off the compilation.

Providing a separate %.d rule would fix this issue

Yes. The following is an example of how to handle C header dependencies. It could be adapted to build css from less and would be an improvement on the blog post technique.

    sources := $(wildcard *.c)

    -include $(subst .c,.d,$(sources))

    %.d: %.c
        $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
        sed 's,\($*\)\.o[ :]*,\ 1.o $@ : ,g' < $@.$$$$ > $@; \
        rm -f $@.$$$$
It uses the fact that if you include a file which doesn't exist but for which there is a rule to build it, GNU make will build it for you.

Yep. Though with newer versions of gcc (I don't know how new though) you can avoid the nasty sed stuff. I'm currently using this to generate my .d files for C files:

    $(objtree)/%.d: $(srctree)/%.c
        @$(CC) -MM -MP -MF $@ $(CPPFLAGS) $< -MT $(objtree)/$*.o -MT $@
That generates a dependency file in the form:
    $(objtree)/%.o $(objtree)/%.d: (dependency list)
    (dependency-list-entry-1):
    (dependency-list-entry-2):
    etc...
It's pretty handy. Avoiding all the sed stuff is nice.
AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.