Aug 4

Say one stage in your build process is a tool that writes out a series of source files and config files. You might have a rule that looks a bit like this:

glue.c glue.h net_conf.xml error_list.config: application.config context.xml target.conf
        generate_glue.exe $^

The trouble is, this is exactly the same as specifying four rules, one for each of the goals. And, depending on the exact version of make you use, you may find that generate_glue.exe is run four times. If that takes more than 4 minutes then you’re going to get really mad. Especially if you have, say, 80 test applications to generate.

A pattern to get around this is to cause the dependency “tree” to reconverge around a marker that tells you when the generator was last run:

glue.c glue.h net_conf.xml error_list.config: glue_generated.touch
        # nothing here
glue_generated.touch: application.config context.xml target.conf
        generate_glue.exe $^
        touch glue_generated.touch

This way, glue_generated.touch gets checked for its age a bunch of times, but the generation action is only executed if some config file is newer than the touch file.

ISTR that this can fail too (maybe it’s if the time granularity is too large) because somewhere I ended up with a horrible bunch of macrology that actually tested the file age explicitly in order to avoid it STILL running the tool n times.

Anyhow. This doesn’t seem to be anywhere on the internets, so it is now.


9 comments so far...

  • ianb1469 Said on August 4th, 2008 at 18:41:

    Steve,
    Here’s another way (at least for GNU make), using the special support for this in a pattern rule.
    i.

    == Multiple targets made once ==
    * Normally a rule with multiple targets is executed once for each target:

    file1 file2 : otherfiles
            commands

    will execute commands twice, setting $@ to file1 and file2 individually.

    Sometimes you want a single command to generate multiple targets. The trick to this is to transform the rule into a pattern rule, which has an exception to cope with things like:

    %.tab.c %.tab.h: %.y
            bison -d $<

    If you want to use this, but without a pattern then you need to create a phony target:

    file1 file2 %.phony1 : otherfiles
            commands

    You need to ensure that the %.phonyXX targets are unique within the invocation of make.

  • lordhutton Said on August 4th, 2008 at 19:08:

    What was that that just shot over my head?

  • sweavo Said on August 4th, 2008 at 19:49:

    Great find, ianb! Where was that?

    ** goes to change all his makefiles **

  • ianb1469 Said on August 4th, 2008 at 20:59:

    Originally, I think I saw it in TFM for GNU make.

    But the juicy bits are just pulled from the our internal wiki :-)

  • sweavo Said on August 5th, 2008 at 08:41:

    addendum. Just tried it without joy on our system (gnu make 3.81 under cygwin under XP Pro). Back to the .touch dodge :-(

  • ianb1469 Said on August 6th, 2008 at 06:23:

    Works for me….is there a missing dependency somewhere else? Perhaps something updating your depenencies for the double target rule?

    Your comment about your other approach requiring extra macrology makes me wonder about this too.

    Also - with your first solution, remember to make the touch of the temp file dependent on successs of the real command. ” && touch ..”

  • ianb1469 Said on August 6th, 2008 at 07:30:

    There’s a neat trick to debug these kind of things (from http://www.ddj.com/development-tools/197003338)

    Add these lines to the start of the file:

    OLD_SHELL:=$(SHELL)
    SHELL = $(warning [$@ ($^) ($?)])$(OLD_SHELL)

    Every time you execute a command, you’ll see something like

    Makefile:7: [t1 (f1 f2) (f1 f2)]

    The syntax is:
    file:linenumber of the rule
    [ target
    (full list of prerequisites of that target)
    (which prerequisites are out of date) ]

  • sweavo Said on August 6th, 2008 at 08:22:

    I don’t think the && is necessary, as make will abandon the sequence of commands on failure (unless the command is prefixed by -)

    Nice debug trick, though!

  • ianb1469 Said on August 6th, 2008 at 20:03:

    I’ve checked and double checked and built yet more test cases. The rule with the %phony works. You surely have a missing dependency somewhere else that is triggering the rule twice.

    Either that or just an embarrassing typo in a rule.

leave a reply

You must be logged in to post a comment.

 

August 2008
S M T W T F S
« Jul   Sep »
 12
3456789
10111213141516
17181920212223
24252627282930
31  

Archives

Meta