簡體   English   中英

Makefile依賴關系,應該是什么依賴關系?

[英]Makefile Dependencies, What Should Be a Dependency?

我有一個關於Makefile依賴項的概念性問題,這是因為我在網上看到有關此問題的不一致之處。

假設我有以下文件:

main.cpp         uses->     my_math.cpp and my_strings.cpp
my_math.cpp      uses->     my_math.h
my_strings.cpp   uses->     my_strings.h

如果我有一個makefile,則一般費用如下:

program: $(all_objs)
     g++ $(all_objs) -o program
main.o: ...
     .......
my_math.o: ...
     .......
my_strings.o: ...
     .......

我不知道每個依賴項應該包含什么內容。 就像math.o #includes my_math.h和my_strings.h一樣,這是否意味着如果我更改my_math.h,main.cpp需要重新編譯嗎? 但為什么? 它像圖書館一樣使用它,對不對? 它不需要重新編譯main.cpp還是對?

像這樣,main.o的結果應該是:

1) main.o: main.cpp
         gcc -c main.cpp

2) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
         gcc -c main.cpp

3) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
         gcc -c main.cpp my_strings.cpp my_math.cpp

我對依賴項以及鏈接的工作方式有些迷失。

任何幫助,將不勝感激! 謝謝!

依賴項是需要更改源代碼才能進行更改的所有內容。 這不僅包括您的#include -d標頭,還包括間接包含的系統標頭,甚至(原則上)還包括編譯器和構建鏈本身(在升級C ++編譯器時,應重新編譯所有軟件)。 如果您的某些C ++代碼是從某些源生成的(例如,通過GNU bison或Qt moc之類的工具或您自己的腳本生成),則源和生成工具都是依賴項。 另請參閱有關程序包管理器的信息

實際上, GCC編譯器能夠輸出大多數make依賴項,尤其是使用-M和相關的處理器選項 閱讀有關自動依賴項生成的信息 另請參見

(實際上,您通常不會在Makefile編寫對編譯器本身的某些顯式依賴關系;但是,在升級編譯器時,請不要忘記make clean

除非您的main.cpp包含my_strings.cpp (這不是常規的並且味道很差),否則您的make規則將不會從my_strings.cppmain.o進行依賴。 但是您的main.cpp可能是#include -ing(直接或間接) my_strings.h因此main.o應依賴於main.cpp還應依賴於my_strings.h

根據經驗,目標文件my_strings.o取決於源文件my_strings.cpp和所有直接或間接包含在其中的#include -d 頭文件 你的主要program執行依賴於它的所有目標文件和要鏈接到它的庫。 g++程序參數的順序非常重要。

它像圖書館一樣使用它,對不對?

根據顯示的內容,您沒有任何自己的 (但您可能使用標准的C ++庫,也許還使用其他一些系統庫)。 在Linux上,這些文件是lib*.a文件(靜態庫)或lib*.so文件(共享庫)。 庫是目標代碼(有時是其他資源)的有組織的集合。

我對依賴項以及鏈接的工作方式有些迷失。

了解源代碼文件, 目標文件 (它們包含重定位信息)和可執行文件 (在Linux上,目標文件和可執行文件以及共享庫使用ELF格式)之間的區別。 另請閱讀有關編譯器鏈接器g++程序可以同時運行)和構建自動化 (要使用make的角色)的作用。

閱讀程序庫HowTo以及有關翻譯單元鏈接器 (及名稱修改 )的更多信息,尤其是Levine的有關鏈接器和加載器的書。

參見 (約實例Makefile為C ++程序)。

順便說一句,在編譯C ++代碼時,應該使用g++ (不是gcc )。 有很大的區別(即使gcc 有時能夠編譯C ++或Fortran代碼,您也大多會使用gcc來編譯C代碼)。 並且(假設您專門使用GNU make)您的Makefile應該提到$(CXX) (不是g++ )。 您需要了解make的內置規則(運行一次make -p來獲取它們),然后最好利用它們(例如,使用$(COMPILE.cc)$(COMPILE.cpp)等)。 您當然應該將-Wall -Wextra (以獲取所有警告,甚至更多)和-g (以獲取調試信息)傳遞給g++ 實際上,您應該在Makefile設置CXXFLAGS變量。

花時間仔細閱讀GNU make文檔Invoking GCC

查看現有自由軟件項目的Makefile -s。 由於各種原因,一些項目正在使用諸如autoconfcmake類的工具生成Makefile -s。 但是大多數簡單的項目不需要這種通用性,因此您應該能夠為C ++項目編寫自己的Makefile 當然,可以從現有代碼中汲取靈感。

如果你有

main.cpp         uses->     my_math.cpp and my_strings.cpp
my_math.cpp      uses->     my_math.h
my_strings.cpp   uses->     my_strings.h

Make的目的是通過構建.o文件和鏈接.o文件,以兩種不同方式維護模塊之間的依賴性。

您可以將其描述為main.o是根的依賴關系樹

                         main.o 
                       /       \
                   my_math.o   my_strings.o

對於每個.o,還有關於源文件的依賴樹,例如

    main.o               my_math.o               my_strings.o
   /      \              /        \              /           \ 
main.cpp   main.h     my_math.cpp  my_math.h  my_strings.cpp my_strings.h

因此,在進行make構建時,它將建立一個依賴樹,其根目錄以main.o為基礎,然后嘗試構建main所需的所有.o文件。 當所有.o文件構建完畢后,它們將被鏈接。

通過遵循依賴關系樹,Make可以確保在更改其中一個依賴模塊時,將鏈接/構建main。

但是,如果您從包含的頭文件之一#define MAXSTRING 32使用了諸如說常量之類的內容,則您不再僅依賴於.o文件,而是依賴於頭文件的內容,因此需要確保main.o如果因為鏈接不夠而更改了標頭,則會構建此鏈接,因此您需要在依賴項中添加.h

                               main.o 
                            /     |     \
                   my_math.o my_strings.o my_strings.h

當然,有一些方法可以使報頭更健壯,從而避免這種依賴性,但這是另一個問題。

您的cpp文件在編譯方面不依賴於其他cpp文件。 簡單的cpp文件應僅依賴於h文件。

在您的問題中,您說main.cpp取決於my_math.cppmy_strings.cpp ,但我認為這是不正確的。 我猜你那里有#include ,這是你的依賴。

一般來說, cpp文件的依賴項都是#include d h文件。

通常, cpp文件之間沒有依賴關系。 您只需通過編譯即可生成o文件。 然后,最終的二進制文件取決於所有o文件。

暫無
暫無

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

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