Posted on 2010-02-05 15:51
Prayer 閱讀(670)
評論(0) 編輯 收藏 引用 所屬分類:
Shell
Makefile中使用隱含規則來編譯程序
本示例演示一個程序的生成過程,使用的程序文件為第4章中的文件。Makefile文件和程序文件在一個文件夾中。Makefile文件如下所示:
CC := gcc HEAD := getarg.h SRC := getarg.c writeinfo.o main.c OBJS := getarg.o writeinfo.o main.o TT := test
Files := $(wildcard ./*)
INC = . CFLAGS = -pipe -g -Wall -I$(INC) LDFLAGS = -Wall -g
all:$(TT)
$(TT):$(OBJS) @echo "+++++++ Build Standalone Programe : $@ +++++++" $(CC) $(LDFLAGS) $(OBJS) -o $@
libtest_d.so:getarg.o writeinfo.o @echo "+++++++ Build Dynamic lib : $@ +++++++" $(CC) -shared $(LDFLAGS) getarg.o writeinfo.o -o $@
test_dlib:libtest_d.so main.o @echo "+++++++ Build Exe by Dynamic lib : $@ +++++++" $(CC) $(LDFLAGS) main.o -L. -ltest_d -o $@
filelist: @echo "<<<<<<< Files in this folder >>>>>>" @file $(Files)
.PHONY : clean filelist
%.o:%c $(CC) $(CFLAGS) -c $< -o $@
clean: @echo "------- clean ------" rm -f *.o rm -f $(TT) rm -f libtest_d.so rm -f test_dlib
|
在本例中,定義了CC等變量,在變量引用和使用這些變量的時候,需要用$(CC)的形式。
在Makefile和源文件所在目錄中,在命令行執行make命令:
執行的結果如下所示:
gcc -pipe -g -Wall -I. -c -o getarg.o getarg.c gcc -pipe -g -Wall -I. -c -o writeinfo.o writeinfo.c gcc -pipe -g -Wall -I. -c -o main.o main.c +++++++ Build Standalone Programe : test +++++++ gcc -Wall -g getarg.o writeinfo.o main.o -o test
|
在執行的過程中,默認執行all目標,由于all目標依賴于變量$(TT),$(TT)實際上是test。$(TT)依賴于$(OBJS),$(OBJS)就是getarg.o writeinfo.o main.o。因此,需要產生這三個目標文件。
上述make工作的處理過程是這樣的:首先尋找三個目標文件(getarg.o,writeinfo.o和main.o)的生成規則。在所有的規則中,并沒有這三個目標文件的生成規則,因此使用默認的目標%.o:%c中的規則生成這三個目標文件。這個時候會使用gcc編譯生成這三個目標文件。生成完三個目標文件之后,將執行test目標,進行目標文件的連接。
事實上,上述執行過程中只是直接執行了all目標,在Makefile中還有libtest_d.so、test_dlib和filelist幾個目標沒有執行,而這些目標可以單獨執行。
執行單獨的目標filelist:
顯示的結果如下:
<<<<<<< Files in this folder >>>>>> ./getarg.c: ASCII C program text ./getarg.h: ASCII text ./getarg.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped ./main.c: ASCII C program text ./main.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped ./Makefile: ASCII make commands text ./test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.4, dynamically linked (uses shared libs), for GNU/Linux 2.6.4, not stripped ./writeinfo.c: ASCII C program text ./writeinfo.h: ASCII text ./writeinfo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
|
這條目標執行的命令是使用file命令查看本文件夾下所有的文件。其中,Files := $(wildcard ./*)表示使用通配符尋找目錄下的所有文件。
執行生成可執行程序test_dlib的命令:
執行的結果如下所示:
+++++++ Build Dynamic lib : libtest_d.so +++++++ gcc -shared -Wall -g getarg.o writeinfo.o -o libtest_d.so +++++++ Build Exe by Dynamic lib : test_dlib +++++++ gcc -Wall -g main.o -L. -ltest_d -o test_dlib
|
test_dlib目標是一個可執行程序,它本身需要連接一個動態庫libtest_d.so,因此它依賴于目標libtest_d.so和main.o目標,由于main.o已經生成,這樣還需要生成libtest_d.so目標。在libtest_d.so目標中,依賴的文件getarg.o和writeinfo.o都已經生成了,因此直接生成這個動態庫即可。libtest_d.so生成后,再生成test_dlib可執行程序。
在以上的示例中的test和test_dlib都是可執行的程序,它們的區別在于前者包含了三個目標文件,可以直接執行,后者只包括了main.o一個目標文件,它的執行必須依賴動態庫。
繼續使用clean清除目標:
執行的結果如下所示:
------- clean ------ rm -f *.o rm -f test rm -f libtest_d.so rm -f test_dlib
|
在清除目標之后,生成test_dlib可執行程序:
$ make test_dlib gcc -pipe -g -Wall -I. -c -o getarg.o getarg.c gcc -pipe -g -Wall -I. -c -o writeinfo.o writeinfo.c +++++++ Build Dynamic lib : libtest_d.so +++++++ gcc -shared -Wall -g getarg.o writeinfo.o -o libtest_d.so gcc -pipe -g -Wall -I. -c -o main.o main.c +++++++ Build Exe by Dynamic lib : test_dlib +++++++ gcc -Wall -g main.o -L. -ltest_d -o test_dlib
|
在這次執行的過程中,由于getarg.o,writeinfo.o和main.o三個目標文件還沒有生成,因此在生成庫libtest_d.so之前,需要先編譯生成getarg.o和writeinfo.o兩個目標,它們使用的是默認的規則。在libtest_d.so生成后,還需要生成main.o的過程,它也需要使用默認的規則。
知識點:通常情況下,為了加速開發,程序員自己編寫的程序在無特殊要求下都可以使用隱含規則,這樣還可以防止因為Makefile編寫錯誤而導致程序運行錯誤。