在 makefile 中查找文件

Find files in makefile

我正在为 GNU make 创建一个 makefile。 我想查找目录结构中的所有文件。 为此,我尝试了:

find_files_recursive = $(wildcard $(1)/*)$(foreach dir,$(wildcard $(1)/*),$(call find_files_recursive,$(dir)))

$(info $(call find_files_recursive,.))

问题是这还会打印目录,而不仅仅是文件。有什么想法可以消除目录吗?

编辑: 我必须创建一个 OS 独立解决方案。所以 Unix-way find -type f 是别无选择的。但这正是我要解决的问题。

使用的解决方案: 根据接受的答案,我开发了一个较短的版本:

find_files_recursive = $(foreach item,$(wildcard $(1)/*),$(if $(wildcard $(item)/.),$(call find_files_recursive,$(item),$(2)),$(item)))

对于 GNU Make 4.2.1:

ffrec = $(foreach E,$(wildcard $(1)/*),\
        $(if $(realpath $(E)/.),$(call ffrec,$(E)),$(E)))
files  := $(call ffrec,.)

如果合适,与$(sort …)合并。

您可以使用 $(wildcard) 通过尝试将 /. 附加到其名称来检查名称是否实际上是一个目录。这将尝试从目录本身到达目录并且它不适用于文件。例如:

$ cat Makefile
filter_files = $(foreach item,$(1),$(if $(wildcard $(item)/.),,$(item)))
find_files_recursive = $(call filter_files,$(wildcard $(1)/*)) $(foreach dir,$(wildcard $(1)/*/.),$(call find_files_recursive,$(dir:/.=)))

$(info $(call find_files_recursive,.))

输出:

$ ls -R
.:
Makefile  foo

./foo:
bar  fooA  fooB

./foo/bar:
barA  baz

./foo/bar/baz:
bazA

$ make
 ./Makefile ./foo/fooB  ./foo/fooA ./foo/bar/barA  ./foo/bar/baz/bazA

由于对此类功能的请求不断弹出,因此 GNUmake table toolkit 中的内置函数 wildcard 现在有一个扩展。它通过一个明显的特征区分文件和目录:如果给定的 glob 以 / 结尾,那么你需要目录,如果 / 不存在,你需要文件。

include gmtt.mk

$(info $(call wildcard-rec,**.c)) # all C source files in the tree

$(info $(call wildcard-rec,**.c **.h)) # a C source and header files

$(info $(call wildcard-rec,drivers/**.c)) # only sources for the `drivers` tree

$(info $(call wildcard-rec,drivers/**/test/)) # all test subdirectories in the `drivers` tree

$(info $(call wildcard-rec,drivers/**/test/*.cfg)) # config files in all test subdirectories in the `drivers` tree