在Unix系統上編譯tarball時,通常需要三步驟:
Makefile的概念非常像是批次檔,但是它有更強大的能力。
make會查閱每一步驟所需要的檔案,如果沒有便執行指令以產生該檔案,如果已經是最新狀態,就直接跳到下個步驟。撰寫者只要了解原始碼的編譯步驟,就可以依序寫好指令,如此只要有Makefile,不管是誰只要鍵入make就可以成功編譯出檔案。
./configure make make install這中間的make指令便是利用makefile來處理編譯步驟。
Makefile的概念非常像是批次檔,但是它有更強大的能力。
make會查閱每一步驟所需要的檔案,如果沒有便執行指令以產生該檔案,如果已經是最新狀態,就直接跳到下個步驟。撰寫者只要了解原始碼的編譯步驟,就可以依序寫好指令,如此只要有Makefile,不管是誰只要鍵入make就可以成功編譯出檔案。
以最簡單的單一檔案來說,編譯指令應該如下:
這樣會把helloworld.c編譯為helloworld這個執行檔。
而若要寫為makefile,可以這麼寫:
上面的意義為,要完成all這個目標,需要helloworld這個檔案,如果找不到它,就執行
注意,all是個關鍵字,良好的makefile都要有一個all,因為這是預設執行目標。
且一定要用tab縮排,否則它不會認目標底下的指令。換行符號也請用Unix的換行符。
gcc helloworld.c -o helloworld
這樣會把helloworld.c編譯為helloworld這個執行檔。
而若要寫為makefile,可以這麼寫:
all: helloworld gcc helloworld.c -o helloworld檔名存為Makefile或是makefile都可以[?],這就是最簡單的makefile。
上面的意義為,要完成all這個目標,需要helloworld這個檔案,如果找不到它,就執行
gcc helloworld.c -o helloworld
這個指令。注意,all是個關鍵字,良好的makefile都要有一個all,因為這是預設執行目標。
且一定要用tab縮排,否則它不會認目標底下的指令。換行符號也請用Unix的換行符。
若是要編譯多個檔案呢?比方說現在有三個檔案:application.c, interface.h, implementation.c,application.c引用了interface.h的函式,而implementation.c則是interface.h的實作。
先來看一下平常編譯該怎麼編:
所以來整理一下:result檔需要implementation.o和application.o這兩個檔案,而這兩個檔案分別需要implementation.c和application.c,如此一來就會變成:
你也可以選擇只執行其中一個目標,像是
先來看一下平常編譯該怎麼編:
gcc -c application.c
gcc -c implementation.c
gcc implementation.o application.o -o result
這樣編譯出來的result就是可執行檔。所以來整理一下:result檔需要implementation.o和application.o這兩個檔案,而這兩個檔案分別需要implementation.c和application.c,如此一來就會變成:
all: result
result: implementation.o application.o
gcc implementation.o application.o -o result
implementation.o: implementation.c
gcc -c implementation.c
application.o: application.c
gcc -c application.c
意即:欲完成all需要先完成result目標,欲完成result需要先完成implementation.o和application.o這兩個目標,而要達成implementation.o和application.o則分別需要implementation.c和application.c這兩個檔案。你也可以選擇只執行其中一個目標,像是
make application.o
就只會產生application.o檔。
總而言之,makefile的基本型式是:
而且目標也不一定要有前置目標,如果執行的目標沒有前置目標的話,代表目標底下的命令一定會執行。
target: required file or target
commands to complete this target
底下不限定有多少行指令,只要有用tab縮排即可。而且目標也不一定要有前置目標,如果執行的目標沒有前置目標的話,代表目標底下的命令一定會執行。
如果你覺得太長,想省略一點,也可以用萬用符號[?]:
all: result
result: *.o
gcc *.o -o result
*.o: *.c
gcc -c *.c
這個版本可以跟上面的版本達到相同的效果,不過當然有點危險就是了。
當然不只能用來編譯,也許你會希望能夠有清掉過程檔的功能:
all: result clean
result: *.o
gcc *.o -o result
*.o: *.c
gcc -c *.c
clean:
rm -f *.o
這樣在下完make
之後會立刻把所有的.o檔清除,或是也可以用make clean
除掉。
也許你在編譯完成之後都會執行一次該程式來測試,那麼也可以這麼寫:
當找不到input.txt時,make會自動停止並回報錯誤,因為文件中找不到如何生成input.txt的資訊。
all: result clean
result: *.o
gcc *.o -o result
*.o: *.c
gcc -c *.c
clean:
rm -f *.o
test: result input.txt
./result <input.txt
如此只要輸入make test
就會自動執行測試。當找不到input.txt時,make會自動停止並回報錯誤,因為文件中找不到如何生成input.txt的資訊。
儘管make沒有明定什麼目標該做什麼事,但是在約定成俗的目標上,請按照慣例:
其他經常用的目標也請不要逆天。
make all
要用來生成所有程式。make install
要用來安裝程式。make clean
要用來清除暫時檔。其他經常用的目標也請不要逆天。
當然這只是最最簡單的makefile,其他如關鍵字聲明之類的,可以去翻make的文件;而automake這套程式可以幫助你生成大型專案的makefile,不過我笨,不會用(汗)。
沒有留言:
張貼留言