Take the 2-minute tour ×

I've got this makefile:

ALL = ../lib/Mo.pm \
      ../lib/Mo/builder.pm \
      ../lib/Mo/default.pm \
      ../lib/Mo/has.pm \

all: $(ALL)

$(ALL): Mo.pm compress.pl Makefile
    perl compress.pl $(@:../lib/%=%) > $@

What it's meant to do is something like this:

$ make -n
perl compress.pl Mo.pm > ../lib/Mo.pm
perl compress.pl Mo/builder.pm > ../lib/Mo/builder.pm
perl compress.pl Mo/default.pm > ../lib/Mo/default.pm
perl compress.pl Mo/has.pm > ../lib/Mo/has.pm

However with dmake on Windows this happens:

d:\mo-pm\src>dmake -n
perl compress.pl ..\lib\Mo.pm > ..\lib\Mo.pm
perl compress.pl ..\lib\Mo\builder.pm > ..\lib\Mo\builder.pm
perl compress.pl ..\lib\Mo\default.pm > ..\lib\Mo\default.pm
perl compress.pl ..\lib\Mo\has.pm > ..\lib\Mo\has.pm

I've been trying out various combinations of s/// and subst to make it work in dmake, and found out that it wants the path to have \s, which means a double substitution against both variants of the path (../lib/ and ..\lib) could work, but i can't figure out how to make it work for both make variants.

Any ideas or other ways to do this?

share|improve this question

1 Answer 1

up vote 3 down vote accepted

It's not only that the dir separator chars are different for both versions, moreover the dmake syntax seems to be deliberately designed to be incompatible with GNU make. The only part of the syntax that is actually compatible is pattern substitution, so this is the way to go:

 all: $(ALL)

 $(ALL) : Makefile compress.pl
 ../lib/%.pm : %.pm 
         perl compress.pl $< > $@

dmake actually substitutes the / for directory separator chars for you here. I've tested this Makefile with an echo instead, and it writes to the right directory.

Explanation: The pattern rules define rules for a particular file to be re-made when it matches a regular expression (the ../lib/%.pm part) and a prerequisite of a similar name is found (%.pm). The % in the prerequisite is replaced by the matching part of the % in the target. The extra rule with Makefile and compress.pl is needed because dmake doesn't like extra prerequisites in a pattern rule. As usual, $< and $@ are make's special variables for source and target file.

So, the core difference is that your original rule said "the files named in this list can be made with the following rule), while the pattern rule says "any file looking like ../lib/%.pm can be made from a matching file in the current directory" and then gives a list of pm files to make.

Pattern rules are actually quite powerful, useful to know. Unfortunately, some makes don't know them, only the older suffix rules.

Further details of what's going on can be obtained by running

make -rdn
share|improve this answer
This works perfectly, thank you! The only thing i needed to look out for is that the indendation in front of the compress line needs to be an actual tab. Would you mind going into detail a bit to explain what happens here? I honestly don't understand what's going on there. (Though i can sort of guess.) (Bounty's your's in three hours.) –  Mithaldu Sep 29 '11 at 10:55
@Mithaldu: You're welcome, and thanks :-). –  thiton Sep 29 '11 at 11:56
Very useful explanation, thank you! :D The first attempt at this actually did use pattern rules, but broke, and you explained why it broke. :) –  Mithaldu Sep 29 '11 at 14:05

Your Answer


