當我們的工程越來越大的以后,每次都使用命令編譯顯得非常的麻煩.所以我們需要一個自動化編譯的工具來幫助我們編譯.在我們使用源碼安裝軟件的時候都會有make,make install等操作,這個就是使用Makefile來進行自動化編譯的工作的.
Makefile也是一個腳本文件和shell腳本非常的相似,但是也有很多的地方不一樣.
程序編譯通常會有一下幾個步驟,先是預編譯,然后將C語言代碼編譯成匯編,然后在將匯編編譯成二進制文件.o文件,然后將所有的.o文件連接起來就得到了可執行文件.
在編寫Makefile時,我們先將所有的c語言代碼編譯成二進制文件,然后將所有二進制文件鏈接起來.
和shell類似的,里面有變量,有命令,有循環,判斷等語句,所有的命令都需要另起一行,而且開始必須是tab鍵(所有開頭是tab鍵的行都會被認為是命令,哪怕不能執行),變量等必須頂行不能有空格等.
簡單的Makefile格式(不涉及循環,選擇等語句):
TARGET... : PREREQUISITES...
COMMAND
a:main.o
gcc -o main.o
main.o:main.c
gcc -c main.c
這樣就是一個最簡單的Makefile
當然我們如果是文件多的話這樣寫就非常的麻煩,我們就可以使用 變量名 += .....來進行編輯,使用時直接$(變量名)來使用.(和shell一樣)
我們也常常會使用make clean的命令等,這個叫做偽目標,直接
clean:
rm *.o
install:
cp .. /bin
Makefile文件也可以應用其他的Makefile文件
include 文件名
在我們寫了.o文件名以后,當.o和.c文件是同名時,我們也可以不用.c文件,make會自動查找同名的文件,例如%.o:%.c.
以下是一些自動化變量:
$@
表示規則的目標文件名。如果目標是一個文檔文件(Linux中,一般稱.a文件為文檔文件,也稱為靜態庫文件) ,那么它代表這個文檔的文件名。在多目標模式規則中,它代表的是哪個觸發規則被執行的目標文件名。
$%
當規則的目標文件是一個靜態庫文件時,代表靜態庫的一個成員名。例如,規則的目標是 “foo.a(bar.o)” , 那么, “$%” 的值就為 “bar.o” , “$@” 的值為“foo.a” 。
如果目標不是靜態庫文件,其值為空。
$<
規則的第一個依賴文件名。 如果是一個目標文件使用隱含規則來重建, 則它代表由隱含規則加入的第一個依賴文件。
$?
所有比目標文件更新的依賴文件列表,空格分割。如果目標是靜態庫文件名,代表的是庫成員(.o文件) 。
$^
規則的所有依賴文件列表,使用空格分隔。如果目標是靜態庫文件,它所代表的只能是所有庫成員(.o文件)名。一個文件可重復的出現在目標的依賴中,變量“$^”只記錄它的一次引用情況。就是說變量“$^”會去掉重復的依賴文件。
$+
類似“$^” ,但是它保留了依賴文件中重復出現的文件。主要用在程序鏈接時庫的交叉引用場合。
$*
在模式規則和靜態模式規則中,代表“莖” 。 “莖”是目標模式中“%”所代表的部分 (當文件名中存在目錄時, “莖” 也包含目錄 (斜杠之前) ) 。例如:文件“dir/a.foo.b” ,當目標的模式為“a.%.b”時,“$*”的值為“dir/a.foo” 。 “莖”對於構造相關文件名非常有用
以下是一般的簡單的Makefile寫法:
COBJS += main.o
#CFLAGS += -O2 -Wall -DDEBUG
CFLAGS += -I./
LDFLAGS += -lmxml -lpthread
CROSS_COMPILE ?=
CC = $(CROSS_COMPILE)gcc
TARGET = tag
all:$(TARGET)
$(TARGET):$(COBJS)
$(CC) -o $@ $^ $(LDFLAGS)
%.o:%.c
$(CC) $(CFLAGS) -c -o $@ $^ $(LDFLAGS)
.PHONY:clean
clean:
rm -f $(COBJS)
