makefile 中 edit

makefile 說白了是一種方便編程的腳本,可用vim makefile 命令建立.隨便一種文本的方式建立他,然後放在你代碼的目錄下.

makefile帶來的好處就是——“自動化編譯”,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。make是一個命令工具,是一個解釋makefile中指令的命令工具,一般來說,大多數的IDE都有這個命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可見,makefile都成爲了一種在工程方面的編譯方法。

假設我們有下面這樣的一個程序,源代碼如下: 

/* main.c */ 
#include "mytool1.h" 
#include "mytool2.h" 

int main(int argc,char **argv) 

mytool1_print("hello"); 
mytool2_print("hello"); 


/* mytool1.h */ 
#ifndef _MYTOOL_1_H 
#define _MYTOOL_1_H 

void mytool1_print(char *print_str); 

#endif 

/* mytool1.c */ 
#include "mytool1.h" 
void mytool1_print(char *print_str) 

   printf("This is mytool1 print %s\n",print_str); 


/* mytool2.h */ 
#ifndef _MYTOOL_2_H 
#define _MYTOOL_2_H 

void mytool2_print(char *print_str); 

#endif 
   
/* mytool2.c */ 
#include "mytool2.h" 
void mytool2_print(char *print_str) 

   printf("This is mytool2 print %s\n",print_str); 



當然由於這個程序是很短的我們可以這樣來編譯 
gcc -c main.c 
gcc -c mytool1.c 
gcc -c mytool2.c 
gcc -o main main.o mytool1.o mytool2.o 
這樣的話我們也可以產生main程序,而且也不時很麻煩.但是如果我們考慮一下如果有一天我們修改了其中的一個文件(比如說mytool1.c)那麼我們難道還要重新輸入上面的命令?也許你會說,這個很容易解決啊,我寫一個SHELL腳本,讓她幫我去完成不就可以了.是的對於這個程序來說,是可以起到作用的.但是當我們把事情想的更復雜一點,如果我們的程序有幾百個源程序的時候,難道也要編譯器重新一個一個的去編譯? 
爲此,聰明的程序員們想出了一個很好的工具來做這件事情,這就是make.我們只要執行以下make,就可以把上面的問題解決掉.在我們執行make之前,我們要先編寫一個非常重要的文件.--Makefile.對於上面的那個程序來說,可能的一個Makefile的文件是: 
#   這是上面那個程序的Makefile文件

$ vim makefile

輸入:(以下括號爲提示:)


main:main.o mytool1.o mytool2.o (main是你最終程序的名字,後面是他的附屬關係,)
(Tab鍵)gcc -o main main.o mytool1.o mytool2.o (輸入之前一定要先按TAB鍵,鏈接!)
main.o:main.c mytool1.h mytool2.h (又一個附屬關係)
(Tab鍵)gcc -c main.c (編譯)
mytool1.o:mytool1.c mytool1.h 
(Tab鍵)gcc -c mytool1.c (編譯)
mytool2.o:mytool2.c mytool2.h 
(Tab鍵)gcc -c mytool2.c(編譯)

保存退出,然後執行make命令就OK啦!

以下是補充內容,可更深入應用:

三、make 是如何工作的
在默認的方式下,也就是我們只輸入make 命令。那麼,
1、make 會在當前目錄下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它會找文件中的第一個目標文件(target),在上面的例子中,他會找到“edit”這個文件,並把這個文件作爲最
終的目標文件。
3、如果edit 文件不存在,或是edit 所依賴的後面的 .o 文件的文件修改時間要比edit 這個文件新,那麼,他就會執行後面所定
義的命令來生成edit 這個文件。
4、如果edit 所依賴的.o 文件也存在,那麼make 會在當前文件中找目標爲.o 文件的依賴性,如果找到則再根據那一個規則生成.o
文件。(這有點像一個堆棧的過程)
5、當然,你的C 文件和H 文件是存在的啦,於是make 會生成.o 文件,然後再用 .o 文件生命make 的終極任務,也就是執
行文件edit 了。
這就是整個 make 的依賴性,make 會一層又一層地去找文件的依賴關係,直到最終編譯出第一個目標文件。在找尋的過程中,
如果出現錯誤,比如最後被依賴的文件找不到,那麼make 就會直接退出,並報錯,而對於所定義的命令的錯誤,或是編譯不
成功,make 根本不理。make 只管文件的依賴性,即,如果在我找了依賴關係之後,冒號後面的文件還是不在,那麼對不起,
我就不工作啦。
通過上述分析,我們知道,像clean 這種,沒有被第一個目標文件直接或間接關聯,那麼它後面所定義的命令將不會被自動執行,
不過,我們可以顯示要make 執行。即命令——“make clean”,以此來清除所有的目標文件,以便重編譯。
於是在我們編程中,如果這個工程已被編譯過了,當我們修改了其中一個源文件,比如file.c,那麼根據我們的依賴性,我們的
目標file.o 會被重編譯(也就是在這個依性關係後面所定義的命令),於是file.o 的文件也是最新的啦,於是file.o 的文件修改
時間要比edit 要新,所以edit 也會被重新鏈接了(詳見edit 目標文件後定義的命令)。
而如果我們改變了“command.h”,那麼,kdb.o 、command.o 和files.o 都會被重編譯,並且,edit 會被重鏈接。
四、makefile 中使用變量
在上面的例子中,先讓我們看看edit 的規則:
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
我們可以看到[.o]文件的字符串被重複了兩次,如果我們的工程需要加入一個新的[.o]文件,那麼我們需要在兩個地方加(應該
是三個地方,還有一個地方在clean 中)。當然,我們的makefile 並不複雜,所以在兩個地方加也不累,但如果makefile 變得
複雜,那麼我們就有可能會忘掉一個需要加入的地方,而導致編譯失敗。所以,爲了makefile 的易維護,在makefile 中我們可
以使用變量。makefile 的變量也就是一個字符串,理解成C 語言中的宏可能會更好。
比如,我們聲明一個變量,叫objects, OBJECTS, objs, OBJS, obj, 或是OBJ,反正不管什麼啦,只要能夠表示obj 文件就行了。
我們在makefile 一開始就這樣定義:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
於是,我們就可以很方便地在我們的makefile 中以“$(objects)”的方式來使用這個變量了,於是我們的改良版makefile 就變成
下面這個樣子:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
於是如果有新的 .o 文件加入,我們只需簡單地修改一下 objects 變量就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章