本示例演示一個程序的生成過程,使用的程序文件為第4章中的文件。Makefile文件和程序文件在一個文件夾中。Makefile文件如下所示:
CC := gcc Files := $(wildcard ./*) INC = . all:$(TT) test_dlib:libtest_d.so main.o filelist: .PHONY : clean filelist %.o:%c clean: |
在本例中,定義了CC等變量,在變量引用和使用這些變量的時候,需要用$(CC)的形式。
在Makefile和源文件所在目錄中,在命令行執(zhí)行make命令:
$ make |
gcc -pipe -g -Wall -I. -c -o getarg.o getarg.c |
在執(zhí)行的過程中,默認(rèn)執(zhí)行all目標(biāo),由于all目標(biāo)依賴于變量$(TT),$(TT)實際上是test。$(TT)依賴于$(OBJS),$(OBJS)就是getarg.o writeinfo.o main.o。因此,需要產(chǎn)生這三個目標(biāo)文件。
上述make工作的處理過程是這樣的:首先尋找三個目標(biāo)文件(getarg.o,writeinfo.o和main.o)的生成規(guī)則。在所有的規(guī)則中,并沒有這三個目標(biāo)文件的生成規(guī)則,因此使用默認(rèn)的目標(biāo)%.o:%c中的規(guī)則生成這三個目標(biāo)文件。這個時候會使用gcc編譯生成這三個目標(biāo)文件。生成完三個目標(biāo)文件之后,將執(zhí)行test目標(biāo),進行目標(biāo)文件的連接。
事實上,上述執(zhí)行過程中只是直接執(zhí)行了all目標(biāo),在Makefile中還有l(wèi)ibtest_d.so、test_dlib和filelist幾個目標(biāo)沒有執(zhí)行,而這些目標(biāo)可以單獨執(zhí)行。
執(zhí)行單獨的目標(biāo)filelist:
$ make filelist |
<<<<<<< Files in this folder >>>>>> |
這條目標(biāo)執(zhí)行的命令是使用file命令查看本文件夾下所有的文件。其中,F(xiàn)iles := $(wildcard ./*)表示使用通配符尋找目錄下的所有文件。
執(zhí)行生成可執(zhí)行程序test_dlib的命令:
$ make test_dlib |
+++++++ Build Dynamic lib : libtest_d.so +++++++ |
test_dlib目標(biāo)是一個可執(zhí)行程序,它本身需要連接一個動態(tài)庫libtest_d.so,因此它依賴于目標(biāo)libtest_d.so和main.o目標(biāo),由于main.o已經(jīng)生成,這樣還需要生成libtest_d.so目標(biāo)。在libtest_d.so目標(biāo)中,依賴的文件getarg.o和writeinfo.o都已經(jīng)生成了,因此直接生成這個動態(tài)庫即可。libtest_d.so生成后,再生成test_dlib可執(zhí)行程序。
在以上的示例中的test和test_dlib都是可執(zhí)行的程序,它們的區(qū)別在于前者包含了三個目標(biāo)文件,可以直接執(zhí)行,后者只包括了main.o一個目標(biāo)文件,它的執(zhí)行必須依賴動態(tài)庫。
繼續(xù)使用clean清除目標(biāo):
$ make clean |
------- clean ------ |
$ make test_dlib |
在這次執(zhí)行的過程中,由于getarg.o,writeinfo.o和main.o三個目標(biāo)文件還沒有生成,因此在生成庫libtest_d.so之前,需要先編譯生成getarg.o和writeinfo.o兩個目標(biāo),它們使用的是默認(rèn)的規(guī)則。在libtest_d.so生成后,還需要生成main.o的過程,它也需要使用默認(rèn)的規(guī)則。
知識點:通常情況下,為了加速開發(fā),程序員自己編寫的程序在無特殊要求下都可以使用隱含規(guī)則,這樣還可以防止因為Makefile編寫錯誤而導(dǎo)致程序運行錯誤。