在 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
我正在为 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