在 makefile 中,如何在一次调用中处理多个目标?
In makefile, how do I process multiple targets in one call?
我正在使用一个私有脚本,该脚本会定期将多个 (~100) 个文本文件转换为 HTML。我写了一个 makefile 只转换有变化的文本文件:
TEXT_DIR = /path/to/app/data/
OUTPUT_DIR = /path/to/app/reports/
.PHONY : html
html : $(wildcard $(OUTPUT_DIR)/*.html)
$(OUTPUT_DIR)/%.html : $(TEXT_DIR)/%.txt
generate_html --html $< $@
当我 运行 make
时,它会为每个更改的文件调用一次脚本:
generate_html --html /path/to/app/data/file1.txt /path/to/app/reports/file1.html
generate_html --html /path/to/app/data/file2.txt /path/to/app/reports/file2.html
generate_html --html /path/to/app/data/file3.txt /path/to/app/reports/file3.html
这非常慢,因为脚本在读取配置和设置时在初始加载时需要一些时间。在一个 运行 中处理所有文件要快得多:
generate_html --html /path/to/app/data/file1.txt /path/to/app/reports/file1.html --html /path/to/app/data/file2.txt /path/to/app/reports/file2.html --html /path/to/app/data/file3.txt /path/to/app/reports/file3.html
如何制作 GNU Make 运行 脚本?
如果您不介意创建一个保存上次构建时间的文件(即这里的 last-run.txt
),您可以这样做。在这里,我使用 $?
获取所有比 last-run.txt
更新的文本文件。比照。 GNU Make Automatic Variables.
TEXT_DIR = /path/to/app/data
OUTPUT_DIR = /path/to/app/reports
build_html_name = $(OUTPUT_DIR)/$(notdir $(1:.txt=.html))
.PHONY: html
html: last-run.txt
last-run.txt: $(wildcard $(TEXT_DIR)/*.txt)
./generate_html $(foreach f,$?,--html $f $(call build_html_name,$f))
date > $@
只要文件的修改时间得到更新,last-run.txt
的内容并不重要;所以 touch $@
而不是 date > $@
完成了这项工作。
您可以使用变量来存储必须更改的文件,而不是直接在 ${OUTPUT_DIR}/%.html
目标中直接 运行 命令。
TEXT_DIR = /path/to/app/data/
OUTPUT_DIR = /path/to/app/reports/
.PHONY : html
html : $(wildcard $(OUTPUT_DIR)/*.html)
generate_html ${TODO}
$(OUTPUT_DIR)/%.html : $(TEXT_DIR)/%.txt
$(eval TODO=${TODO} --html $< $@)
我正在使用一个私有脚本,该脚本会定期将多个 (~100) 个文本文件转换为 HTML。我写了一个 makefile 只转换有变化的文本文件:
TEXT_DIR = /path/to/app/data/
OUTPUT_DIR = /path/to/app/reports/
.PHONY : html
html : $(wildcard $(OUTPUT_DIR)/*.html)
$(OUTPUT_DIR)/%.html : $(TEXT_DIR)/%.txt
generate_html --html $< $@
当我 运行 make
时,它会为每个更改的文件调用一次脚本:
generate_html --html /path/to/app/data/file1.txt /path/to/app/reports/file1.html
generate_html --html /path/to/app/data/file2.txt /path/to/app/reports/file2.html
generate_html --html /path/to/app/data/file3.txt /path/to/app/reports/file3.html
这非常慢,因为脚本在读取配置和设置时在初始加载时需要一些时间。在一个 运行 中处理所有文件要快得多:
generate_html --html /path/to/app/data/file1.txt /path/to/app/reports/file1.html --html /path/to/app/data/file2.txt /path/to/app/reports/file2.html --html /path/to/app/data/file3.txt /path/to/app/reports/file3.html
如何制作 GNU Make 运行 脚本?
如果您不介意创建一个保存上次构建时间的文件(即这里的 last-run.txt
),您可以这样做。在这里,我使用 $?
获取所有比 last-run.txt
更新的文本文件。比照。 GNU Make Automatic Variables.
TEXT_DIR = /path/to/app/data
OUTPUT_DIR = /path/to/app/reports
build_html_name = $(OUTPUT_DIR)/$(notdir $(1:.txt=.html))
.PHONY: html
html: last-run.txt
last-run.txt: $(wildcard $(TEXT_DIR)/*.txt)
./generate_html $(foreach f,$?,--html $f $(call build_html_name,$f))
date > $@
只要文件的修改时间得到更新,last-run.txt
的内容并不重要;所以 touch $@
而不是 date > $@
完成了这项工作。
您可以使用变量来存储必须更改的文件,而不是直接在 ${OUTPUT_DIR}/%.html
目标中直接 运行 命令。
TEXT_DIR = /path/to/app/data/
OUTPUT_DIR = /path/to/app/reports/
.PHONY : html
html : $(wildcard $(OUTPUT_DIR)/*.html)
generate_html ${TODO}
$(OUTPUT_DIR)/%.html : $(TEXT_DIR)/%.txt
$(eval TODO=${TODO} --html $< $@)