“C語(yǔ)言”讀書(shū)札記之[Linux下C語(yǔ)言編程環(huán)境]
介紹
一般程序都是由多個(gè)源文件編譯鏈接而成的,這些源文件的處理步驟通常由Makefile文件管理。
用途
make工具用來(lái)進(jìn)行協(xié)調(diào)的工具,可以根據(jù)程序模塊的修改情況重新編譯鏈接目標(biāo)代碼,以保證目標(biāo)代碼總是由它的最新模塊組成。
準(zhǔn)備:
要使用make,準(zhǔn)備Makefile的文件(也可以準(zhǔn)備其他文件如GNUMakefile或makefile,推薦使用Makefile),它描述了軟件包中各個(gè)文件之間的關(guān)系,提供了更新每個(gè)文件的命令。
方便使用:
當(dāng)一個(gè)適當(dāng)?shù)腗akefile存在時(shí),每次改變某些源文件,用簡(jiǎn)單的shell命令(make),將足以完成所有必需的重新編譯。
原理:
make 程序利用Makefile的數(shù)據(jù)和每個(gè)文件最新一次更改的時(shí)間來(lái)確定哪些文件需要更新;對(duì)每個(gè)需要更新的文件,make程序使用Makefile中定義的命令來(lái)更新它。
格式:
- #用“井”號(hào)表明注釋。
- target(要生成的文件): dependencies(被依賴(lài)的文件)
- #命令前面用的是“tab”而非空格。誤用空格是初學(xué)者容易犯的錯(cuò)誤!
- 命令1
- 命令2
- 命令3
- .
- .
- .
- 命令n
- #可以使用“\”表示續(xù)行。注意,“\”之后不能有空格!
target通常是我們要生成的文件的名字,擺放的順序不重要,但第一個(gè)target是默認(rèn)的target。當(dāng)make不帶參數(shù)時(shí),自動(dòng)執(zhí)行第一個(gè)target。target也可以是要求make完成的動(dòng)作,執(zhí)行這種target后并不能得到和target同名的文件,因此,也稱(chēng)為偽target(phony target)。
dependencies是生成target所需的文件名列表。依賴(lài)可以為空,常用的“clean”target就常常沒(méi)有依賴(lài),只有命令。
命令可以是任何一個(gè)shell能運(yùn)行的命令。
案例:
比如生成exe文件,它由2個(gè)目標(biāo)代碼某塊組成,分別為module1.o和module2.o
module1.h文件
- int module1 = 1;
module1.c文件
- #include "module1.h"
- void print1(){
- printf("var module1:%d\n", module1);
- }
module2.h文件
- int module2 = 2;
module2.c文件
- #include <stdio.h>
- #include "module2.h"
- void print2(){
- printf("var module2:%d\n", module2);
- }
- int main(){
- print1();
- print2();
- return 0;
- }
編譯
Makefile文件
- exe:module2.o module1.o
- gcc -g module1.o module2.o -o exe
- module2.o:module2.h module2.c
- gcc -g -c module2.c
- module1.o:module1.h module1.c
- gcc -g -c module1.c
- clean:
- rm -f exe *.o
截圖
#p#
規(guī)則
在編寫(xiě)完源程序文件后,從中生成需要的Makefile規(guī)則。
最基本的編寫(xiě)規(guī)則的方法是從最終的源程序文件開(kāi)始一個(gè)一個(gè)的查看源碼文件,把它們要生成的目標(biāo)文件做為目標(biāo),而C語(yǔ)言源碼文件和源碼文件包含的頭文件作為依賴(lài)文件生成規(guī)則。
目標(biāo)和條件之間的關(guān)系是:欲更新目標(biāo),必須首先更新它的所有條件;所有條件中只要有一個(gè)條件被更新了,目標(biāo)也必須隨之被更新。所謂“更新”就是執(zhí)行一遍規(guī)則中的命令列表,命令列表中的每條命令必須以一個(gè)Tab開(kāi)頭,注意不能是空格,Makefile的格式不像C語(yǔ)言的縮進(jìn)那么隨意,對(duì)于Makefile中的每個(gè)以Tab開(kāi)頭的命令,make會(huì)創(chuàng)建一個(gè)Shell進(jìn)程去執(zhí)行它。
Makefile中的變量
Makefile中變量就像一個(gè)環(huán)境變量。事實(shí)上環(huán)境變量在make中也被解釋成make的變量。
作用:
保存文件名列表。——可以方便地加入新的目標(biāo)文件而且不易出錯(cuò)。
保存編譯器參數(shù)。——在很多源代碼編譯時(shí),gcc需要很長(zhǎng)的參數(shù)選項(xiàng),在很多情況下,所有的編譯命令使用一組相同的選項(xiàng),如果把這組選項(xiàng)使用一個(gè)變量表示,那么可以把這個(gè)變量放在所有引用編譯器的地方。(當(dāng)要改變選項(xiàng)的時(shí)候,只需改變一次這個(gè)變量?jī)?nèi)容即可)
語(yǔ)法:
變量:“變量”指的是用一個(gè)字符串代替另一個(gè)字符串的功能。在makefile中可以使用“=”號(hào)來(lái)定義變量,使用“$(變量名)”來(lái)使用變量;還可以用“:=”追加變量的內(nèi)容。習(xí)慣上,變量名使用大寫(xiě)。
定義:
變量名=字符串
使用:
$(變量名)
追加:
變量名:=字符串
案例:進(jìn)化上面的Makefile
- OBJS=module1.o module2.o
- C=-c
- CC=gcc
- exe:$(OBJS)
- $(CC) -g $(OBJS) -o exe
- module2.o:module2.h module2.c
- $(CC) -g $(C) module2.c
- module1.o:module1.h module1.c
- $(CC) -g $(C) module1.c
- clean:
- rm -f exe *.o
偽目標(biāo)
首先要明確,并不是所有的目標(biāo)文件都對(duì)應(yīng)于磁盤(pán)文件,有的目標(biāo)文件的存在只是為了形成一條規(guī)則,從而使make完成特定的工作,并不生成新的目標(biāo)文件,這樣的目標(biāo)稱(chēng)為偽目標(biāo)。——如上面Makefile中的clean。常用的還有all。
放例子:
- all:exe1 exe2
- exe1:exe1.c exe1.h
- gcc exe1.c -o exe1
- exe2:exe2.c exe2.h
- gcc exe2.c -o exe2
- clean:
- rm -f exe*
其中的all和clean都為偽目標(biāo)。偽目標(biāo)文件是不存在的。注意上面例子中第一條規(guī)則下的命令行為空,make不會(huì)執(zhí)行任何動(dòng)作,只是檢查依賴(lài)文件的更新情況, 掃描剩下的幾條規(guī)則并執(zhí)行相應(yīng)的編譯命令生成可執(zhí)行文件。
條件語(yǔ)句
條件語(yǔ)句可以將一個(gè)變量與其他變量的值進(jìn)行比較,或?qū)⒁粋€(gè)變量與一個(gè)字符串常量相比較。——這樣就可以根據(jù)變量的值執(zhí)行或忽略Makefile文件中的一部分腳本。
注意:條件語(yǔ)句用于控制make時(shí)間看見(jiàn)的Makefile文件部分,而不能用于執(zhí)行時(shí)控制shell命令。
條件語(yǔ)句3條指令:ifeq, else 和endif
放樣例:
- ifeq($(VAR), 1)
- gcc -o exe1 module
- else
- gcc -o exe2 module
- endif
調(diào)試make
我們?cè)诤芏嗾Z(yǔ)言中都要用到調(diào)試,那么我們自然對(duì)make也要想到調(diào)試了。
make的調(diào)試很簡(jiǎn)單,只需通過(guò)-d選項(xiàng)可是make在執(zhí)行命令時(shí)打印調(diào)試信息。
這些信息包括:
1、make重新編譯時(shí)需要檢查的文件
2、哪些文件被比較以及比較的結(jié)果
3、需要重新生成的文件
4、make將要使用的隱含規(guī)則
5、make實(shí)際執(zhí)行的隱含規(guī)則和命令
放截圖樣例(一部分)
參考文獻(xiàn)
總結(jié)
想要熟練地掌握make工具,必需通過(guò)不斷的練習(xí)并參考其他Makefile的例子。
我會(huì)在后期的開(kāi)發(fā)學(xué)習(xí)中不斷完善這篇博文。
原文鏈接:http://www.cnblogs.com/baochuan/archive/2012/07/11/2583593.html