GNU does with many target directories

I need to integrate the generation of many HTML files into an existing Makefile . The problem is that HTML files must be in many different directories. My idea is to write an implicit rule that converts the source file (* .st) to the corresponding html file

 %.html: %.st $(HPC) -o $@ $< 

and a rule that depends on all html files

 all: $(html) 

If the HTML file is not in the builddir make file, it does not find the implicit rule: *** No rule to make target . If I change an implicit rule like this:

 $(rootdir)/build/doc/2009/06/01/%.html: %.st $(HPC) -o $@ $< 

he found, but then I should have an implicit rule for almost every file in the project. According to the Implicit Rules Search Algorithm in the GNU make manual, rule searches work as follows:

  • Divide t into the part of the directory called d, and the rest into n. For example, if t is src/foo.o', then d is src /', and n is `foo.o '.
  • Make a list of all the template rules, one of whose goals is t or n. If the target pattern contains a slash, it maps to t; otherwise, against n.

Why is the implicit rule not found, and what would be the most elegant solution if using GNU make ?

Here is a stripped down version of my Makefile :

 rootdir = /home/user/project/doc HPC = /usr/local/bin/hpc html = $(rootdir)/build/doc/2009/06/01/some.html %.html: %.st $(HPC) -o $@ $< #This works, but requires a rule for every output dir #$(rootdir)/build/doc/2009/06/01/%.html: %.st # $(HPC) -o $@ $< .PHONY: all all: $(html) 
+4
source share
4 answers

Like Maria Shalnova I like recursive make (although I disagree with “Recursive Make it considered harmful”), and generally it’s better to do something HERE from the source of THERE, and not vice versa. But if you need, I suggest a slight improvement: generate HTML generate only RULE, not COMMAND.

+4
source

Your active implicit rule makes $(rootdir)/build/doc/2009/06/01/some.html depend on $(rootdir)/build/doc/2009/06/01/some.st . If $(rootdir)/build/doc/2009/06/01/some.st does not exist, then the rule will not be used / found.

The recorded rule makes $(rootdir)/build/doc/2009/06/01/some.html dependent on some.st

One solution is to make the original layout match the destination / result layout.

Another option is to create rules as needed using eval . But it will be quite difficult:

 define HTML_template $(1) : $(basename $(1)) cp $< $@ endef $(foreach htmlfile,$(html),$(eval $(call HTML_template,$(htmlfile)))) 
+4
source

The best solution I have found so far is to create an implicit rule for each target directory using foreach-eval-call , as explained in the GNU make user guide . I have no idea how it scales to several thousand target directories, but we'll see ...

If you have a better solution, submit it!

Here is the code:

 rootdir = /home/user/project/doc HPC = /usr/local/bin/hpc html = $(rootdir)/build/doc/2009/06/01/some.html \ $(rootdir)/build/doc/2009/06/02/some.html targetdirs = $(rootdir)/build/doc/2009/06/01 \ $(rootdir)/build/doc/2009/06/02 define generateHtml $(1)/%.html: %.st -mkdir -p $(1) $(HPC) -o $$@ $$< endef $(foreach targetdir, $(targetdirs), $(eval $(call generateHtml, $(targetdir)))) .PHONY: all all: $(html) 
+4
source

Another possibility is for commando make invoke itself recursively with the -C argument with each output directory. Recursive make is a somewhat standard way of working with subdirectories, but beware of the consequences mentioned in the article “Recursive look is considered harmful”

+3
source

All Articles