Gnumake rules and templates

I use GNUmake to create a deployment version of some web content from the source directory. I want to be rules that will run some files using compression tools (like YUI compressor), and then for everything that doesn't have a rule, just copy it.

So for example:

# Rule with all the $(WWW_OUT_DIR)/*.* files as a prerequisite all: $(WWW_OUT_FILES) # Generic rule to perform compression on Javascript files. $(WWW_OUT_DIR)/%.js: $(WWW_SRC_DIR)/%.js $(YUI_COMP) $(YUI_COMP_OPTS) $< > $@ # Generic rule to perform compression on CSS files. $(WWW_OUT_DIR)/%.css: $(WWW_SRC_DIR)/%.css $(YUI_COMP) $(YUI_COMP_OPTS) $< > $@ # TDB Rule to magically handle everything else? (This doesn't work) $(WWW_OUT_DIR)/%.%: $(WWW_SRC_DIR)/%.% cp $< $@ 

How can I fulfill what the last rule is trying to fulfill? That is, for everything in $ (WWW_OUT_FILES) that is not .js or .css, just copy it? If possible, I want to keep the dependency on the corresponding input file.

+4
source share
1 answer

You are almost right, the only thing that needs to be fixed is the last rule of the template, just delete the extra percent symbol:

 $(WWW_OUT_DIR)/%: $(WWW_SRC_DIR)/% cp $< $@ 

Also keep in mind that with GNU Make 3.82, the template search algorithm has been slightly modified (from Changelog):

Template-specific variables and template rules are now applied in a short first-order order instead of the definition order (variables and rules with the same bar length are still applied in the order definition). This creates the usually desired behavior when more specific patterns are preferred.

This is exactly what you want if using the latest version of Make. In order for your Makefile to be compatible with other versions of GNU Make (including versions earlier than 3.82), the rule must be defined after the others (as in the original question).

UPD

A good example from here :

Prior to version 3.82, when gmake finds several matches while searching for a template, it prefers templates declared earlier in the makefile over templates declared later. Starting with 3.82, gmake instead prefers a pattern that results in the shortest stem. This sounds a little vague due to jargon, but I think it actually makes gmake better stick to the principle of least surprise. Here is an example:

 all: sub/foo.x %.x: @echo "Prefer first match (stem is $*)." sub/%.x: @echo "Prefer most specific match (stem is $*)." 

Compare the output from gmake 3.81 and 3.82:

  • gmake 3.81

     Prefer first match (stem is sub/foo). 
  • gmake 3.82

     Prefer most specific match (stem is foo). 

gmake 3.82 prefers the second template because it is more specific than the first. Please note that this is a significant incompatibility compared to previous versions of gmake!

+6
source

Source: https://habr.com/ru/post/1396726/


All Articles