Makefile遍历目录生成目录树图片遇阻,求技术解决方案
通用Makefile编写问题排查与解决
我是Makefile新手,需要编写一个通用Makefile实现以下功能:
- 遍历指定目录的所有子目录
- 判断目标目录是指定根目录还是其子目录
- 通过
tree命令生成目录树,再用convert命令生成去除文件路径的目录树图片
手动指定目录的硬编码版本可正常运行,但尝试两种方法均报错,具体如下:
方法1
PROJECT_DIR = ../hub/hub/ SUB_DIRECTORIES = $(shell find $(PROJECT_DIR) -maxdepth 1 -type d -exec echo {} \;) SUB_DIRECTORIES_FORMATTED = $(SUB_DIRECTORIES) | sed 's|..\/hub\/hub\/||g' | sed 's/\s\+/|/g' all: @echo $(SUB_DIRECTORIES) for $(directory) in $(SUB_DIRECTORIES); do \ if test $$directory = $(PROJECT_DIR); then \ echo "Generating root.png" && tree -P '*.py' -I '__pycache__|.c' $(directory) | convert -size 364x422 label:@- ./source/root.png; \ else \ "Generating $(subst $(PROJECT_DIR),,$(directory)) png" && tree -P '*.py' -I '__pycache__|.c' $(directory) | convert -size 364x422 label:@- ./source/$(subst $(PROJECT_DIR),,$(directory)).png; \ fi \ done
错误情况:subst功能失效,生成的文件名包含完整路径,导致报错。
方法2
PROJECT_DIR = ../hub/hub/ SUB_DIRECTORIES =: $(shell find $(PROJECT_DIR) -maxdepth 1 -type d -exec echo {} \;) SUB_DIRECTORIES_FORMATTED = $(SUB_DIRECTORIES) | sed 's|..\/hub\/hub\/||g' | sed 's/\s\+/|/g' all: @$(foreach file, $(wildcard $(SUB_DIRECTORIES)/), \ $(if $(filter $(file), $(PROJECT_DIR)), \ $(shell tree -P '*.py' -I '__pycache__|.c' $(file) | convert -size 364x422 label:@- ./source/root.png;), \ $(shell tree -P '*.py' -I '__pycache__|.c' $(file) | convert -size 364x422 label:@- ./source/$(subst $(PROJECT_DIR),,$(file)).png;) \ ) \ );
错误情况:语法错误,foreach执行逻辑不符合Makefile规则,导致运行失败。
解决方案
下面是修正后的通用Makefile,解决了路径替换和循环逻辑的问题:
# 指定项目根目录 PROJECT_DIR := ../hub/hub/ # 获取根目录下所有一级子目录(含根目录本身) SUB_DIRECTORIES := $(shell find $(PROJECT_DIR) -maxdepth 1 -type d) # 确保source目录存在 .PHONY: all clean all: create_dirs generate_images create_dirs: @mkdir -p ./source generate_images: $(SUB_DIRECTORIES) $(SUB_DIRECTORIES): @if [ "$@" = "$(PROJECT_DIR)" ]; then \ echo "Generating root.png"; \ tree -P '*.py' -I '__pycache__|.c' "$@" | convert -size 364x422 label:@- ./source/root.png; \ else \ # 提取目录名称,替换掉根路径 DIR_NAME=$(subst $(PROJECT_DIR),,$@); \ echo "Generating $$DIR_NAME.png"; \ tree -P '*.py' -I '__pycache__|.c' "$@" | convert -size 364x422 label:@- ./source/$$DIR_NAME.png; \ fi clean: @rm -rf ./source/*.png
关键修正点:
- 路径替换逻辑:在shell循环中使用
subst提取目录名,避免Makefile变量展开时机问题 - 循环方式:利用Makefile的目标依赖机制遍历目录,比shell循环更符合Makefile规范
- 目录预创建:添加
create_dirs目标确保./source目录存在,避免生成图片时出错 - 语法修正:移除方法2中
SUB_DIRECTORIES =:的多余冒号,修正foreach的错误用法
内容的提问来源于stack exchange,提问作者Koa
相关产品推荐
相关产品推荐

