如何在目录中漫步并查找具有特定扩展名的所有文件

时间:2012-01-28 17:40:49

标签: c++ makefile gnu-make

我需要编写一个预构建的makefile,它与主构建文件分开调用。这个make文件应该在调用它的目录中散步。另一个名为'sources.mk'的make文件中有一个目录列表,其中包含一个描述目录的变量:

SUBDIRS := \
. \
directory1 \
directory2 \

现在,我需要在这个列表中运行一个循环,在这个循环中我需要调用一个实用程序来处理所有带有'h'扩展名的文件。我写了这个:

include Default/sources.mk

find_files:
    for prefix in $(SUBDIRS); do \
        for file in *.h; do \
            C:/QtSDK/Desktop/Qt/4.7.4/mingw/bin/moc.exe $$prefix/$$file; \
        done \
    done

运行命令:make -f premake.mk

我没有描述错误,有很多错误,我正在尝试不同的makefile,但我是新手,并且这些尝试都失败了。请查看我的代码和/或建议其他方法。

2 个答案:

答案 0 :(得分:2)

您的问题可能只是一件简单的事情:您在当前目录中的file中寻找*.h,而不是在子目录中。试试这个:

for prefix in $(SUBDIRS); do \
    for file in $$prefix/*.h; do \
        C:/QtSDK/Desktop/Qt/4.7.4/mingw/bin/moc.exe $$file; \
    done \
done

话虽如此,更好的方法是使用make来处理所有文件(并决定是否所有文件都需要重新处理!),而不是使用规则中的显式循环。您将从头文件列表开始,如Eldar Abusalimov的回答所示:

moc_headers := $(wildcard $(SUBDIRS:%=%/*.h))

内部部分将SUBDIRS列表操作为directory1/*.hdirectory2/*.h等形式,然后wildcard函数展开所有*.h模式。

然后,从中生成输出文件列表:

moc_mocfiles := $(patsubst %.h, %_moc.cpp, $(moc_headers))

这会获取头文件directory1/header1.hdirectory1/header2.h等扩展列表,并将%.h模式替换为%_moc.cpp。 (请注意,因为这些名称都具有目录名称作为名称的一部分,所以您无法轻松使用更常见的moc_%.h名称模式,因为您将获得moc_directory1/header1.cpp,而不是所需的directory1/moc_header1.cpp {1}}。有办法解决这个问题,但更容易避免这个问题。)无论如何,这会为您提供输出文件列表:directory1/header1_moc.cppdirectory1/header2_moc.cpp等等

现在您已经有了一个输出文件列表,Make知道如何轻松地迭代这些文件。您只需将该列表声明为您正在制作的其他目标的先决条件,例如:

find_files: $(moc_mocfiles)

最后,您为从*_moc.cpp文件制作*.h文件制定了一般规则:

%_moc.cpp: %.h
     C:/QtSDK/Desktop/Qt/4.7.4/mingw/bin/moc.exe $< -o $@

在那里,第一行表示“这是你如何制作一个符合%_moc.cpp模式的文件,如果你有一个符合%.h模式的文件来制作它”。在第二行中,$<成为输入文件(%.h文件),$@成为输出文件。在这里,您明确告诉moc.exe使用-o选项吐出一个%_moc.cpp名称的文件,而不是默认情况下使用的任何文件。

所以,将所有这些放在一起,当你制作find_files目标时,make会意识到它需要在%_moc.cpp列表中创建所有moc_mocfiles个文件,并且每个文件都是它会看到它有一个适合的规则,它会看到规则适用,因为相应的%.h文件存在,它将应用规则。

这样做的另一个好处是,如果%_moc.cpp文件已经存在并且比%.h文件更新,表明它已经是最新的,那么下一步就不会重新生成它你跑的时间。它只会重新生成与您编辑过的%.h文件对应的文件。

(哦,还有最后一件事:当从这个答案中剪切并粘贴所有这些东西时,请确保你的标签在正确的位置!)

答案 1 :(得分:1)

只需使用GNU Make的原生wildcard function

HEADERS := $(wildcard $(SUBDIRS:%=%/*.h))