Jamie
Jamie

Reputation: 7431

How to make a recursive make evaluate sub-directory pre-requisites?

Appreciating that the title is not quite on "target", how can I make it so that when I call make at the top level, it will recursively call the makefiles in the sub-directories?

Having been intrigued by the Kconfig pattern, to learn it, I've applied it to a mark down to pdf generator.

The recursive Makefile resides in ./scripts/Makefile.boilerplate and is defined:

HEADER=$(wildcard section-header.md)

.PHONY:all clean $(md-sub-y)
all clean: $(md-sub-y)

all: $(TARGET)

clean:
    @ $(RM) $(TARGET)

$(TARGET): $(HEADER) $(md-y) | $(md-sub-y)
    @ cat /dev/null $^ > $@

$(md-sub-y):
    @ $(MAKE) -C $(@D) TOPDIR=$(TOPDIR) $(MAKECMDGOALS)

I'm likely using the order-only prerequisite for the $(TARGET) target inappropriately, but it solved a minor problem.

In each directory there is a unique KConfig file (not shown), which lists CONFIG_{OPTION} macros that evaluate to either y or n. Then each directory contains a Makefile that has the form:

include Kconfig

md-$(CONFIG_INTRODUCTION)+= Introduction.md
md-$(CONFIG_FW_UPDATE)+= FW-update.md
md-sub-$(CONFIG_CHAPTERS)+= Chapters/Chapters.md
md-$(CONFIG_CHAPTERS)+= Chapters/Chapters.md
md-$(CONFIG_EXAMPLES)+= Examples.md
md-$(CONFIG_APPENDIX_I)+= Appendix-I.md
md-$(CONFIG_APPENDIX_II)+= Appendix-II.md
md-$(CONFIG_APPENDIX_III)+= Appendix-III.md

include ${TOPDIR}/scripts/Makefile.boilerplate

And finally, the very top level makefile is (abbreviated):

.PHONY: all clean pdf embedded_html
all clean test: JsonAPI/JsonAPI.md

all: pdf embedded_html

pdf: $(MARKDOWN_FILES:.md=.pdf)

embedded_html: $(MARKDOWN_FILES:.md=.html)

MAKEFLAGS += --no-print-directory

clean:
    @ $(RM) *.pdf *.html

JsonAPI/JsonAPI.md:
    @ $(MAKE) -C $(@D) TOPDIR=${CURDIR} $(MAKECMDGOALS)

%.html:%.md
    @ pandoc -s --toc -c /var/www/css/bootstrap.css $< -f markdown -t html -s -o $@

%.pdf:%.md
    @ pandoc --read=markdown --table-of-contents --toc-depth=3 --preserve-tabs --standalone --template=template.latex $(PANDOC_ENGINE)=pdflatex --listings -V geometry:margin=1in --highlight-style=pygments -H listing-setup.tex -r markdown+simple_tables+table_captions+yaml_metadata_block $< -o $@

If I call make on an unbuilt directory tree, it works fine. But there are a few problems I'm not sure how to address:

  1. How can I ensure that if an updated .md deeply nested in the directory tree will cause the top level PDF file to be updated? Or, How can I force the makefile's in the sub-directories to be called?
  2. The clean target at the top level is problematic, in that it doesn't recurse through the sub-directories. What do I need to do to remedy that?
  3. Is there a better way to include the Makefile.boilerplate makefile, without having to define the TOPDIR on the $(MAKE) command line as I've done?

For 1, and 2, I'm guessing that an empty target dependency (FORCE:) will be required. And for 3, I've tried using $(CURDIR) but it was always evaluating to the directory the Makefile resided in, not the parent directory where the original make command was invoked.

Upvotes: 0

Views: 321

Answers (1)

Jamie
Jamie

Reputation: 7431

Changing the md-sub-$(CONFIG_EEEE) macro definition to be just the directory was the key, and to make those targets have an empty rule.

Essentially, the per directory Makefile from above becomes:

include Kconfig

md-$(CONFIG_INTRODUCTION)+= Introduction.md
md-$(CONFIG_FW_UPDATE)+= FW-update.md
md-sub-$(CONFIG_CHAPTERS)+= Chapters/Chapters.md
md-$(CONFIG_CHAPTERS)+= Chapters
md-$(CONFIG_EXAMPLES)+= Examples.md
md-$(CONFIG_APPENDIX_I)+= Appendix-I.md
md-$(CONFIG_APPENDIX_II)+= Appendix-II.md
md-$(CONFIG_APPENDIX_III)+= Appendix-III.md

include ${TOPDIR}/scripts/Makefile.boilerplate

and the default Makefile.boilerplate changes the $(md-sub-y) target too:

$(md-sub-y): FORCE
    @ $(MAKE) -C $@ TOPDIR=$(TOPDIR) $(MAKECMDGOALS)

FORCE:

And the top level makefile no longer needs $(@D) on the command line for the JsonAPI recipe, just $@.

Upvotes: 0

Related Questions