簡體   English   中英

通過解析Makefile檢索使用的頭文件和源文件名

[英]Retrieve used header and source file names by parsing Makefile

我想從還包含未使用目標的Makefile中提取所有*.cc*.h文件名。 此處的示例Makefile: https : //gist.github.com/berceanu/7554a9c4371b807e425259c7e99b5de9

我試過運行make -Bnd並查看已修剪的文件,但我不知道這是否會丟失任何內容。

make -Bnd | grep "Pruning file" | sort | uniq

預期結果:在上述Makefile上make runmake run使用的所有*.h*.cc文件的列表。

我建議使用--dry-run --print-data-base而不是-Bnd來轉儲目標,目標依賴項,規則,變量等的完整數據庫。

您嘗試從Makefile提取此信息的方法可能是錯誤的方法。 make不知道實際使用了哪些頭文件。 make只知道它的頭文件你已經明確地告訴了make有關的依賴關系,這是不是很可靠。 Makefile的信息可能有兩種錯誤。 它可能包含未使用的目標(如您所注意到的)或未使用的頭文件。 它可能會錯過實際上包含但在Makefile未提及的頭文件。 更糟糕的是,如果頭文件的實際包含取決於宏,如#ifdef XYZ_FEATURE #include "additionalHeaderFile.h" #endif ,該怎么#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來獲取列表用於構建run的所有.cc.h文件。 您甚至可以在不更改Makefile情況下執行此操作: make clean; make CPPFLAGS:=-MMD && cat *.d | sed -e 's/\\\\//g' -e 's/:/ /g' -e 's/ \\+/\\n/g' | sort -u make clean; make CPPFLAGS:=-MMD && cat *.d | sed -e 's/\\\\//g' -e 's/:/ /g' -e 's/ \\+/\\n/g' | sort -u make clean; make CPPFLAGS:=-MMD && cat *.d | sed -e 's/\\\\//g' -e 's/:/ /g' -e 's/ \\+/\\n/g' | sort -u

同樣,您在要點中共享的Makefile也存在很多問題。

  • 按照慣例,默認目標應命名為all 1 2 3 那不需要是二進制文件的名稱,它只是一個.PHONY目標。
  • 具有目標文件列表的變量應命名為OBJSOBJECTS ,而不是OBJ OBJ這個名稱具有誤導性,因為它是單數形式。
  • 代替rm使用$(RM)表示-f ,因此在文件不存在的情況下也不會造成麻煩。 (作為一個副作用, Makefile將變得更加可移植,因為並非所有平台都使用rm刪除文件。)
  • clean不是文件,因此應該是.PHONY目標。
  • clean的配方應使用::而不是: ,以便將來在Makefile較大並拆分為多個文件時,每個文件都可以擁有自己的clean目標,而不會出現問題。
  • 不是特定於規則的變量應在定義時進行擴展,而不是在引用時進行擴展,因此應使用:=而不是=定義。
  • 代替C++使用已經定義的CXX
  • 不要將選項放到C++ / CXX ,而要使用LDFLAGS ,因為您正在鏈接。
  • 您應該具有與二進制文件具有相同基名的源文件。 然后,您可以使用內置規則進行鏈接。
  • Makefile中的顯式依賴關系Makefile維護。 每次添加,刪除或更改項目頭文件的#include語句時,都必須更新Makefile ,這很容易忘記,而且很痛苦,尤其是當#include語句位於頭文件中時。 即使進行了盡職調查,這也是無形的合並沖突。 相反,在有明確的相關性Makefile ,你應該使用CPPFLAGS+=-MMD在你開始Makefile和追加-include $(wildcard *.d)在你結束Makefile ,並添加*.d到文件列表刪除clean 然后,您可以從Makefile刪除所有依賴關系規則(鏈接規則除外)。
  • 命名二進制run不是一個好主意。 看到您的Makefile具有run目標的用戶可能希望它運行實際程序,而不是鏈接它。
  • 最好讓每個對象單獨一行。 當多個開發人員同時更改對象列表時,這可以大大減少項目中的合並沖突。

您的實際Makefile應該如下所示,將二進制文件從run重命名為program

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)

Makefile將與您的Makefile做“相同”的事情,但是幾乎不需要維護 不需要更新依賴項,因為它們是從C預處理器生成的依賴項文件中自動獲取的。 如果將-save-temps添加到CFLAGSCXXFLAGSCPPFLAGS任何一個, *.[adios]還將刪除創建的文件。

已知此類Makefile可用於GCC,clang,AOCC(AMD優化C編譯器)和armcc。 它可能也適用於許多其他編譯器和預處理器,尤其是當它們基於或嘗試與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 $@

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM