如何让GNU Make识别单个源文件生成多个输出文件?
解决SVG批量转PNG的Makefile依赖问题
针对你遇到的“无法跟踪数量未知的PNG输出文件依赖”的问题,核心思路是用**标记文件(stamp file)**间接管理依赖,或者通过shell命令直接判断触发条件,以下是两种可行方案:
方案1:用Stamp文件跟踪依赖(推荐)
这种方法通过一个小型标记文件记录SVG的最新状态,同时自动检查PNG的存在性和时效性:
# 替换成你实际的SVG转PNG命令 SVG_CONVERTER = your_svg_to_png_program # 模式规则:为每个SVG生成对应的标记文件 %.png.stamp: %.svg @# 定义当前SVG对应的所有PNG文件路径 @PNGS=$(basename $<).*.png; \ # 情况1:没有找到任何PNG文件,直接生成 if [ -z "$$(ls $$PNGS 2>/dev/null)" ]; then \ $(SVG_CONVERTER) $<; \ touch $@; \ else \ # 情况2:检查是否有PNG文件比SVG旧,有则重新生成 if [ -n "$$(find $$PNGS ! -newer $< | head -n1)" ]; then \ $(SVG_CONVERTER) $<; \ touch $@; \ fi; \ fi # 让所有生成的PNG依赖于标记文件,避免Makefile将其视为无关文件 $(wildcard *.000[0-9].png): %.png: $(basename %).png.stamp @# 空命令,仅声明依赖关系
工作逻辑
%.png.stamp是绑定到单个SVG的标记文件,它的更新条件完全符合你的需求:无PNG时、任意PNG过时都会触发转换命令。- 转换完成后更新标记文件的时间戳,确保它比所有PNG文件都新,后续Makefile会以此判断是否需要重新构建。
方案2:无Stamp的简化版
如果不想额外生成标记文件,可以用伪目标触发检查,直接通过shell命令判断条件:
SVG_CONVERTER = your_svg_to_png_program # 伪目标:触发所有SVG的检查与更新 update-pngs: $(patsubst %.svg,%.check,$(wildcard *.svg)) # 每个SVG对应一个检查目标 %.check: %.svg @PNGS=$(basename $<).*.png; \ # 同时判断两种触发条件:无PNG 或 存在过时PNG if [ -z "$$(ls $$PNGS 2>/dev/null)" ] || [ -n "$$(find $$PNGS ! -newer $< | head -n1)" ]; then \ $(SVG_CONVERTER) $<; \ fi @touch $@
执行make update-pngs即可批量检查所有SVG并更新对应的PNG。
注意事项
- 务必把
your_svg_to_png_program替换成你实际使用的转换命令。 find $$PNGS ! -newer $< | head -n1是高效判断逻辑:找到第一个过时的PNG就停止检查,避免遍历所有文件浪费时间。
内容的提问来源于stack exchange,提问作者Marnanel Thurman
相关产品推荐
相关产品推荐

