?? linux聯盟 善用gnu make做開發].htm
字號:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>LINUX聯盟-XXlinux.com[善用GNU Make做開發]</title>
<style type="text/css">
<!--
body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}
-->
</style>
<link rel="stylesheet" type="text/css" href="../css/css.css">
<style type="text/css">
<!--
.style1 {font-weight: bold}
.style2 {color: #FF0000}
-->
</style>
</head>
<body>
<iframe id="baiduasframe" border="0" vspace="0" hspace="0" marginwidth="0"
marginheight="0" framespacing="0" frameborder="0" scrolling="no" width="0"
height="0" src="http://unstat.baidu.com/bdas.bsc?tn=zouwenyedg"></iframe>
<center>
<link rel="stylesheet" type="text/css" href="../css/css.css"">
<style type="text/css">
<!--
body {
background-color: #000000;
}
.style1 {color: #FFFFFF}
-->
</style>
<link rel="stylesheet" type="text/css" href="../css/css.css"">
<style type="text/css">
<!--
body {
background-color: #003366;
}
.style1 {color: #FFFFFF}
.style2 {color: #000000}
-->
</style>
<cneter>
<table width="762" height="5" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="783" bgcolor="#FFFFFF"></td>
</tr>
</table>
</center>
<center>
<table width="762" height="77" border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF">
<tr valign="top">
<td width="178" height="80" valign="top"><img src="../images/logo.gif" width="178" height="80"></td>
<td width="581" valign="top"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="582" height="80">
<param name="movie" value="../pic/005.swf">
<param name="quality" value="high">
<embed src="../pic/005.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="582" height="80"></embed>
</object></td>
</tr>
</table>
</center>
<center>
<table width="762" border="0" cellpadding="0" cellspacing="0" background="../pic/lbg.gif">
<tr>
<td width="430"><table width="430" cellpadding="0" cellspacing="0" >
<form action="../search.asp" method="post">
<tr >
<td width="428" height="22" align="left" valign="middle"> <span class="style1">資源搜索</span> <input type=text size=42 name="keyword" class=button>
<input type=submit value="搜 索" name="submit" class=button>
<input type=hidden name=datesearch value=all>
<input type="hidden" name="AreaSearch" value=1>
</td>
</tr>
</form>
</table></td>
<td width="330"></td>
</tr>
</table>
<table width="762" height="1" border="0" cellpadding="0" cellspacing="0" background="../../images/hhh.gif" bgcolor="#AD0000">
<tr>
<td height="1" align="left" valign="top"><img src="../../images/hhh.gif" width="3" height="1"></td>
</tr>
</table>
</center>
<center>
<table width="762" border="0" cellpadding="0" cellspacing="0" bgcolor="#AD0000">
<tr>
<td width="577" height="228" align="left" valign="top" bgcolor="#FFFFFF"><table width="577" height="125" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="577" height="125" align="left" valign="top"><table width="577" border="0" align="left" cellpadding="0" cellspacing="0">
<tr>
<td width="577" align="center" valign="top"><table width="577" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="740" height="20"> 當前位置:<a href="http://www.xxlinux.com">首頁</a> >> LINUX開發區 >> 軟件開發 >> 正文</td>
</tr>
</table>
<table width="577" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="637" height="24" align="center" valign="middle" bgcolor="eeeeee"><font style="font-size:16px"><b>善用GNU Make做開發</b></font><font
color="#999999"> </font></td>
</tr>
</table>
<table width="577" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="747" height="24" align="center" valign="middle"><font
color="#999999"><font color="#CC0000">來源:<font color="#CC0000">賽迪網</font> <font color="#999999"></font> 時間:2004-11-16 13:11:07</font></font></td>
</tr>
</table>
<table width="577" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="749" align="right" valign="middle"><font color="#999999">發布:<font color="#CC0000">燕南天</font>
<script language=javascript src="../count.asp?Filename=20041116131107.htm"></script>
</font> </td>
</tr>
</table>
<table width="577" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="748"> </td>
</tr>
</table>
<table width="563" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="563"><font class=f14 id=zoom> 在編寫小型的Linux應用程序時,一般情況下只會有少數幾個源文件。這樣程序員能夠很容易地理清它們之間的包含和引用關系。但隨著軟件項目逐漸變大,對源文件的處理也將變得越來越復雜起來。此時單純依賴手工方式進行管理的做法就顯得有些力不從心了。為此,Linux專門為軟件開發提供了一個自動化管理工具GNU make。通過它,程序員可以很方便地管理軟件編譯的內容、方式和時機,從而使程序員能夠把主要精力集中在代碼的編寫上。 <BR><BR> make將整個軟件項目的代碼分開放在幾個小的源文件里,在改動其中一個文件的時候,可以只對該文件重新進行編譯,然后重新連接所有的目標文件。對于那些由許多源文件組成的大型軟件項目來說,全部重新進行編譯需要花費很長的時間,而采用這種項目管理方法則可以極大地提高工作效率,讓原本復雜繁瑣的開發工作變簡單。 <BR><BR> <B>Makefile文件</B> <BR><BR> GNU make是一個用來控制軟件構建過程的自動工具,程序員通過定義構建規則來控制代碼的創建過程。這些規則通常定義在一個名為Makefile的文件中。Makefile被用來告訴make編譯哪些文件、怎樣編譯和何時編譯。Makefile中的每條規則事實上都包含如下一些內容:<BR> ◆ 目標(target)是make最終需要創建的對象;<BR> ◆ 依賴(dependency)通常是一個列表,指明編譯目標時需要用到的其它文件;<BR> ◆ 命令(command)也是一個列表,指明從依賴文件創建出目標對象所需要執行的命令。 <BR><BR> 雖然Makefile中的目標通常都是可執行程序,但事實上可以是諸如文本文件和HTML頁面等任何內容,甚至能夠用來測試或設置環境變量。Makefile中的命令則不僅可以是編譯命令,還可以是任何Shell命令。 <BR><BR> 先來看一個例子。假設整個軟件項目是由control.c、io.c和main.c三個源文件所構成的,編寫的Makefile文件內容如下: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>all : program
program : control.o ui.o main.o
gcc -o program control.o ui.o main.o
control.o : control.c
gcc -Wall -c -o control.o control.c
ui.o : ui.c
gcc -Wall -c -o ui.o ui.c
main.o : main.c
gcc -Wall -c -o main.o main.c
clean :
rm -f program *.o</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> 在將上述Makefile文件與源文件保存到同一目錄之后,就可以在命令行中輸入“make”命令來編譯整個項目了。make在執行過程中,首先會查找到Makefile文件第一條規則中的目標,即上述文件中的all。根據設定好的規則,該目標需要依賴于program。由于all并不是一個已經存在的文件,所以每次在make被調用的時候,顯然都需要先檢查program。繼續往下不難發現,program目標是依賴于control.o、ui.o和main.o的。這就意味著如果其中任何一個比生成的可執行文件要新,那么就需要重新構建可執行文件program,否則就沒有必要執行這一步了。 <BR><BR> 在Makefile文件的其余部分,為每一個中間生成的目標文件都專門定義了一條規則,用來指明創建過程中它們與C源文件的依賴性。也就是說,如果一個特定的C源文件被更新了,那么與之對應的目標文件也必須重新生成。下面是make在構建項目過程中的輸出結果: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>#make
gcc -Wall -c -o control.o control.c
gcc -Wall -c -o ui.o ui.c
gcc -Wall -c -o main.o main.c
gcc -o program control.o ui.o main.o</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> 不難看出,首先是C源文件被編譯成目標文件,然后才是目標文件被連接成最終的可執行文件。由于相互間依賴關系的制約,這些步驟會被有條不紊地依次執行。最終可執行文件要求目標文件都被更新過,而每個目標文件則要求C源文件被更新過。如果此時重新執行“make”命令,會出現下面的結果。原因是程序已經被編譯過了,并且沒有做過任何改動,所以就沒有再編譯的必要了: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE># make
make: Nothing to be done for 'all'.</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> 如果只是改變了其中的部分文件,那么make會自動檢測出需要對哪些源文件重新進行編譯,并連接成最后的可執行文件。用戶可以參考下面的過程: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>#touch main.c
# make
gcc -Wall -c -o main.o main.c
gcc -o program control.o ui.o main.o</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> 當make檢測到main.o目標時,發現main.c文件已經被更新,于是main.o文件必須被重新編譯,相應地program需要被重新連接。make的魅力就在于能夠自動進行條件檢測,并采取適當的行動。它永遠也不會去編譯那些沒有改動過的源文件,因此大大節省了在開發大型軟件項目時所浪費在編譯上的時間。 <BR><BR> <B>變量</B> <BR><BR> 為了簡化Makefile的編寫,make引入了變量。變量實際上是為文本串在Makefile中定義一個便于記憶的名稱。變量的定義和應用與Linux的環境變量一樣,變量名大寫,變量一旦定義之后,就可以通過將變量名用圓括號包起來,并在前面加上“$”符號來進行引用。 <BR><BR> 變量一般都在Makefile的頭部定義。如果變量的值發生了改變,很顯然只需在一個地方進行修改就可以了,從而大大簡化了Makefile的維護。下面是將前面用到的Makefile利用變量進行改寫后的結果: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o program
control.o : control.c
$(CC) $(CFLAGS) -c -o control.o control.c
ui.o : ui.c
$(CC) $(CFLAGS) -c -o ui.o ui.c
main.o : main.c
$(CC) $(CFLAGS) -c -o main.o main.c
clean :
rm -f program $(OBJS)</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> make將其使用的變量細分為兩類:遞歸展開變量和簡單展開變量。遞歸展開變量在被引用時會逐層展開,即如果在展開式中包含了對其它變量的引用,則這些變量也會被展開,直到沒有需要被展開的變量為止。假設變量TOPDIR和SUBDIR的定義如下: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>TOPDIR = /home/xiaowp
SUBDIR = $(TOPDIR)/project</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> 此時變量SUBDIR的值在解析時會被正確地展開為/home/xiaowp/project,但對于下面的定義: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>TOPDIR = /home/xiaowp
SUBDIR = $(TOPDIR)/project
SUBDIR = $(SUBDIR)/src</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR> 很清楚,希望得到的結果是/home/xiaowp/project/src,但實際并非如此。SUBDIR在引用時會被遞歸展開,從而陷入一個無限循環當中,make能夠檢測到這個問題并報告如下錯誤:<BR> *** Recursive variable 'SUBDIR' references itself (eventually). Stop <BR><BR> 為了避免這個問題,可以使用簡單展開變量。與遞歸展開變量在引用時展開不同,簡單展開變量是在定義處展開的,并且只展開一次,從而消除了變量的嵌套引用。在定義時,其語法與遞歸展開變量有細微的不同: <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -