多文件及多目錄下MakeFile文件的編寫

Makefile 描述了整個工程中所有文件的編譯順序、編譯規則。而make工具則可以對我們的Makefile規則進行解釋執行。Makefile文件的規則包含了目標文件依賴文件之間的依賴關係 以及更新此規則 所需要的命令

目標文件:依賴文件
命令

其中,命令前是Tab不是空格,否則make會報錯。

首先,上一段Hello World的代碼:

/* test.c */
#include <stdio.h> 
int main(){  
    printf("hello world\n");
    return 0
}

通常情況下,可以使用GCC對這段代碼進行編譯鏈接:gcc test.c -o test,然後執行./test 即可預期輸出 hello world。 同時,我們也可以通過makefile實現工程的自動化編譯。

test:test.o                  #依賴關係 1 :目標文件 test,依賴文件是test.o
    cc test.o -o test        #命令1:     將編譯輸出的test.o文件鏈接成目標可執行文件test
test.o:test.c                #依賴關係 2 :目標文件 test.o,依賴文件是test.c
    cc -c test.c -o test.o   #命令2:     把源文件編譯成二進制目標代碼 test.o
clean:                       #規則3:     沒有任何依賴關係只有執行命令的目標被稱爲 僞目標
    rm  test.o test          #命令3:     清除編譯生成的所有文件

make命令的方式是:make -f makefile文件名 ,也可以直接執行 make,make工具會默認使用名稱爲makefile或Makefile的文件進行解釋執行。在上述makefile文件中,存在兩個依賴關係,make 會把 第一個規則的目標 當做 整個工程的最終目標,即 test ;同時,make 會比較每一條規則 目標文件 及其依賴文件的修改時間,決定 這條規則的命令是否執行,如本例中當我們修改了 test.c 文件時,make會首先執行命令2去生成test.o 文件,而最終目標文件test 也會因test.o 的修改時間改變而重新鏈接;

多文件的Makefile例子

實際開發過程中,一個項目會包含很多源代碼文件或庫文件。這時候,我們需要對多文件同時進行編譯鏈接,下面是一個多文件Makefile的例子,代碼的目錄結構如下:

├── client.c
├── server.c
├── config.h
└── makefile

具體代碼可見 http://blog.csdn.net/qq524425141/article/details/51340787,針對這個工程,編寫了 Makefile。

all:client server
    @echo make completed                 #編譯完成提示一下,使用"@"防止回顯
client:client.c config.h 
    gcc client.c -o client
server:server.c config.h
    gcc server.c -o server
clean:
    rm client server *.o

隨着工程包含編譯文件的增多,編寫Makefile文件變得越來越麻煩,這時候,我們就可以利用make的一些預定義變量和規則簡化makefile。如對於上面的makefile。可以稍作簡化。

all:client server
client:config.h              #client的依賴文件雖然沒有指出client.c,但是 make 會進行 自動推導
    gcc client.c -o $@       # 預定義變量,$@ 表示規則的目標,常見預定義變量見附錄
server:config.h         
    gcc server.c -o $@
clean:        
    rm client server  

繼續簡化,最終的Makefile可以簡寫如下:

all:client server
$(all):
    cc $^ -o $@              #$^ 表示所有依賴文件
clean:        
    -rm client server

其中,-rm 是因爲當我們 連續兩次 執行make clean後會報錯,使用-rm 可以忽略錯誤繼續執行。

多目錄下makefile編寫

同樣是上面的例子,目錄結構如下:

├── makefile
├── clientdir
│ ├── client.c
│ └── makefile
├── serverdir
│├── server.c
│└── makefile

我們對client和server程序的Makefile分別進行編譯,然後在上一級目錄編寫總的對這兩個項目同時進行編譯。這三個makefile分別如下:

#./clientdir/makefile
all:client
$(all):        
    gcc $<-o $@
clean:        
    -rm client
#./serverdir/makefile
all:server
server:        
    gcc  server.c -o $@
clean:        
    rm server
all clean:
        @for subdir in client server;\
        do\
                #echo $$subdir;\
                if test -d $$subdir;\
                then\
                        echo making $@ in $$subdir;\
                        (cd $$subdir && make $@) || exit 1;\
                fi;\
        done

執行make all 或者make即可在相應的目錄下生成目標程序,執行make clean可同時刪除目標。

make中常用的預定義變量

$* 不包含擴展名的目標文件名稱。
$+ 所有的依賴文件,以空格分開,並以出現的先後爲序,可能包含重複的依賴文件。
$< 第一個依賴文件的名稱。
$? 所有的依賴文件,以空格分開,這些依賴文件的修改日期比目標的創建日期晚。
$@ 目標的完整名稱。
$^ 所有的依賴文件,以空格分開,不包含重複的依賴文件。
$%	如果目標是歸檔成員,則該變量表示目標的歸檔成員名稱。例如,如果目標名稱爲(image.o),則 $@ 爲 ,而 $%image.o。
AR  歸檔維護程序的名稱,默認值爲 ar。
ARFLAGS 歸檔維護程序的選項。
AS  彙編程序的名稱,默認值爲 as。
ASFLAGS 彙編程序的選項。
CC   C 編譯器的名稱,默認值爲 cc。
CFLAGS   C 編譯器的選項。
CPP  C 預編譯器的名稱,默認值爲 $(CC) -E。
CPPFLAGS    C 預編譯的選項。
CXX  C++ 編譯器的名稱,默認值爲 g++。
CXXFLAGS    C++ 編譯器的選項。
FC   FORTRAN 編譯器的名稱,默認值爲 f77。
FFLAGS   FORTRAN 編譯器的選項。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章