- make/makefile介紹
1.1 基本認識
make是一個命令,makefile是一個文件(Makefile和makefile是相同的,字母大小寫不影響),這是我們首先需要了解的。
1.2 依賴關系、依賴方法
為什么需要這個自動化構建工具呢?當我們創建一個文件并在其中寫入內容后,需要使用gcc或g++工具進行編譯。如果文件被修改后,我們需要重新編譯,這時又得輸入命令gcc -o 目標文件 源文件。每一次修改后輸入編譯命令都很麻煩,這時我們可以使用自動化構建工具,通過依賴關系和依賴方法來解決這個問題。
1.3 具體操作步驟
首先,創建一個test.c文件,并使用vim在其中寫入內容,可以通過不同模式之間的切換來實現。然后,創建一個makefile文件,里面包含依賴關系和依賴方法。
在makefile中,”test:test.c”表示依賴關系,意思是test文件是test.c文件編譯后的結果。第二行是依賴方法,即編譯的命令。
clean命令用于清理編譯生成的文件,使用的是”rm -f test”。
創建makefile文件和寫入test.c文件后,直接使用make命令。make命令會執行makefile中的第一個命令,即編譯test.c文件。這樣,我們就不需要重復輸入編譯命令。但要注意,第一次使用make后,如果再次使用,系統會提示”test up to date”,表示test文件(編譯后的文件)已保存,除非對test.c內容進行修改,否則無法重新編譯。
輸入”make clean”命令,可以清除編譯生成的文件。
1.4 進一步理解源文件到可執行文件
我們可以將這個過程寫得更復雜一些,顯示中間文件的生成過程,然后重新編譯,分析依賴關系和依賴方法。
在這個例子中,test文件依賴于test.o文件,test.o依賴于test.s文件,test.s依賴于test.i文件,test.i依賴于test.c文件。這個過程類似于遞歸過程(實際操作中可以使用簡便寫法)。
這個例子是為了說明多層依賴關系在執行時的順序問題。使用make命令時,執行順序與makefile中寫入的順序相反,類似于遞歸的歸過程。由于依賴關系,后出現的指令會先被執行,因為最先需要的是test.i文件,它直接由test.c文件生成,按照這個順序才能實現編譯過程。
實際上,我們輸入的是4組指令,每組都有依賴關系和依賴方法。我們可以隨意更換這4組指令的順序,輸出結果不變,可以正常運行。因此,make會自動推導makefile中的依賴關系,與順序無關。但如果缺少任意一個中間環節,過程將無法正常運行,因為它們之間是相互依賴的。
1.5 默認設置
make會自頂向下訪問命令。我們在makefile中添加新的內容,即文件的清理。什么是默認設置呢?就是在執行make命令時,會默認執行文件編譯的中間過程。要清理文件,需要使用”make clean”命令。這是因為在默認的make命令作用下,會先執行上面的文件指令。如果我們將清理指令放在gcc命令的前面,就會優先執行清理命令。
但我們一般不會將文件清理放在前面,因為我們還需要對相關文件進行操作,刪除清理后就無法操作了。
1.6 make二次使用的解釋
第一次編譯后使用make會執行相關操作,但第二次或更多次使用make就無法有效發揮作用,這是為了提高編譯效率。
如何做到:源文件編譯成可執行文件時,如果源文件最近修改時間早于可執行文件,我們對源文件修改后(未編譯),新文件比可執行程序更新,這時可以直接使用make命令(這時會重新編譯)。
這也是為什么文件編譯一次后只能make一次,但修改后就可以再次使用make命令的原因。
1.7 兩個文件的時間問題
我們上面介紹了源文件和可執行文件的時間早晚問題,以確定make命令能否有效使用。在Linux中,我們可以使用stat命令查看相關時間。
“stat test.c”顯示源文件的相關時間,”stat test”顯示編譯后的可執行文件的相關時間,stat命令用于查看時間,后面可以跟文件名。
顯示的內容相同,只是具體數值不同:
下面顯示了文件的相關信息,access是訪問文件的最新時間(訪問范圍較廣,使用cat查看文件內容、修改文件內容、打開文件等都算訪問),modify是修改時間,change相當于改變,兩個很相似,有什么區別呢?簡稱ACM。
之前介紹權限時說過,文件=文件內容+文件屬性,modify相當于改變文件內容,只對文件屬性進行修改,我們稱之為change。因此,對文件操作時,可能修改文件內容和屬性,內容就是modify,屬性就是change。
但這三個時間不是割裂的,改變文件內容時,modify時間肯定變,文件內容改變會引起文件大小改變,change時間也會改變,要修改內容肯定要打開文件,access時間也會改變,因此這三個時間不是沒有聯系。
1.8 總是被執行
我們上面介紹的時間,實際上是判斷源文件和目標文件的生成時間,以決定make是否會被執行。如果我們希望make命令輸入后一定被執行,可以在第一行前面添加”.PHONY:文件名字”。
上面的就是makefile中應該輸入的內容,使用make后就會發現它一定會被執行。但我們一般不會這樣做,可以將總是被執行的設置放在clean那一行,這樣我們的清除操作就可以總是被執行(默認實際上也可以被多次執行),但并不一定只有文件清理的其他指令,這不是多此一舉,書寫格式如下所示:
1.9 特殊符號介紹
我們在使用gcc進行編譯時,@可以表示依賴關系前面的文件,^可以表示依賴關系后面的文件,我們可以使用這些符號代替涉及到的兩個文件。
但實際上在查看文件內容時,這些特殊符號會以文件名的形式回顯出來。
我們在命令前面添加一個@符號,就可以讓make后的結果不會顯示在屏幕上,這是隱藏功能。