📄 2.htm
字号:
<tr>
<td align="right" style="border-bottom: 1px dashed #B0C4DE; color: #0033ff;"><font style="font-size: 8pt;">Java/Linux</font></td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=6" >Java</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=6">rss</a>) </td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=5" >Perl</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=5">rss</a>) </td>
</tr>
</table>
<table cellspacing="0" cellpadding="0" width="95%" border="0" style="margin-bottom: 4px;" align="center">
<tr>
<td align="right" style="border-bottom: 1px dashed #B0C4DE; color: #0033ff;"><font style="font-size: 8pt;">综合</font></td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=9" >其他开发语言</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=9">rss</a>) </td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=11" >文件格式</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=11">rss</a>) </td>
</tr>
</table>
<table cellspacing="0" cellpadding="0" width="95%" border="0" style="margin-bottom: 4px;" align="center">
<tr>
<td align="right" style="border-bottom: 1px dashed #B0C4DE; color: #0033ff;"><font style="font-size: 8pt;">企业开发</font></td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=10" >游戏开发</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=10">rss</a>) </td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=12" >网站制作技术</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=12">rss</a>) </td>
</tr>
</table>
<table cellspacing="0" cellpadding="0" width="95%" border="0" style="margin-bottom: 4px;" align="center">
<tr>
<td align="right" style="border-bottom: 1px dashed #B0C4DE; color: #0033ff;"><font style="font-size: 8pt;">数据库</font></td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=8" >数据库开发</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=8">rss</a>) </td>
</tr>
</table>
<table cellspacing="0" cellpadding="0" width="95%" border="0" align="center">
<tr>
<td align="right" style="border-bottom: 1px dashed #B0C4DE; color: #0033ff;"><font style="font-size: 8pt;">软件工程</font></td>
</tr>
<tr>
<td align="right"><a href="/articlelist.aspx?c=13" >其他</a> (<a href="http://www.csdn.net/Rss/RssFeed.aspx?rssid=1&bigclassid=13">rss</a>) </td>
</tr>
</table>
</td>
</tr>
</table>
<br>
<table width="100%" border="0" cellspacing="1" cellpadding="0" bgcolor="#000000">
<tr>
<td valign="top" bgcolor="#EDEDED">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td height="27" align="right" background="/images/top.gif"><font class="fonttitle">积极原创作者 </font></td>
</tr>
</table>
<table width="100%" cellpadding="2" cellspacing="1" border="0">
<tr><td align="right"><a href='/user/qiaoshaojie'>qiaoshaojie</a> <font color="#FF0000">(1)</font></td></tr>
<tr><td align="right"><a href='/user/yoqi'>yoqi</a> <font color="#FF0000">(1)</font></td></tr>
<tr><td align="right"><a href='/user/eliry'>eliry</a> <font color="#FF0000">(2)</font></td></tr>
<tr><td align="right"><a href='/user/fasttalk'>fasttalk</a> <font color="#FF0000">(23)</font></td></tr>
<tr><td align="right"><a href='/user/BennyMavis'>BennyMavis</a> <font color="#FF0000">(4)</font></td></tr>
<tr><td align="right"><a href='/user/james999'>james999</a> <font color="#FF0000">(31)</font></td></tr>
<tr><td align="right"><a href='/user/MasterLRC'>MasterLRC</a> <font color="#FF0000">(12)</font></td></tr>
<tr><td align="right"><a href='/user/fatalerror99'>fatalerror99</a> <font color="#FF0000">(1)</font></td></tr>
<tr><td align="right"><a href='/user/ihavenoidea'>ihavenoidea</a> <font color="#FF0000">(1)</font></td></tr>
<tr><td align="right"><a href='/user/ire_wang'>ire_wang</a> <font color="#FF0000">(2)</font></td></tr>
</table>
</td>
</tr>
</table>
</TD>
<TD vAlign="top" width="786">
<table width="100%" border="0" cellpadding="4">
<tr>
<td width="10" height="19"></td>
<td height="19">
<table width="100%" border="0" cellspacing="3" cellpadding="3">
<tr>
<td>
<a href="http://www.csdn.net/">CSDN</a> - <a href="http://dev.csdn.net/">文档中心</a>
- <font color="#003399">
<a id="ArticleTitle1_ArticleTitle1_hlClass" href="/articlelist.aspx?c=13">其他</a></font>
</td>
<TD align="right">
阅读:<span id="ArticleTitle1_ArticleTitle1_lblReadCount">26329</span>
评论:
<span id="ArticleTitle1_ArticleTitle1_lblCommentCount">3</span>
<a href="#Comment">参与评论</a>
</TD>
</tr>
</table>
<table width="100%" border="0" cellspacing="3" cellpadding="3" bgcolor="#eeeeee">
<tr>
<td width="60" height="0" nowrap></td>
<td></td>
</tr>
<tr>
<td height="16" align="center" nowrap bgcolor="#003399"><font color="#ffffff">标题</font></td>
<td><b>
<span id="ArticleTitle1_ArticleTitle1_lblTitle">跟我一起写 Makefile(二)</span></b>
选择自 <a id="ArticleTitle1_ArticleTitle1_AuthorLink" href="/user/haoel">haoel</a> 的 Blog
</td>
</tr>
<tr>
<td height="16" align="center" bgcolor="#003399"><font color="#ffffff">关键字</font></td>
<td width="500">
<span id="ArticleTitle1_ArticleTitle1_lblKeywords">C C++ make makefile</span></td>
</tr>
<tr>
<td height="16" align="center" bgcolor="#003399"><font color="#ffffff">出处</font></td>
<td>
<span id="ArticleTitle1_ArticleTitle1_lblSource"></span></td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="10"></td>
<td><span id="ArticleContent1_ArticleContent1_lblContent"><P><FONT face="Courier New"><STRONG>三、make是如何工作的</STRONG></FONT></P>
<P><FONT face="Courier New">在默认的方式下,也就是我们只输入make命令。那么,</FONT></P>
<P><FONT face="Courier New"> 1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。<BR> 2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。<BR> 3、如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。<BR> 4、如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)<BR> 5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。</FONT></P>
<P><FONT face="Courier New">这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。</FONT></P>
<P><FONT face="Courier New">通过上述分析,我们知道,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。</FONT></P>
<P><FONT face="Courier New">于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如file.c,那么根据我们的依赖性,我们的目标file.o会被重编译(也就是在这个依性关系后面所定义的命令),于是file.o的文件也是最新的啦,于是file.o的文件修改时间要比edit要新,所以edit也会被重新链接了(详见edit目标文件后定义的命令)。</FONT></P>
<P><FONT face="Courier New">而如果我们改变了“command.h”,那么,kdb.o、command.o和files.o都会被重编译,并且,edit会被重链接。</FONT></P>
<P><BR><FONT face="Courier New"><STRONG>四、makefile中使用变量</STRONG></FONT></P>
<P><FONT face="Courier New">在上面的例子中,先让我们看看edit的规则:</FONT></P>
<P><FONT face="Courier New"> edit : main.o kbd.o command.o display.o \<BR> insert.o search.o files.o utils.o<BR> cc -o edit main.o kbd.o command.o display.o \<BR> insert.o search.o files.o utils.o</FONT></P>
<P><FONT face="Courier New">我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文件,那么我们需要在两个地方加(应该是三个地方,还有一个地方在clean中)。当然,我们的makefile并不复杂,所以在两个地方加也不累,但如果makefile变得复杂,那么我们就有可能会忘掉一个需要加入的地方,而导致编译失败。所以,为了makefile的易维护,在makefile中我们可以使用变量。makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。</FONT></P>
<P><FONT face="Courier New">比如,我们声明一个变量,叫objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,反正不管什么啦,只要能够表示obj文件就行了。我们在makefile一开始就这样定义:</FONT></P>
<P><FONT face="Courier New"> objects = main.o kbd.o command.o display.o \<BR> insert.o search.o files.o utils.o</FONT></P>
<P><FONT face="Courier New">于是,我们就可以很方便地在我们的makefile中以“$(objects)”的方式来使用这个变量了,于是我们的改良版makefile就变成下面这个样子:</FONT></P>
<P><FONT face="Courier New"> objects = main.o kbd.o command.o display.o \<BR> insert.o search.o files.o utils.o</FONT></P>
<P><FONT face="Courier New"> edit : $(objects)<BR> cc -o edit $(objects)<BR> main.o : main.c defs.h<BR> cc -c main.c<BR> kbd.o : kbd.c defs.h command.h<BR> cc -c kbd.c<BR> command.o : command.c defs.h command.h<BR> cc -c command.c<BR> display.o : display.c defs.h buffer.h<BR> cc -c display.c<BR> insert.o : insert.c defs.h buffer.h<BR> cc -c insert.c<BR> search.o : search.c defs.h buffer.h<BR> cc -c search.c<BR> files.o : files.c defs.h buffer.h command.h<BR> cc -c files.c<BR> utils.o : utils.c defs.h<BR> cc -c utils.c<BR> clean :<BR> rm edit $(objects)</FONT></P>
<P><FONT face="Courier New"><BR>于是如果有新的 .o 文件加入,我们只需简单地修改一下 objects 变量就可以了。</FONT></P>
<P><FONT face="Courier New">关于变量更多的话题,我会在后续给你一一道来。</FONT></P>
<P><BR><FONT face="Courier New"><STRONG>五、让make自动推导</STRONG></FONT></P>
<P><FONT face="Courier New">GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。</FONT></P>
<P><FONT face="Courier New">只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。</FONT></P>
<P><BR><FONT face="Courier New"> objects = main.o kbd.o command.o display.o \<BR> insert.o search.o files.o utils.o</FONT></P>
<P><FONT face="Courier New"> edit : $(objects)<BR> cc -o edit $(objects)</FONT></P>
<P><FONT face="Courier New"> main.o : defs.h<BR> kbd.o : defs.h command.h<BR> command.o : defs.h command.h<BR> display.o : defs.h buffer.h<BR> insert.o : defs.h buffer.h<BR> search.o : defs.h buffer.h<BR> files.o : defs.h buffer.h command.h<BR> utils.o : defs.h</FONT></P>
<P><FONT face="Courier New"> .PHONY : clean<BR> clean :<BR> rm edit $(objects)</FONT></P>
<P><FONT face="Courier New">这种方法,也就是make的“隐晦规则”。上面文件内容中,“.PHONY”表示,clean是个伪目标文件。</FONT></P>
<P><FONT face="Courier New">关于更为详细的“隐晦规则”和“伪目标文件”,我会在后续给你一一道来。</FONT></P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -