You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修正点:

  1. 路径替换逻辑:在shell循环中使用subst提取目录名,避免Makefile变量展开时机问题
  2. 循环方式:利用Makefile的目标依赖机制遍历目录,比shell循环更符合Makefile规范
  3. 目录预创建:添加create_dirs目标确保./source目录存在,避免生成图片时出错
  4. 语法修正:移除方法2中SUB_DIRECTORIES =:的多余冒号,修正foreach的错误用法

内容的提问来源于stack exchange,提问作者Koa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:35:28