【问题标题】:How to make a recursive make evaluate sub-directory pre-requisites?如何进行递归评估子目录先决条件?
【发布时间】:2021-07-13 16:40:55
【问题描述】:

感谢标题不是完全在“目标”上,我怎样才能使它在顶层调用make时,它会递归调用子目录中的makefile?

对 Kconfig 模式很感兴趣,为了学习它,我将它应用到了一个标记为 pdf 的生成器。

递归 Makefile 位于 ./scripts/Makefile.boilerplate 并被定义:

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)

我可能不恰当地使用了 $(TARGET) 目标的仅订单先决条件,但它解决了一个小问题。

在每个目录中都有一个唯一的 KConfig 文件(未显示),其中列出了计算结果为 ynCONFIG_{OPTION} 宏。然后每个目录都包含一个 Makefile,格式如下:

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

最后,最顶层的 makefile 是(缩写):

.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 $@

如果我在未构建的目录树上调用 make,它可以正常工作。但是有几个问题我不知道如何解决:

  1. 如何确保更新的.md 深深嵌套在目录树中会导致顶级 PDF 文件被更新?或者,如何强制调用子目录中的 makefile?
  2. 顶层的clean 目标存在问题,因为它不会通过子目录递归。我需要做些什么来解决这个问题?
  3. 有没有更好的方法来包含Makefile.boilerplate makefile,而不必像我所做的那样在$(MAKE) 命令行上定义TOPDIR

对于 1 和 2,我猜测将需要一个空的目标依赖项 (FORCE:)。对于 3,我尝试使用 $(CURDIR),但它总是评估 Makefile 所在的目录,而不是调用原始 make 命令的父目录。

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    md-sub-$(CONFIG_EEEE) 宏定义更改为只是目录是关键,并使这些目标具有空规则。

    基本上,上面的每个目录Makefile 变成:

    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
    

    默认的Makefile.boilerplate 也改变了$(md-sub-y) 目标:

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

    并且顶级 makefile 不再需要 $(@D) 用于 JsonAPI 配方的命令行,只需 $@

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-12
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多