使用Makefile清理子目录

时间:2014-09-24 01:13:45

标签: makefile gnu-make

是否可以从父目录执行make clean,它也可以递归清理所有子目录,而不必在每个子目录中包含makefile?

例如,目前在我的Makefile中,我有类似的东西:

SUBDIRS = src, src1

.PHONY: clean subdirs $(SUBDIRS)

clean: $(SUBDIRS)
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c

$(SUBDIRS):
    $(MAKE) -C $(SUBDIRS) clean 

但是,这要求我在src和src1中都有一个Makefile。否则,我会收到错误

No rule to make target clean

因为我只想在每个子目录中运行命令“rm -rf * .o ~core .depend。 .cmd * .ko * .mod.c”,所以似乎多余了必须在每个子目录中包含一个Makefile,并使用完全相同的行进行清理。是不是只能在每个子目录中运行相同的清洁命令?

5 个答案:

答案 0 :(得分:1)

我同意你可以让rm命令对子目录进行操作。但是类似下面的内容允许仅使用单个makefile进行递归make:

SUBDIRS = . src src1
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))

clean: $(SUBDIRSCLEAN)

clean_curdir:
    rm -rfv *.o *~ core .depend .*.cmd *.ko *.mod.c

%clean: %
    $(MAKE) -C $< -f $(PWD)/Makefile clean_curdir

答案 1 :(得分:1)

不是使用递归,而是可以向find发送shell以获取目录列表并执行单次迭代以生成通配符:

SUBDIR_ROOTS := foo bar
DIRS := . $(shell find $(SUBDIR_ROOTS) -type d)
GARBAGE_PATTERNS := *.o *~ core .depend .*.cmd *.ko *.mod.c
GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS)))

clean:
    rm -rf $(GARBAGE)

答案 2 :(得分:0)

你不能没有外部程序的帮助。最好的是一个shell脚本,它在每个子目录中执行递归和调用make(在他的响应中查看我对@robert的评论)这样的事情将完成工作(并且不依赖于GNU make功能)

#!/bin/sh
ROOTDIR=`/bin/pwd`
for dir in `find . -type d -print`
do
    make -C "${dir}" -f "${ROOTDIR}"/Makefile clean
done

当然,您可以将此序列(在目标cleanrec中)放在Makefile

cleanrec:
    ROOT=`/bin/pwd`; \
    for dir in `find . -type d -print`; \
    do \
        make -C "$${dir}" -f "$${ROOTDIR}"/Makefile clean; \
    done

并保留clean目标以进行本地清理单个目录。原因是Makefile只有静态信息来进行make,你必须得到一些外部帮助才能知道你在每个目录中有哪些子目录。所以,如果你要获得外部帮助,你最好使用一个好工具 find(1) sh(1)

答案 3 :(得分:0)

@Christoph答案的变体:

# Exclude directory from find . command
# https://stackoverflow.com/questions/4210042/exclude-directory-from-find-command
GARBAGE_TYPES         := "*.gz(busy)" *.aux *.log *.pdf *.aux *.bbl *.log *.out *.synctex.gz *.fls
DIRECTORIES_TO_CLEAN  := $(shell find -not -path "./.git**" -not -path "./images**" -type d)
GARBAGE_TYPED_FOLDERS := $(foreach DIR, $(DIRECTORIES_TO_CLEAN), $(addprefix $(DIR)/,$(GARBAGE_TYPES)))

clean:
    $(RM) -rf $(GARBAGE_TYPED_FOLDERS)
    # echo $(GARBAGE_TYPED_FOLDERS)

这是乳胶文件的示例。由于文件类型名称上的括号,GARBAGE_TYPES上的第一个模式在其周围有双引号。没有它,rm无法删除它们。其他模式不需要引号。

第二个DIRECTORIES_TO_CLEAN使用与清理目录列表相反的目录,即不清理的目录列表。当您只有一个或两个目录.gitimages时,如果您不想清理这些目录,但想清除其他所有目录,这非常有用。

答案 4 :(得分:0)

ALL_MOD = $(shell find . -maxdepth 1 -type d )
ALL_MOD_CLEAN = $(addsuffix .clean, $(ALL_MOD))

.PHONY: $(ALL_MOD_CLEAN) $(ALL_MOD) default all clean

$(ALL_MOD_CLEAN): 
    $(E) "cleaning $(basename $@)"
    if [ -e $(basename $@)/Makefile ] ; then \
            $(MAKE) -C $(basename $@) clean ;\
    fi 

clean: $(ALL_MOD_CLEAN)
    $(E) "cleaning complete: " $(ALL_MOD)

添加“。”后缀并使用$(basename ...)代替原始目标,否则每次需要清理项目时都会重新制作所有文件