make clean命令清理在不同目录中编译的对象

发布时间 2023-10-21 09:55:04作者: imxiangzi
 

Using Makefile to clean subdirectories

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

例如,当前在我的Makefile中,我有类似以下内容:

1
2
3
4
5
6
7
8
9
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。 否则,我会得到错误

1
No rule to make target clean

由于我仍然只想在每个子目录中运行命令" rm -rf * .o?core .depend ..cmd * .ko * .mod.c",因此似乎不得不在每个子目录中都包含一个Makefile,这是多余的。 完全相同的线清洁。 没有办法简单地在每个子目录中运行相同的clean命令吗?

 

  • 您可能只想让clean命令以递归方式删除文件。 参见:superuser.com/questions/61258/
  • 或只是循环循环遍历$(SUBDIRS)并手动运行每个rm。
  • 实际上,如果您仔细地编写顶级Makefile(或编写包含的单独的clean.mk makefile),那么我认为可以在该配方中$(MAKE) -C $@ -f clean.mk clean。 (注意$@而不是$(SUBDIRS)。-C接受单个参数而不是列表。)
  • 您将在子make上获得SUBDIRS变量的副本,这会破坏过程的递归部分。 仅当您具有相同的子目录(具有相同的名称)时,该计划才有效。

 

 


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

1
2
3
4
5
6
7
8
9
10
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

 

  • 您如何在src或src1中递归一次?您如何知道其中有多少个子目录并构造变量SUBDIRS的新版本?
  • 该示例已完成。 运行make --debug将显示正在发生的事情。 如果硬编码列表不起作用,则类似find的东西可能会检测到子目录。

 

 


除了使用递归,您还可以使用find来获取目录列表,并进行一次迭代以生成通配符:

1
2
3
4
5
6
7
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)

 

 


@Christoph答案的变体:

1
2
3
4
5
6
7
8
9
# 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使用与要清除的目录列表相反的内容,即,要清除的目录列表。当您只有一个或两个目录(.git和images)不想清理,但又想清理其他所有内容时,此功能很有用。


您不能没有外部程序的帮助。最好的方法是在每个子目录中执行递归和调用的shell脚本(请看我对@robert的评论),这样的事情就可以完成工作(并且不依赖于GNU make功能)

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

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

1
2
3
4
5
6
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)这样的好工具

 

 

 

from:  https://www.codenong.com/26007005/