gpt4 book ai didi

c++ - 通过解析Makefile检索使用的头文件和源文件名

转载 作者:太空宇宙 更新时间:2023-11-04 11:56:50 26 4
gpt4 key购买 nike

我想从包含未使用目标的Makefile中提取所有*.cc*.h文件名。这里是Makefile示例:https://gist.github.com/berceanu/7554a9c4371b807e425259c7e99b5de9
我试过运行make -Bnd并查看修剪过的文件,但我不知道这是否遗漏了什么。
make -Bnd | grep "Pruning file" | sort | uniq
预期结果:上述生成文件上*.h使用的所有*.ccmake run文件的列表。

最佳答案

您试图从Makefile中提取此信息的方法可能是错误的。make不知道实际使用了哪些头文件。make只知道您在依赖项中明确告诉了make哪些头文件,这不是很可靠。Makefile中的信息有两种可能是错误的。它可以包含未使用的目标(如您所注意到的)或未使用的头文件。它可能会丢失实际包含但未在Makefile中提及的头文件。更糟糕的是,如果头文件的实际包含依赖于宏,比如#ifdef XYZ_FEATURE #include "additionalHeaderFile.h" #endif,该怎么办。
至少有三种方法可以生成所需的列表,即编译过程中实际使用的.cc.h文件列表:
(盲目信任Makefilemake -n --print-data-base
(遵循构建的真实文件,但也有点难以解析)strace -f make
(依赖于GCC、clang、armcc和其他编译器中的一个特性来生成Makefile,非常可靠)将CPPFLAGS:=-MMD添加到Makefile,运行make clean,然后make,然后使用cat *.d获取用于生成.cc的所有.hrun文件的列表。你甚至可以在不改变Makefilemake clean; make CPPFLAGS:=-MMD && cat *.d | sed -e 's/\\//g' -e 's/:/ /g' -e 's/ \+/\n/g' | sort -u的情况下做到这一点。
另外,您在要点中共享的Makefile也有很多问题。
按照惯例,默认目标应命名为all123 。这不需要是二进制文件的名称,它只是一个 .PHONY目标。
带有对象文件列表的变量应命名为 OBJSOBJECTS,而不是 OBJ。这个名字有误导性,因为它是单数的。
而不是 OBJ使用 rm,这意味着 $(RM),因此在文件不存在的情况下不会有麻烦。(作为副作用, -f将变得更加便携,因为并非所有平台都使用 Makefile来删除文件。)
rm不是文件,因此应该是 clean目标。
.PHONY应该使用 clean而不是 ::作为其配方,以便将来当 :更大并拆分为多个文件时,每个文件都可以有自己的 Makefile目标而不会出现问题。
非规则特定的变量应在定义时展开,而不是在引用时展开,因此应使用 clean而不是 :=来定义。
使用已定义的 =而不是 C++
使用 CXX,而不是将选项放入 C++/ CXX,因为您正在链接。
应该有一个与二进制文件具有相同基名的源文件。然后可以使用内置规则进行链接。
LDFLAGS中的显式依赖关系是维护的一个难题。每次添加、删除或更改项目头文件的 Makefile语句时, #include都必须更新,这很容易忘记,而且这是一种痛苦,尤其是当 Makefile语句位于头文件中时。即使尽职尽责,这也是一场看不见的合并冲突。您应该在 #include开头使用 Makefile,在 CPPFLAGS+=-MMD结尾附加 Makefile,并将 -include $(wildcard *.d)添加到要在 Makefile中删除的文件列表中,而不是在 *.d中具有显式依赖关系。然后可以从 clean中删除所有依赖关系规则(除了链接的规则)。
命名二进制 Makefile不是一个好主意。看到您的 run有一个 Makefile目标的用户会希望它运行实际的程序,而不是链接它。
最好把每一个对象单独放在一行。当多个开发人员同时更改对象列表时,这显著减少了项目中的合并冲突。
实际的 run应该是这样的,二进制文件从 Makefile重命名为 run

LDFLAGS:=-Wno-deprecated -lm
CPPFLAGS+=-MMD
BINARY:=program

OBJECTS:= \
$(BINARY).o \
binomh.o \
# More objects here

.PHONY: all
all: $(BINARY)

$(BINARY): $(OBJECTS)

.PHONY: clean
clean::
$(RM) \
$(BINARY) \
*.[adios] \

-include $(wildcard *.d)

这个 program将做与您的 Makefile相同的事情,但它几乎是免维护的。不需要更新依赖项,因为它们是从C预处理器生成的依赖项文件中自动获取的。 Makefile还将删除在您将 *.[adios]添加到任何 -save-tempsCFLAGSCXXFLAGS时创建的文件。
众所周知,这种类型的 CPPFLAGS适用于GCC、clang、AOCC(AMD optimizec Compiler)和armcc。它可能也适用于其他一些编译器和预处理器,特别是当它们基于GCC或clang/LLVM或试图与GCC或clang/LLVM兼容时。
顺便说一句,如果你有兴趣知道这对你有用的话,除了经验之外,还有很高的信心:我已经把你的 Makefile添加到它上面,以便复制你的源代码结构。头文件将只是空文件。C++源文件将是从 Makefile中的依赖项获取的 #include语句列表。
%.cc:
grep '^$*\.o.*:' $(MAKEFILE_LIST) | sed -e 's/.*://' -e 's/.*$*\.cc//' -e 's/ \([^ ]\+\)/#include "\1"\n/g' >$@

%.h:
touch $@

关于c++ - 通过解析Makefile检索使用的头文件和源文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54029987/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com