做網(wǎng)站 (公司)如何做好平臺推廣
文章目錄
- 1. MakeFile 的作用
- 2. 背景知識說明
- 2.1 程序的編譯與鏈接
- 2.2 常見代碼的文檔結(jié)構(gòu)
- 3. MakeFile 的內(nèi)容
- 4. Makefile的基本語法
- 5. 變量定義
- 5.1 一般變量賦值語法
- 5.2 自動化變量
- 6. 通配符
參考:
Makefile教程:Makefile文件編寫1天入門
Makefile由淺入深–教程、干貨
Makefile詳解(超級好) 陳皓
1. MakeFile 的作用
Makefile 文件描述了 Linux 系統(tǒng)下 C/C++ 工程的編譯規(guī)則,它用來自動化編譯 C/C++ 項目。一旦寫編寫好 Makefile 文件,只需要一個 make 命令,整個工程就開始自動編譯,不再需要手動執(zhí)行 GCC 命令。
2. 背景知識說明
2.1 程序的編譯與鏈接
編譯(compile)是將源文件編譯成中間目標文件的過程。對于C、C++,在Windows下是.obj
文件,在UNIX下是.o
文件。
鏈接(link)是將目標文件合成執(zhí)行文件。
正確的編譯要求語法正確,函數(shù)與變量的聲明正確。一般來說每個源文件(頭文件+cpp文件)都對應于一個中間目標文件。 鏈接是鏈接函數(shù)和全局變量,可以使用中間目標文件來鏈接。鏈接時需要支出中間目標文件名稱。
在源文件較多的情況下(此時中間目標文件也多),可以給中間目標文件打包,這種包文件就“庫文件”(Library FIle),也就是.lib
文件或.a
文件。
2.2 常見代碼的文檔結(jié)構(gòu)
src
:源碼incl
:頭文件bin
:執(zhí)行碼lib
:靜態(tài)/動態(tài)庫
3. MakeFile 的內(nèi)容
Makefile 文件中主要包含了五項內(nèi)容:
- 變量定義:在Makefile 中我們要定義一系列的變量,變量一般都是字符串,這個有點像C語言中的宏,當Makefile被執(zhí)行時,其中的變量都會被擴展到相應的引用位置上。
- 顯式規(guī)則:顯式規(guī)則說明了,如何生成一個或多的的目標文件。這是由Makefile 的明顯指出,要生成的文件,文件的依賴文件,生成的命令。 .
- 隱晦規(guī)則:make有自動推導的功能,隱晦規(guī)則指導我們?nèi)绾魏喡缘貢鴮慚akefile的同時又讓
make
命令能夠順利執(zhí)行。 - 文件指示:其包括了三個部分,一個是在一個 Makefile 中引用另一個 Makefile,就像C語言中的 include 一樣;另一個是指根據(jù)某些情況指定 Makefile 中的有效部分,就像C語言中的預編譯 #if 一樣;還有就是定義一個多行的命令。
- 注釋:Makefile 中只有行注釋,和 UNIX 的 Shell 腳本一樣,其注釋是用“#”字符。
4. Makefile的基本語法
一般的 Makefile 語句的形式如下:
targets:prerequisitescommand
或
targets:prerequisites;commandcommand
其中:
targets
是目標,可以是中間文件,也可以是可執(zhí)行文件或標簽;prerequisites
是依賴的文件,要生成 targets 需要的文件或者是目標??梢允嵌鄠€,也可以是沒有;command
是make 需要執(zhí)行的命令(任意的 shell 命令)。可以有多條命令,每一條命令占一行。
注意:目標和依賴文件之間要使用冒號分隔開,命令的開始要使用Tab鍵。
以此規(guī)則可以寫出如下代碼:
test:test.cgcc -o test test.c
上述代碼實現(xiàn)的功能就是編譯 test.c 文件,通過這個實例可以詳細的說明 Makefile 的具體的使用。其中 test 是的目標文件,也是我們的最終生成的可執(zhí)行文件。依賴文件就是 test.c 源文件,重建目標文件需要執(zhí)行的操作是gcc -o test test.c
。
5. 變量定義
5.1 一般變量賦值語法
MakeFile中變量定義的基本語法:
valname = valuelist
- MakeFile中的變量沒有數(shù)據(jù)類型(或者理解為是字符數(shù)組?)。
- 值列表可以是零項,也可以是一項或者多項。
調(diào)用變量的格式:$(valname)
或${valname}
,如
OBJ=main.o test.o test1.o test2.o
test:$(OBJ)gcc -o test $(OBJ)
變量的賦值
Makefile 有四種基本賦值方式:
- 簡單賦值 ( := ) 編程語言中常規(guī)理解的賦值方式,只對當前語句的變量有效。
- 遞歸賦值 ( = ) 賦值語句可能影響多個變量,所有目標變量相關的其他變量都受影響(如使用該變量賦值的變量)。
- 條件賦值 ( ?= ) 如果變量未定義,則使用符號中的值定義變量。如果該變量已經(jīng)賦值,則該賦值語句無效。
- 追加賦值 ( += ) 原變量用空格隔開的方式追加一個新值。
案例:
簡單賦值
x:=foo
y:=$(x)b
x:=new
test:@echo "y=>$(y)"@echo "x=>$(x)"
在 shell 命令行執(zhí)行make test
我們會看到:
y=>foob
x=>new
遞歸賦值
x=foo
y=$(x)b
x=new
test:@echo "y=>$(y)"@echo "x=>$(x)"
在 shell 命令行執(zhí)行make test
我們會看到:
y=>newb
x=>new
條件賦值
x:=foo
y:=$(x)b
x?=new
test:@echo "y=>$(y)"@echo "x=>$(x)"
在 shell 命令行執(zhí)行make test
我們會看到:
y=>foob
x=>foo
追加賦值
x:=foo
y:=$(x)b
x+=$(y)
test:@echo "y=>$(y)"@echo "x=>$(x)"
在 shell 命令行執(zhí)行make test
我們會看到:
y=>foob
x=>foo foob
5.2 自動化變量
自動化變量是Makefile 自動產(chǎn)生的變量。
自動化變量 | 說明 |
---|---|
$@ | 表示規(guī)則的目標文件名。如果目標是一個文檔文件(Linux 中,一般成 .a 文件為文檔文件,也成為靜態(tài)的庫文件),那么它代表這個文檔的文件名。在多目標模式規(guī)則中,它代表的是觸發(fā)規(guī)則被執(zhí)行的文件名。 |
$% | 當目標文件是一個靜態(tài)庫文件時,代表靜態(tài)庫的一個成員名。 |
$< | 規(guī)則的第一個依賴的文件名。如果是一個目標文件使用隱含的規(guī)則來重建,則它代表由隱含規(guī)則加入的第一個依賴文件。 |
$? | 所有比目標文件更新的依賴文件列表,空格分隔。如果目標文件時靜態(tài)庫文件,代表的是庫文件(.o 文件)。 |
$^ | 代表的是所有依賴文件列表,使用空格分隔。如果目標是靜態(tài)庫文件,它所代表的只能是所有的庫成員(.o 文件)名。一個文件可重復的出現(xiàn)在目標的依賴中,變量$^ 只記錄它的第一次引用的情況。就是說變量“$^”會去掉重復的依賴文件。 |
$+ | 類似$^ ,但是它保留了依賴文件中重復出現(xiàn)的文件。主要用在程序鏈接時庫的交叉引用場合。 |
$* | 在模式規(guī)則和靜態(tài)模式規(guī)則中,代表“莖”?!扒o”是目標模式中“%”所代表的部分(當文件名中存在目錄時,“莖”也包含目錄部分)。 |
6. 通配符
通配符 | 使用說明 |
---|---|
* | 匹配0個或者是任意個字符 |
? | 匹配任意一個字符 |
[] | 我們可以指定匹配的字符放在 “[]” 中 |
% | 匹配任意字符 |
通配符可以使用在規(guī)則的命令和規(guī)則中,但不能直接用于變量聲明。如:
# 使用在命令中
.PHONY::clean
clean:rm -rf *.o test
# 使用在規(guī)則中
test:*.cgcc -o $@ $^
```我們可以在 Makefile 中這樣寫
如果我們就是相要通過引用變量的話,我們要使用一個函數(shù) `wildcard`:
```shell
OBJ=$(wildcard *.c)
test:$(OBJ)gcc -o $@ $^