0

I'm trying to take some source files, create some customised versions of those sources, then process those customised sources down to output files I can use. I'm using this make file. Note that this file is not fully complete, currently it only does the CSS* make, once that's working I will add the PHP* make which is similar:

# root sources
CSSSOURCES =    $(wildcard *.scss)
PHPSOURCES =    $(wildcard *.phtml)

# partials, creates a configed source
CSSMSOURCES =   $(addprefix m.,$(CSSSOURCES:.scss=.m)) 
CSSDSOURCES =   $(addprefix d.,$(CSSSOURCES:.scss=.d)) 
PHPMSOURCES =   $(addprefix m.,$(PHPSOURCES:.phtml=.m)) 
PHPDSOURCES =   $(addprefix d.,$(PHPSOURCES:.phtml=.d))

# targets
CSSMTARGETS =   $(CSSMSOURCES:.m=.css)
CSSDTARGETS =   $(CSSDSOURCES:.d=.css)
PHPMTARGETS =   $(PHPMSOURCES:.m=.php)
PHPDTARGETS =   $(PHPDSOURCES:.d=.php)

# ensure no clash with built in rules
.SUFFIXES: .m .d .scss .css .phtml .php

all:    $(CSSMTARGETS)

%.m:    %.scss
    echo "%define MOBILE" | cat - $< >tmp
    mv tmp $@

%.d:    %.scss
    echo "%define DESKTOP" | cat - $< >tmp
    mv tmp $@

%.css:  %.m %d
    cat $< | mym1.pl >$@
    rm $<

.PHONY: test
test:
    @echo "sources - $(CSSSOURCES)"
    @echo "msources - $(CSSMSOURCES)"
    @echo "targets - $(CSSMTARGETS)"

Instead of creating the CSS targets I get this error:

make: *** No rule to make target 'm.page.css', needed by 'all'. Stop.

carlesgg97
  • 4,184
  • 1
  • 8
  • 24
  • Got the '%.css' rule to work on m.page.css you need m.page.m and m.page.d. However, note that the command also remove the input file (rm $<)'. – dash-o Oct 23 '19 at 10:32
  • The "rm $<" is about cleaning up the intermediate .m and .d files after the css has been created, if I comment this out I still get the same error message – user5007932 Oct 23 '19 at 10:56
  • So fo you have a file `m.page.scss`? – tripleee Oct 23 '19 at 11:06
  • I have a file page.scss (source) which make should turn into m.page.m and m.page.d (intermediate file via %.m and %.d rules) which make should then turned into m.page.css and d.page.css (targets via %.css rule) – user5007932 Oct 23 '19 at 11:14
  • But there are no recipes in your Makefile which do this. If you need a target `m.page.m` to exist, you need to tell `make` how it should be made. – tripleee Oct 23 '19 at 11:16
  • My logic (which could be wrong) was that to make the m.page.css target make would look for m.page.m (the %.css: %.m %.d rule), would not find it, so using the %.m: %.scss rule make would make m.page.m from page.css first – user5007932 Oct 23 '19 at 11:40
  • I'm guessing you are looking for a way to create `{m,d}.{a,b,c,d}.css` from sources `a.scss`, `b.scss`, `c.scss`, `d.scss` and correspondingly `.html` from `.phtml` but this is not really clear from the question. Could you please [edit] to clarify? – tripleee Oct 23 '19 at 11:49
  • Writing to a `tmp` file and then moving to `$@` separately is brittle and prevents parallel `make`. If you need this, don't use a static file name `tmp`; but here, really, I don't think there is any useful way for `cat` to fail where `cat` + `mv` succeeds, so probably just don't use a temporary file. – tripleee Oct 23 '19 at 11:52
  • Not keen on a tmp file myself but its all I could come up with...you are correct, Im trying to "create {m,d}.{a,b,c,d}.css from sources a.scss, b.scss, c.scss, d.scss and correspondingly .php from .phtml", I tried to say this in the first couple of lines of the post, apologies if I was not clear. How would you do this via make? – user5007932 Oct 23 '19 at 12:02
  • I agree with the comment about static TMP. Usually, the solution that can be used is: create-output > $@.tmp && mv $@.tmp $@ – dash-o Oct 23 '19 at 12:03

2 Answers2

0

make operates on file names; if there is no file named m.page.m and no file named m.page.d - which is what m.page.css depends on in accordance with your declared dependencies - then Make will conclude that it needs to create these. If it does not have any rules (built-in or by way of a recipe) to create those, the error message you get tells you pretty much exactly that.

I'm guessing what you actually want is something like

m.%: %
    echo "%define MOBILE" | cat - $< >$@

d.%: %
    echo "%define DESKTOP" | cat - $< >$@

This tells make how to create m.whatever and d.whatever from whatever; so it now knows how to create m.x.phtml from x.phtml and d.y.scss from y.scss etc.

(Notice also how this avoids the separate mv of a static temporary file name, as discussed in comments.)

%.css: %.scss
    mym1.pl <$< >$@
%.php: %.phtml
    mym1.pl <$< >$@

This tells make how to create m.z.css from m.z.scss, d.w.php from d.w.phtml, etc. I'm guessing here that mym1.pl can handle both cases.

(Notice also the refactoring to avoid useless use of cat.)

This does away with the somewhat mysterious .m and .d suffixes so you probably have to refactor the variables at the top of your Makefile.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • After trying to stay with my original approach I eventually bit the bullet and refactored as you suggested, works and code is clean, many thanks – user5007932 Oct 23 '19 at 14:52
0

Instead of creating the CSS targets I get this error:

make: *** No rule to make target 'm.page.css', needed by 'all'.  Stop.

Your makefile provides exactly one rule by which m.page.css could be built or updated:

%.css:  %.m %d
    cat $< | mym1.pl >$@
    rm $<

In order for that rule to apply, however, both of the prerequisites, expressed as %.m and %d [sic] need to exist or be able to be built. There are problems with both.

The former in this case represents a file m.page.m. This apparently does not already exist, but you have a rule by which it could be built from m.page.scss. Except you don't have an m.page.scss or any rule to build one. The corresponding root source file is actually page.sccs.

The latter prerequisite, %d, would have an analogous problem, but it doesn't even get that far because you have omitted a period from the prerequisite name (should be %.d, not %d).

The rule quoted above is moreover bogus because it designates two prerequisites but only uses one. That's not inherently wrong, but it does not do anything useful to serve you here.

Replacing your current pattern rules with these should help:

m.%.m:    %.scss
    echo "%define MOBILE" | cat - $< >tmp
    mv tmp $@

d.%.d:    %.scss
    echo "%define DESKTOP" | cat - $< >tmp
    mv tmp $@

%.css:  %.m
    cat $< | mym1.pl >$@
    rm $<

%.css:  %.d
    cat $< | mym1.pl >$@
    rm $<
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Have worked on this approach along the lines of your suggestions and got it to work but as per previous comments it was messy so ended up changing approach to that suggested by @tripleee, thanks for your help – user5007932 Oct 23 '19 at 14:48