﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-DANCE WITH JAVA-随笔分类-利器</title><link>http://www.blogjava.net/dreamstone/category/15444.html</link><description>开发出高质量的系统</description><language>zh-cn</language><lastBuildDate>Sat, 26 Jan 2008 15:33:38 GMT</lastBuildDate><pubDate>Sat, 26 Jan 2008 15:33:38 GMT</pubDate><ttl>60</ttl><item><title>apache Ant中文手册 2.0版 (教程)</title><link>http://www.blogjava.net/dreamstone/archive/2008/01/25/177827.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 25 Jan 2008 10:36:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2008/01/25/177827.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/177827.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2008/01/25/177827.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/177827.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/177827.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ant 中文手册 教程&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2008/01/25/177827.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/177827.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2008-01-25 18:36 <a href="http://www.blogjava.net/dreamstone/archive/2008/01/25/177827.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdom 或 dom4j读取xml文件时如何让dtd验证使用本地dtd文件或者不生效</title><link>http://www.blogjava.net/dreamstone/archive/2007/08/29/140993.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 29 Aug 2007 09:05:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/08/29/140993.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/140993.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/08/29/140993.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/140993.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/140993.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、写在所有之前：因为dom4j和jdom在这个问题上处理的方法是一模一样的，只是一个是SAXBuilder 一个SAXReader，这里以jdom距离，至于dom4j只需要同理替换一下就可以了。二、问题发生的情况当你用jdom读取一个有dtd验证的xml文件,同时你的网络是不通的情况下。会出现以下错误：1，代码如下package&nbsp;dom;import&nbsp;java.io.Fi...&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/08/29/140993.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/140993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-08-29 17:05 <a href="http://www.blogjava.net/dreamstone/archive/2007/08/29/140993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse3.3的一些新的特性</title><link>http://www.blogjava.net/dreamstone/archive/2007/07/27/132865.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 27 Jul 2007 10:08:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/07/27/132865.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/132865.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/07/27/132865.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/132865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/132865.html</trackback:ping><description><![CDATA[eclipse3.3相对3.2有很大改动，不过以一个使用者的身份罗列一些新的特性。<br>1,ctrl + shift+ o 在代码中有错误的时候也能执行了<br>2,显示个数&nbsp;&nbsp; 显示tab数变多了<br>3,最大最小化效果好了，而且多了直接能点开一些窗口的按钮。注意边上<br>4,执行速度变快了，启动速度，关闭速度都快了很多<br>5,导入工程的时候选定一个文件夹，自动寻找子文件夹中的所有工程，并且过滤掉已经导入的工程。<br>6,新建工程的时候自动建处src和bin，虽然3.2的时候也可以自己手动配置实现，但3.3时默认实现，更人性化一<br>些。<br>7,据说占用内存少了<br>用了一天看到就这些，欢迎补充. 
<img src ="http://www.blogjava.net/dreamstone/aggbug/132865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-07-27 18:08 <a href="http://www.blogjava.net/dreamstone/archive/2007/07/27/132865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过httpClient连接 tomcat https  (ssl)</title><link>http://www.blogjava.net/dreamstone/archive/2007/07/27/132861.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 27 Jul 2007 10:01:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/07/27/132861.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/132861.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/07/27/132861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/132861.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/132861.html</trackback:ping><description><![CDATA[&nbsp;
<p><span>HttpClient</span><span>连接</span><span>tomcat https</span><span>（使用私有证书）</span></p>
<p><span>步骤一：</span></p>
<p><span>在</span><span>www.apache.org</span><span>下载所需的类包</span></p>
<p><span>commons-codec-1.3.jar</span></p>
<p><span>commons-httpclient-3.1-rc1.jar</span></p>
<p><span>commons-logging.jar</span></p>
<p><span>步骤二：</span></p>
<p><span>制作证书：</span></p>
<p><span>keytool -genkey -alias tomcat -keyalg RSA</span></p>
<p><span>任意输入，最后一个提示输入回车（保证两个密码相等）否则</span><span>tomcat</span><span>不能启动</span><span>.</span></p>
<p><span>默认生成的文件在用户目录下</span><span>.keystore</span></p>
<p><span>步骤三：</span></p>
<p><span>配置</span><span>tomcat</span></p>
<p><span>更改</span><span>tomcat</span><span>配置文件</span><span>server.xml</span></p>
<p><span>加入</span></p>
<p><span>&lt;Connector port="8443" maxHttpHeaderSize="8192"</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>maxThreads="150" minSpareThreads="25" maxSpareThreads="75"</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>enableLookups="false" disableUploadTimeout="true"</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>acceptCount="100" scheme="https" secure="true"</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>clientAuth="false" sslProtocol="TLS" </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp; </span>keystoreFile="C:\.keystore"<span>&nbsp;&nbsp; </span>keystorePass="123456"</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp; </span>/&gt;</span></p>
<p><span>其中</span><span>keystoreFile</span><span>是刚生成文件的带全路径的名字</span></p>
<p><span>keystorePass</span><span>是刚才建立证书时候的名字</span></p>
<p><span>启动</span><span>tomcat</span><span>，访问</span><span>https:\\localhost:8443/</span><span>如果能正常看到，说明</span><span>tomcat</span><span>的</span><span>https</span><span>配置成功</span><span>.</span></p>
<p><span>步骤四：</span></p>
<p><span>生成</span><span>jdk</span><span>能使用的证书<br></span>&nbsp;1,用ie导出证书(导出方法：<a href="http://www.ibm.com/developerworks/cn/opensource/os-httpclient/#N10114">http://www.ibm.com/developerworks/cn/opensource/os-httpclient/#N10114</a>)</p>
<p><span>2,假设上边导出文件的名字叫</span><span>tt.cer</span></p>
<p><span>执行</span><span>(</span><span>确保配置了</span><span>java &nbsp;home)</span></p>
<p><span>keytool -import -noprompt -keystore <span>D:\Java\jdk<st1:chsdate w:st="on" Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False">1.5.0</st1:chsdate>_06\jre\lib\security\carcert</span> -alias tomcat -file<span> tt.cer </span>&#8211;trustcacerts</span></p>
<p><span>其中红色的部分替换成自己</span><span>jre</span><span>的路径</span><span>,alias</span><span>同建立证书时的名字，</span><span>file</span><span>时刚才导出的证书的名字</span></p>
<p>&nbsp;</p>
<p><span>会提示输入密码，输入刚才建立证书时输入的密码</span></p>
<p>&nbsp;</p>
<p><span>步骤五：</span></p>
<p><span>编写代码</span></p>
<p align=left>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.commons.httpclient.HttpClient;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.commons.httpclient.HttpStatus;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.commons.httpclient.methods.GetMethod;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.commons.httpclient.params.HttpMethodParams;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_304_1224_Open_Image onclick="this.style.display='none'; Codehighlighter1_304_1224_Open_Text.style.display='none'; Codehighlighter1_304_1224_Closed_Image.style.display='inline'; Codehighlighter1_304_1224_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_304_1224_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_304_1224_Closed_Text.style.display='none'; Codehighlighter1_304_1224_Open_Image.style.display='inline'; Codehighlighter1_304_1224_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Test&nbsp;</span><span id=Codehighlighter1_304_1224_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_304_1224_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_362_389_Open_Image onclick="this.style.display='none'; Codehighlighter1_362_389_Open_Text.style.display='none'; Codehighlighter1_362_389_Closed_Image.style.display='inline'; Codehighlighter1_362_389_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_362_389_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_362_389_Closed_Text.style.display='none'; Codehighlighter1_362_389_Open_Image.style.display='inline'; Codehighlighter1_362_389_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception</span><span id=Codehighlighter1_362_389_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_362_389_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;normal();</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssl();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_432_492_Open_Image onclick="this.style.display='none'; Codehighlighter1_432_492_Open_Text.style.display='none'; Codehighlighter1_432_492_Closed_Image.style.display='inline'; Codehighlighter1_432_492_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_432_492_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_432_492_Closed_Text.style.display='none'; Codehighlighter1_432_492_Open_Image.style.display='inline'; Codehighlighter1_432_492_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ssl()</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception</span><span id=Codehighlighter1_432_492_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_432_492_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;url&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">https://127.0.0.1:8443/ts/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get(url);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_538_597_Open_Image onclick="this.style.display='none'; Codehighlighter1_538_597_Open_Text.style.display='none'; Codehighlighter1_538_597_Closed_Image.style.display='inline'; Codehighlighter1_538_597_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_538_597_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_538_597_Closed_Text.style.display='none'; Codehighlighter1_538_597_Open_Image.style.display='inline'; Codehighlighter1_538_597_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;normal()</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception</span><span id=Codehighlighter1_538_597_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_538_597_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;url&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://127.0.0.1:8080/ts/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get(url);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_651_1222_Open_Image onclick="this.style.display='none'; Codehighlighter1_651_1222_Open_Text.style.display='none'; Codehighlighter1_651_1222_Closed_Image.style.display='inline'; Codehighlighter1_651_1222_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_651_1222_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_651_1222_Closed_Text.style.display='none'; Codehighlighter1_651_1222_Open_Image.style.display='inline'; Codehighlighter1_651_1222_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;get(String&nbsp;url)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception</span><span id=Codehighlighter1_651_1222_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_651_1222_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient&nbsp;client&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;HttpClient();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetMethod&nbsp;getMethod&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;GetMethod(url);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;DefaultHttpMethodRetryHandler());&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">执行getMethod</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;statusCode&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;client.executeMethod(getMethod);<br><img id=Codehighlighter1_1010_1085_Open_Image onclick="this.style.display='none'; Codehighlighter1_1010_1085_Open_Text.style.display='none'; Codehighlighter1_1010_1085_Closed_Image.style.display='inline'; Codehighlighter1_1010_1085_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1010_1085_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1010_1085_Closed_Text.style.display='none'; Codehighlighter1_1010_1085_Open_Image.style.display='inline'; Codehighlighter1_1010_1085_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(statusCode&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;HttpStatus.SC_OK)&nbsp;</span><span id=Codehighlighter1_1010_1085_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1010_1085_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.err.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Method&nbsp;failed:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;getMethod.getStatusLine());<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">byte</span><span style="COLOR: #000000">[]&nbsp;responseBody&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;getMethod.getResponseBody();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;String(responseBody));<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getMethod.releaseConnection();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p align=left>&nbsp;</p>
<p><span>普通连接和</span><span>ssl</span><span>连接只有一个差距就是</span><span>url</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/132861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-07-27 18:01 <a href="http://www.blogjava.net/dreamstone/archive/2007/07/27/132861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>apache mina (异步连接框架)介绍</title><link>http://www.blogjava.net/dreamstone/archive/2007/07/09/129004.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 09 Jul 2007 03:26:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/07/09/129004.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/129004.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/07/09/129004.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/129004.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/129004.html</trackback:ping><description><![CDATA[<font size=2>一、介绍<br>mina(Multipurpose Infrastructure for Network Applications) 是apache的顶级项目之一，用于构造异步连接的各种网络应用<br>二、最简单的使用实例<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;aicu.mina;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.IOException;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.net.InetSocketAddress;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.nio.charset.Charset;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.ByteBuffer;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.IoAcceptor;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.SimpleByteBufferAllocator;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.filter.LoggingFilter;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.filter.codec.ProtocolCodecFilter;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.filter.codec.textline.TextLineCodecFactory;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.transport.socket.nio.SocketAcceptor;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.transport.socket.nio.SocketAcceptorConfig;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_581_1434_Open_Image onclick="this.style.display='none'; Codehighlighter1_581_1434_Open_Text.style.display='none'; Codehighlighter1_581_1434_Closed_Image.style.display='inline'; Codehighlighter1_581_1434_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_581_1434_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_581_1434_Closed_Text.style.display='none'; Codehighlighter1_581_1434_Open_Image.style.display='inline'; Codehighlighter1_581_1434_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MinaTimeServer&nbsp;</span><span id=Codehighlighter1_581_1434_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_581_1434_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;PORT&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">9123</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_689_1432_Open_Image onclick="this.style.display='none'; Codehighlighter1_689_1432_Open_Text.style.display='none'; Codehighlighter1_689_1432_Closed_Image.style.display='inline'; Codehighlighter1_689_1432_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_689_1432_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_689_1432_Closed_Text.style.display='none'; Codehighlighter1_689_1432_Open_Image.style.display='inline'; Codehighlighter1_689_1432_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;IOException&nbsp;</span><span id=Codehighlighter1_689_1432_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_689_1432_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置buffer</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByteBuffer.setUseDirectBuffers(</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByteBuffer.setAllocator(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SimpleByteBufferAllocator());<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">定义acceptor</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IoAcceptor&nbsp;acceptor&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SocketAcceptor();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">定义config</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SocketAcceptorConfig&nbsp;cfg&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SocketAcceptorConfig();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置config,加入filter</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cfg.getSessionConfig().setReuseAddress(&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cfg.getFilterChain().addLast(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">logger</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;LoggingFilter()&nbsp;);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cfg.getFilterChain().addLast(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">codec</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ProtocolCodecFilter(&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;TextLineCodecFactory(&nbsp;Charset.forName(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UTF-8</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;))));<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">加入port&nbsp;handler&nbsp;cfg</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;acceptor.bind(&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;InetSocketAddress(PORT),&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;TimeServerHandler(),&nbsp;cfg);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">MINA&nbsp;Time&nbsp;server&nbsp;started.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>对应的handler ,handler的作用是在对应的网事件的处理代码<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;aicu.mina;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.util.Date;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.IdleStatus;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.IoHandlerAdapter;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.IoSession;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.common.TransportType;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.apache.mina.transport.socket.nio.SocketSessionConfig;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_341_1116_Open_Image onclick="this.style.display='none'; Codehighlighter1_341_1116_Open_Text.style.display='none'; Codehighlighter1_341_1116_Closed_Image.style.display='inline'; Codehighlighter1_341_1116_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_341_1116_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_341_1116_Closed_Text.style.display='none'; Codehighlighter1_341_1116_Open_Image.style.display='inline'; Codehighlighter1_341_1116_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TimeServerHandler&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;IoHandlerAdapter&nbsp;</span><span id=Codehighlighter1_341_1116_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_341_1116_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_421_466_Open_Image onclick="this.style.display='none'; Codehighlighter1_421_466_Open_Text.style.display='none'; Codehighlighter1_421_466_Closed_Image.style.display='inline'; Codehighlighter1_421_466_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_421_466_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_421_466_Closed_Text.style.display='none'; Codehighlighter1_421_466_Open_Image.style.display='inline'; Codehighlighter1_421_466_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;exceptionCaught(IoSession&nbsp;session,&nbsp;Throwable&nbsp;t)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception&nbsp;</span><span id=Codehighlighter1_421_466_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_421_466_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.printStackTrace();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.close();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_546_804_Open_Image onclick="this.style.display='none'; Codehighlighter1_546_804_Open_Text.style.display='none'; Codehighlighter1_546_804_Closed_Image.style.display='inline'; Codehighlighter1_546_804_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_546_804_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_546_804_Closed_Text.style.display='none'; Codehighlighter1_546_804_Open_Image.style.display='inline'; Codehighlighter1_546_804_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;messageReceived(IoSession&nbsp;session,&nbsp;Object&nbsp;msg)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception&nbsp;</span><span id=Codehighlighter1_546_804_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_546_804_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;msg.toString();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">如果是quit就关闭session退出</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_647_682_Open_Image onclick="this.style.display='none'; Codehighlighter1_647_682_Open_Text.style.display='none'; Codehighlighter1_647_682_Closed_Image.style.display='inline'; Codehighlighter1_647_682_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_647_682_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_647_682_Closed_Text.style.display='none'; Codehighlighter1_647_682_Open_Image.style.display='inline'; Codehighlighter1_647_682_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;str.trim().equalsIgnoreCase(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">quit</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;)&nbsp;</span><span id=Codehighlighter1_647_682_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_647_682_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.close();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">否则打印当前日期</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;date&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Date();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.write(&nbsp;date.toString()&nbsp;);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Message&nbsp;written<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_871_1114_Open_Image onclick="this.style.display='none'; Codehighlighter1_871_1114_Open_Text.style.display='none'; Codehighlighter1_871_1114_Closed_Image.style.display='inline'; Codehighlighter1_871_1114_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_871_1114_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_871_1114_Closed_Text.style.display='none'; Codehighlighter1_871_1114_Open_Image.style.display='inline'; Codehighlighter1_871_1114_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sessionCreated(IoSession&nbsp;session)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception&nbsp;</span><span id=Codehighlighter1_871_1114_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_871_1114_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Session&nbsp;created<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;session.getTransportType()&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;TransportType.SOCKET&nbsp;)<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((SocketSessionConfig)&nbsp;session.getConfig()&nbsp;).setReceiveBufferSize(&nbsp;</span><span style="COLOR: #000000">2048</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setIdleTime(&nbsp;IdleStatus.BOTH_IDLE,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
三、使用方法：<br>编译上边两个类（需要加入mina的jar文件)，然后运行terminalServer<br>开始-&gt;运行-&gt;cmd进入控制台<br>telnet 127.0.0.1 9123<br>输入hello<br>得到当前日期<br>输入quit关闭session。<br></font>
<img src ="http://www.blogjava.net/dreamstone/aggbug/129004.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-07-09 11:26 <a href="http://www.blogjava.net/dreamstone/archive/2007/07/09/129004.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SLF4J 教程（自由在各种log中切换)</title><link>http://www.blogjava.net/dreamstone/archive/2007/07/09/128993.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 09 Jul 2007 02:47:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/07/09/128993.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/128993.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/07/09/128993.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/128993.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/128993.html</trackback:ping><description><![CDATA[<p>一、介绍：<br>简单日记门面(simple logging Facade for java)SLF4J是为各种loging APIs提供一个简单统一的<br>接口，从而使得最终用户能够在部署的时候配置自己希望的loging APIs实现。 Logging API实现既可以<br>选择直接实现SLF4J接的loging APIs如： NLOG4J、SimpleLogger。也可以通过SLF4J提供的API实现<br>来开发相应的适配器如Log4jLoggerAdapter、JDK14LoggerAdapter。在SLF4J发行版本中包含了几个<br>jar包，如slf4j-nop.jar, slf4j-simple.jar, slf4j-log4j12.jar, slf4j-log4j13.jar, <br>slf4j-jdk14.jar and slf4j-jcl.jar通过这些jar文件可以使编译期与具体的实现脱离。或者说可以<br>灵活的切换<br>二、官方站点<br>官方的网站：<a href="http://www.slf4j.org/manual.html">http://www.slf4j.org/manual.html</a><br>三、为何使用slf4j?<br>我们在开发过程中可能使用各种log，每个Log有不同的风格、布局，如果想灵活的切换那么slf4j是比较好的<br>选择。<br>四、如何使用slf4j<br>下边一段程序是经典的使用slf4j的方法.</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.slf4j.Logger;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;org.slf4j.LoggerFactory;<br><img id=Codehighlighter1_77_562_Open_Image onclick="this.style.display='none'; Codehighlighter1_77_562_Open_Text.style.display='none'; Codehighlighter1_77_562_Closed_Image.style.display='inline'; Codehighlighter1_77_562_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_77_562_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_77_562_Closed_Text.style.display='none'; Codehighlighter1_77_562_Open_Image.style.display='inline'; Codehighlighter1_77_562_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Wombat&nbsp;</span><span id=Codehighlighter1_77_562_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_77_562_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000">&nbsp;Logger&nbsp;logger&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;LoggerFactory.getLogger(Wombat.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;t;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;oldT;<br><img id=Codehighlighter1_217_426_Open_Image onclick="this.style.display='none'; Codehighlighter1_217_426_Open_Text.style.display='none'; Codehighlighter1_217_426_Closed_Image.style.display='inline'; Codehighlighter1_217_426_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_217_426_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_217_426_Closed_Text.style.display='none'; Codehighlighter1_217_426_Open_Image.style.display='inline'; Codehighlighter1_217_426_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setTemperature(Integer&nbsp;temperature)&nbsp;</span><span id=Codehighlighter1_217_426_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_217_426_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oldT&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;t;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temperature;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Temperature&nbsp;set&nbsp;to&nbsp;{}.&nbsp;Old&nbsp;temperature&nbsp;was&nbsp;{}.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;t,&nbsp;oldT);<br><img id=Codehighlighter1_360_423_Open_Image onclick="this.style.display='none'; Codehighlighter1_360_423_Open_Text.style.display='none'; Codehighlighter1_360_423_Closed_Image.style.display='inline'; Codehighlighter1_360_423_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_360_423_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_360_423_Closed_Text.style.display='none'; Codehighlighter1_360_423_Open_Image.style.display='inline'; Codehighlighter1_360_423_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(temperature.intValue()&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_360_423_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_360_423_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Temperature&nbsp;has&nbsp;risen&nbsp;above&nbsp;50&nbsp;degrees.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_468_560_Open_Image onclick="this.style.display='none'; Codehighlighter1_468_560_Open_Text.style.display='none'; Codehighlighter1_468_560_Closed_Image.style.display='inline'; Codehighlighter1_468_560_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_468_560_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_468_560_Closed_Text.style.display='none'; Codehighlighter1_468_560_Open_Image.style.display='inline'; Codehighlighter1_468_560_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id=Codehighlighter1_468_560_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_468_560_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wombat&nbsp;wombat&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Wombat();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wombat.setTemperature(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wombat.setTemperature(</span><span style="COLOR: #000000">55</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br>下边介绍一下运行上边程序的过程。<br>1,编译上边的程序，需要classpath中加入slf4j-api-1.4.1.jar文件<br>2,运行时，需要classpath中加上slf4j-simple-1.4.1.jar<br>运行得到结果:<br>----------------------------<br>0 [main] ERROR Wombat - Temperature set to 1. Old temperature was null.<br>0 [main] ERROR Wombat - Temperature set to 55. Old temperature was 1.<br>0 [main] INFO Wombat - Temperature has risen above 50 degrees.<br>这个是simple log风格，</p>
<p>3,切换：如果想切换到jdk14的log的风格，只需要把slf4j-simple-1.4.1.jar<br>从classpath中移除，同时classpath中加入slj4j-jdk14-1.4.1.jar<br>这时的运行结果:<br>---------------------------------------------------<br>2007-7-9 10:40:15 Wombat setTemperature<br>严重: Temperature set to 1. Old temperature was null.<br>2007-7-9 10:40:16 Wombat setTemperature<br>严重: Temperature set to 55. Old temperature was 1.<br>2007-7-9 10:40:16 Wombat setTemperature<br>信息: Temperature has risen above 50 degrees.<br>已经变成jdk14的log风格了。<br>4,再次切换到log4j<br>同样移除slj4j-jdk14-1.4.1.jar，加入slf4j-log4j12-1.4.1.jar，同时加入log4j-1.2.x.jar<br>加入log4j.properties。得到显示结果:<br>---------------------------------------<br>10:42:27,328 ERROR Wombat: Temperature set to 1. Old temperature was null.<br>10:42:27,328 ERROR Wombat: Temperature set to 55. Old temperature was 1.<br>10:42:27,328&nbsp; INFO Wombat: Temperature has risen above 50 degrees.<br>在不同的风格中切换只需要在部署期切换类库就可以了，和开发时无关。<br></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/128993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-07-09 10:47 <a href="http://www.blogjava.net/dreamstone/archive/2007/07/09/128993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让linux开机自动启动oracle</title><link>http://www.blogjava.net/dreamstone/archive/2007/05/25/119887.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 25 May 2007 01:29:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/05/25/119887.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/119887.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/05/25/119887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/119887.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/119887.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: linux 开机 自动启动 oracle&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/05/25/119887.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/119887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-05-25 09:29 <a href="http://www.blogjava.net/dreamstone/archive/2007/05/25/119887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse3.3  m7</title><link>http://www.blogjava.net/dreamstone/archive/2007/05/18/118358.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 18 May 2007 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/05/18/118358.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/118358.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/05/18/118358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/118358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/118358.html</trackback:ping><description><![CDATA[<p>&nbsp; 下了eclipse3.3 m7看了一下,发现3.3在界面方面比3.2有很大改进,最小化问题,解决了,最大化和最小化之间的效果也做的更漂亮了.建立java工程默认有src和 bin了.更人性化了一些.</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/118358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-05-18 14:39 <a href="http://www.blogjava.net/dreamstone/archive/2007/05/18/118358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>配置tomcat5.5  jndi  各种配置方式 分析总结（mysql）</title><link>http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 07 May 2007 14:27:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/115766.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/115766.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/115766.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: tomcat5.5 jndi 各种配置方式 分析总结&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/115766.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-05-07 22:27 <a href="http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ant 中文教程 1.1版本</title><link>http://www.blogjava.net/dreamstone/archive/2007/04/30/114824.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 30 Apr 2007 09:13:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/04/30/114824.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/114824.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/04/30/114824.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/114824.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/114824.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ant  中文  教程 手册&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/04/30/114824.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/114824.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-04-30 17:13 <a href="http://www.blogjava.net/dreamstone/archive/2007/04/30/114824.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐, 源码搜索</title><link>http://www.blogjava.net/dreamstone/archive/2007/02/22/100364.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Thu, 22 Feb 2007 11:00:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/02/22/100364.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/100364.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/02/22/100364.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/100364.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/100364.html</trackback:ping><description><![CDATA[一个挺有意思的网站，能搜索源代码，类似google的收录网页进行搜索，这个是收录源代码进行搜索，另外还有eclipse插件，可以试试挺好玩。<a href="http://www.koders.com/">http://www.koders.com/</a><br>
<img src ="http://www.blogjava.net/dreamstone/aggbug/100364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-02-22 19:00 <a href="http://www.blogjava.net/dreamstone/archive/2007/02/22/100364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过Eclipse插件Bytecode Outline方便了解Java字节码</title><link>http://www.blogjava.net/dreamstone/archive/2007/02/22/100358.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Thu, 22 Feb 2007 10:44:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/02/22/100358.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/100358.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/02/22/100358.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/100358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/100358.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Eclipse, 编译, 反编译, 字节码, 插件 ,Bytecode Outline,asm&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/02/22/100358.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/100358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-02-22 18:44 <a href="http://www.blogjava.net/dreamstone/archive/2007/02/22/100358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse中最常用的热键</title><link>http://www.blogjava.net/dreamstone/archive/2007/02/08/98706.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Thu, 08 Feb 2007 03:41:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/02/08/98706.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/98706.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/02/08/98706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/98706.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/98706.html</trackback:ping><description><![CDATA[<p>Eclipse中最常用的热键:</p>
<p>1,Ctrl+D &nbsp;&nbsp;&nbsp;&nbsp;删除选中的几行<br>2,Alt+上下箭头 &nbsp;&nbsp;&nbsp;移动选中的代码块<br>3,Alt+左右箭头&nbsp;&nbsp;&nbsp;回退 前进<br>4,Alt+Shift+上下箭头 &nbsp;&nbsp;复制选中的代码块<br>5,sysout+Ctrl space&nbsp;&nbsp;&nbsp;&nbsp; 生成System.out.println();<br>6,main + Ctrl space&nbsp;&nbsp;&nbsp;&nbsp; 生成最简单的main函数<br>7,Ctrl+Shift+X&nbsp;&nbsp;&nbsp;切换成大写<br>8,Ctrl+Shift+Y&nbsp;&nbsp;&nbsp;切换成小写<br>9,Ctrl+Z&nbsp;&nbsp;&nbsp;&nbsp;取消undo<br>10,Ctrl+Y&nbsp;&nbsp;&nbsp;&nbsp;redo<br>11,Ctrl+S&nbsp;&nbsp;&nbsp;&nbsp;保存<br>12,Tab&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;块缩进<br>13,Shift+Tab&nbsp;&nbsp;&nbsp;反向块缩进<br>14,Ctrl+Shif+F&nbsp;&nbsp;&nbsp;格式化代码<br>15,Ctrl+O&nbsp;&nbsp;&nbsp;&nbsp;显示成员方法 ,成员对象<br>16,Ctrl+Shift+I &nbsp;&nbsp;调试的时候显示对象的值<br>17,Ctrl+M&nbsp;&nbsp;&nbsp;&nbsp;全屏<br>18,Ctrl+N&nbsp;&nbsp;&nbsp;&nbsp;新建<br>19,Ctrl+L&nbsp;&nbsp;&nbsp;&nbsp;进入到第N行<br>20,Ctrl+/&nbsp;&nbsp;&nbsp;&nbsp;注释打开代码<br>21,Ctrl+Shift+/&nbsp;&nbsp;&nbsp;块注释<br>22,Ctrl+Shift+\&nbsp;&nbsp;&nbsp;块注释取消<br>23,Ctrl+1&nbsp;&nbsp;&nbsp;&nbsp;纠正代码<br>24,F3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;显示继承树<br>25,Ctrl+F&nbsp;&nbsp;&nbsp;&nbsp;查找替换<br>26,Ctrl+H&nbsp;&nbsp;&nbsp;&nbsp;更大范围的查找替换<br>27,F5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Step into<br>28,F6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Step over<br>29,F7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Step return<br>30,F8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resume</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/98706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-02-08 11:41 <a href="http://www.blogjava.net/dreamstone/archive/2007/02/08/98706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用IText打印PDF</title><link>http://www.blogjava.net/dreamstone/archive/2007/01/29/96468.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 29 Jan 2007 03:55:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/01/29/96468.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/96468.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/01/29/96468.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/96468.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/96468.html</trackback:ping><description><![CDATA[IText是开源的，对与打印PDF做的还不错，下边一个例子关于IText的，列出了大部份常用的功能。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.FileOutputStream;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.Cell;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.Document;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.Font;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.PageSize;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.Paragraph;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.Table;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.pdf.BaseFont;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.lowagie.text.pdf.PdfWriter;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_328_2692_Open_Image onclick="this.style.display='none'; Codehighlighter1_328_2692_Open_Text.style.display='none'; Codehighlighter1_328_2692_Closed_Image.style.display='inline'; Codehighlighter1_328_2692_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_328_2692_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_328_2692_Closed_Text.style.display='none'; Codehighlighter1_328_2692_Open_Image.style.display='inline'; Codehighlighter1_328_2692_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Example&nbsp;</span><span id=Codehighlighter1_328_2692_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_328_2692_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Font&nbsp;FONT_11;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;BaseFont&nbsp;msgothic;<br><img id=Codehighlighter1_451_1183_Open_Image onclick="this.style.display='none'; Codehighlighter1_451_1183_Open_Text.style.display='none'; Codehighlighter1_451_1183_Closed_Image.style.display='inline'; Codehighlighter1_451_1183_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_451_1183_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_451_1183_Closed_Text.style.display='none'; Codehighlighter1_451_1183_Open_Image.style.display='inline'; Codehighlighter1_451_1183_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception</span><span id=Codehighlighter1_451_1183_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_451_1183_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_458_649_Open_Image onclick="this.style.display='none'; Codehighlighter1_458_649_Open_Text.style.display='none'; Codehighlighter1_458_649_Closed_Image.style.display='inline'; Codehighlighter1_458_649_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_458_649_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_458_649_Closed_Text.style.display='none'; Codehighlighter1_458_649_Open_Image.style.display='inline'; Codehighlighter1_458_649_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span id=Codehighlighter1_458_649_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_458_649_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">定义字体</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msgothic&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;BaseFont.createFont(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">D:\\workspace\\UseIText\\MSMINCHO.TTC,0</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FONT_11</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Font(msgothic);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FONT_11.setSize(</span><span style="COLOR: #000000">11</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_668_696_Open_Image onclick="this.style.display='none'; Codehighlighter1_668_696_Open_Text.style.display='none'; Codehighlighter1_668_696_Closed_Image.style.display='inline'; Codehighlighter1_668_696_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_668_696_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_668_696_Closed_Text.style.display='none'; Codehighlighter1_668_696_Open_Image.style.display='inline'; Codehighlighter1_668_696_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(Exception&nbsp;e)</span><span id=Codehighlighter1_668_696_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_668_696_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">为了测试方便，加入自动关闭打开acrord32</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.getRuntime().exec(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">tskill&nbsp;acrord32</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).waitFor();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Document&nbsp;document</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Document(PageSize.A4.rotate());<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">写文件</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PdfWriter&nbsp;writer</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">PdfWriter.getInstance(document,&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;FileOutputStream(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">d:/temp.pdf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.open();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makeDocument(document);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.close();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">为了测试方便，加入自动关闭打开acrord32</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.getRuntime().exec(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c:\\Program&nbsp;Files\\Adobe\\Acrobat&nbsp;</span><span style="COLOR: #000000">7.0</span><span style="COLOR: #000000">\\Reader\\acrord32.exe\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;d:/temp.pdf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).waitFor();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1252_1845_Open_Image onclick="this.style.display='none'; Codehighlighter1_1252_1845_Open_Text.style.display='none'; Codehighlighter1_1252_1845_Closed_Image.style.display='inline'; Codehighlighter1_1252_1845_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1252_1845_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1252_1845_Closed_Text.style.display='none'; Codehighlighter1_1252_1845_Open_Image.style.display='inline'; Codehighlighter1_1252_1845_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;makeDocument(Document&nbsp;document)</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception</span><span id=Codehighlighter1_1252_1845_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1252_1845_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">table大部份操做类似与html,下边是一些常用的参数<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">3是总的列数，也可以同时指定行数和列数new&nbsp;Table(3,4)</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Table&nbsp;table</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Table(</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">table的宽度</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setWidth(</span><span style="COLOR: #000000">98</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">类似html的cellSpaceing</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setSpacing(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">每一列的宽度，是比例不是固定宽度</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_1483_1492_Open_Image onclick="this.style.display='none'; Codehighlighter1_1483_1492_Open_Text.style.display='none'; Codehighlighter1_1483_1492_Closed_Image.style.display='inline'; Codehighlighter1_1483_1492_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1483_1492_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1483_1492_Closed_Text.style.display='none'; Codehighlighter1_1483_1492_Open_Image.style.display='inline'; Codehighlighter1_1483_1492_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setWidths(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">[]</span><span id=Codehighlighter1_1483_1492_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1483_1492_Open_Text><span style="COLOR: #000000">{</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">30</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">60</span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">对齐方式</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setAlignment(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">CENTER</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">table是否有边框</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setBorder(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">cell默认是否有边框</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setDefaultCellBorder(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">自动填充空白</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.setAutoFillEmptyCells(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;<br><img id=Codehighlighter1_1705_1732_Open_Image onclick="this.style.display='none'; Codehighlighter1_1705_1732_Open_Text.style.display='none'; Codehighlighter1_1705_1732_Closed_Image.style.display='inline'; Codehighlighter1_1705_1732_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1705_1732_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1705_1732_Closed_Text.style.display='none'; Codehighlighter1_1705_1732_Open_Image.style.display='inline'; Codehighlighter1_1705_1732_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">n;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_1705_1732_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1705_1732_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makeContent(table);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">新的一页要加上这句</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.newPage();<br><img id=Codehighlighter1_1792_1819_Open_Image onclick="this.style.display='none'; Codehighlighter1_1792_1819_Open_Text.style.display='none'; Codehighlighter1_1792_1819_Closed_Image.style.display='inline'; Codehighlighter1_1792_1819_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1792_1819_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1792_1819_Closed_Text.style.display='none'; Codehighlighter1_1792_1819_Open_Image.style.display='inline'; Codehighlighter1_1792_1819_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">n;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_1792_1819_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1792_1819_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makeContent(table);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.add(table);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1909_2149_Open_Image onclick="this.style.display='none'; Codehighlighter1_1909_2149_Open_Text.style.display='none'; Codehighlighter1_1909_2149_Closed_Image.style.display='inline'; Codehighlighter1_1909_2149_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1909_2149_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1909_2149_Closed_Text.style.display='none'; Codehighlighter1_1909_2149_Open_Image.style.display='inline'; Codehighlighter1_1909_2149_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;makeContent(Table&nbsp;table)</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000">&nbsp;Exception&nbsp;</span><span id=Codehighlighter1_1909_2149_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1909_2149_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;len&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;table.columns();<br><img id=Codehighlighter1_1964_2146_Open_Image onclick="this.style.display='none'; Codehighlighter1_1964_2146_Open_Text.style.display='none'; Codehighlighter1_1964_2146_Closed_Image.style.display='inline'; Codehighlighter1_1964_2146_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1964_2146_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1964_2146_Closed_Text.style.display='none'; Codehighlighter1_1964_2146_Open_Image.style.display='inline'; Codehighlighter1_1964_2146_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">len;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_1964_2146_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1964_2146_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;testStr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">xxxxxxxxxxxxxxxxxxxxxx</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cell&nbsp;cell</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Cell(testStr);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">max&nbsp;lines&nbsp;，设置成1防止换行，配合cell宽度，可以实现自动截取</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell.setMaxLines(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.addCell(cell);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">构造一个自定义的cell</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_2244_2690_Open_Image onclick="this.style.display='none'; Codehighlighter1_2244_2690_Open_Text.style.display='none'; Codehighlighter1_2244_2690_Closed_Image.style.display='inline'; Codehighlighter1_2244_2690_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2244_2690_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2244_2690_Closed_Text.style.display='none'; Codehighlighter1_2244_2690_Open_Image.style.display='inline'; Codehighlighter1_2244_2690_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;Cell&nbsp;makeCell(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;colspan,String&nbsp;align,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;maxLines,Font&nbsp;font)</span><span id=Codehighlighter1_2244_2690_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_2244_2690_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cell&nbsp;cell&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Paragraph&nbsp;paragraph&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img id=Codehighlighter1_2300_2625_Open_Image onclick="this.style.display='none'; Codehighlighter1_2300_2625_Open_Text.style.display='none'; Codehighlighter1_2300_2625_Closed_Image.style.display='inline'; Codehighlighter1_2300_2625_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2300_2625_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2300_2625_Closed_Text.style.display='none'; Codehighlighter1_2300_2625_Open_Image.style.display='inline'; Codehighlighter1_2300_2625_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span id=Codehighlighter1_2300_2625_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_2300_2625_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">使用自定义字体</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;paragraph</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Paragraph(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">testxxx</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,font);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Cell(paragraph);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置colspan,同样的方法可以设置rowspan</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_2437_2472_Open_Image onclick="this.style.display='none'; Codehighlighter1_2437_2472_Open_Text.style.display='none'; Codehighlighter1_2437_2472_Closed_Image.style.display='inline'; Codehighlighter1_2437_2472_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2437_2472_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2437_2472_Closed_Text.style.display='none'; Codehighlighter1_2437_2472_Open_Image.style.display='inline'; Codehighlighter1_2437_2472_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(colspan&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_2437_2472_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_2437_2472_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell.setColspan(colspan);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置对齐</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_2529_2574_Open_Image onclick="this.style.display='none'; Codehighlighter1_2529_2574_Open_Text.style.display='none'; Codehighlighter1_2529_2574_Closed_Image.style.display='inline'; Codehighlighter1_2529_2574_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2529_2574_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2529_2574_Closed_Text.style.display='none'; Codehighlighter1_2529_2574_Open_Image.style.display='inline'; Codehighlighter1_2529_2574_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((align&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">align.equals(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">)))</span><span id=Codehighlighter1_2529_2574_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_2529_2574_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell.setHorizontalAlignment(align);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置maxlines</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell.setMaxLines(maxLines);<br><img id=Codehighlighter1_2644_2672_Open_Image onclick="this.style.display='none'; Codehighlighter1_2644_2672_Open_Text.style.display='none'; Codehighlighter1_2644_2672_Closed_Image.style.display='inline'; Codehighlighter1_2644_2672_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2644_2672_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2644_2672_Closed_Text.style.display='none'; Codehighlighter1_2644_2672_Open_Image.style.display='inline'; Codehighlighter1_2644_2672_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(Exception&nbsp;e)</span><span id=Codehighlighter1_2644_2672_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_2644_2672_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;cell;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/96468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-01-29 11:55 <a href="http://www.blogjava.net/dreamstone/archive/2007/01/29/96468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4J的一些小技巧和使用中一些须要注意的问题。</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/29/84391.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 29 Nov 2006 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/29/84391.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/84391.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/29/84391.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/84391.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/84391.html</trackback:ping><description><![CDATA[<p><br>一、为多个项目指定使用哪个log4j文件<br>情况一：多个小项目合成一个大项目，多个小项目有自己不同的入口，这个时候如果使用同一个log4j文件，各个项目的输<br>出会混乱在一起，如果拆分成多个小项目，看起来又比较散不太好管理。<br>情况二：一个项目实施在linux上，编写在windows上,log4j的输出目录/opt/xxx/web.log<br>这个时候开发者被迫必须在本机的workspace所在的目录加入一个opt/xxx/web.log的目录和文件<br>同时，大多数情况下linux上的服务是不须要输出log到Console，只要输出到文件<br>而windows大部份是只须要输出到console，不须要输出到文件<br>本地调试的时候log4j的级别多是debug ,而实际实施的时候多是之上的级别<br>造成须要不停的修改log4j的属性文件,cvs同步的时候不停的提示<br>也许你说可以整个项目完成再来写log4j的属性文件，但有的时候这个效果并不好。<br>因为还有这种时候，项目完成（包括log），反复测试的这段时间。</p>
<p>解决：解决办法很简单，建立一个log4j的配制文件的目录，在这个目录下为每个小项目建立一个目录，<br>每个目录下放着自己的log4j配制,然後把这些目录作为每个小工程的classpath的第一个，ok上边的问题就<br>解决了。这个时候可以写一个log4j放在src下，用来开发时候调试用，而真正服务器上使用的都在各自的文件夹下</p>
<p>二,为默写包，某些类定义不同的log4j级别<br>是否想过这中需求呢，一个项目调试的时候，希望其中默写包不打出log信息。<br>比如struts的包，spring的包，还有你引用的别人已经开发好包，或者你自己写的类，但是你不想看到这个<br>类的log信息.但是你须要调试当前的一些class，log级别必须设置在debug级别<br>这个时候可以在log4j的属性文件中加入如下内容:<br>log4j.logger.包名or类名=高的级别<br>例如:<br>log4j.logger.org.springframework=error</p>
<p>三、注意事项<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img id=Codehighlighter1_21_63_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_63_Open_Text.style.display='none'; Codehighlighter1_21_63_Closed_Image.style.display='inline'; Codehighlighter1_21_63_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_21_63_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_63_Closed_Text.style.display='none'; Codehighlighter1_21_63_Open_Image.style.display='inline'; Codehighlighter1_21_63_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;execute()</span> <span id=Codehighlighter1_21_63_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_21_63_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/dot.gif">..</span> <span style="COLOR: #008000"><br></span><span style="COLOR: #008080">3</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top> </span><span style="COLOR: #000000">&nbsp;logger.debug(</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">aa</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">+</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">bb</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">+</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">cc</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">5</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span></div>
<p><br>是否这么写过呢？这样写是有些问题的。当你把log级别调整到info或者更高的时候，log信息是不输出了<br>但是字符串的拼接一样进行了，使你的程序效率降低，实验一下<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img id=Codehighlighter1_21_61_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_61_Open_Text.style.display='none'; Codehighlighter1_21_61_Closed_Image.style.display='inline'; Codehighlighter1_21_61_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_21_61_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_61_Closed_Text.style.display='none'; Codehighlighter1_21_61_Open_Image.style.display='inline'; Codehighlighter1_21_61_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;execute()</span> <span id=Codehighlighter1_21_61_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_21_61_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/dot.gif">..</span> <span style="COLOR: #008000"><br></span><span style="COLOR: #008080">3</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top> </span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(getStr());<br></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">5</span> <span style="COLOR: #000000"><img id=Codehighlighter1_85_130_Open_Image onclick="this.style.display='none'; Codehighlighter1_85_130_Open_Text.style.display='none'; Codehighlighter1_85_130_Closed_Image.style.display='inline'; Codehighlighter1_85_130_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_85_130_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_85_130_Closed_Text.style.display='none'; Codehighlighter1_85_130_Open_Image.style.display='inline'; Codehighlighter1_85_130_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> </span><span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;String&nbsp;getStr()</span> <span id=Codehighlighter1_85_130_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_85_130_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">6</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">execute&nbsp;getStr</span> <span style="COLOR: #000000">"</span> <span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">7</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">8</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span></div>
<p><br>调整log4j属性文件级别到info 结果getStr()照样执行了<br>解决办法：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img id=Codehighlighter1_21_102_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_102_Open_Text.style.display='none'; Codehighlighter1_21_102_Closed_Image.style.display='inline'; Codehighlighter1_21_102_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_21_102_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_102_Closed_Text.style.display='none'; Codehighlighter1_21_102_Open_Image.style.display='inline'; Codehighlighter1_21_102_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;execute()</span> <span id=Codehighlighter1_21_102_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_21_102_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/dot.gif">.</span> <span style="COLOR: #008000"><br></span><span style="COLOR: #008080">3</span> <span style="COLOR: #008000"><img id=Codehighlighter1_62_100_Open_Image onclick="this.style.display='none'; Codehighlighter1_62_100_Open_Text.style.display='none'; Codehighlighter1_62_100_Closed_Image.style.display='inline'; Codehighlighter1_62_100_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_62_100_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_62_100_Closed_Text.style.display='none'; Codehighlighter1_62_100_Open_Image.style.display='inline'; Codehighlighter1_62_100_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top> </span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000">(logger.isDebugEnabled())</span> <span id=Codehighlighter1_62_100_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_62_100_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(getStr());<br></span><span style="COLOR: #008080">5</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">6</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">7</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span></div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/84391.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-29 17:33 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/29/84391.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVN 的Local Repository的使用和学习使用SVN的索引</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/28/83940.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 27 Nov 2006 17:28:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/28/83940.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/83940.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/28/83940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/83940.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/83940.html</trackback:ping><description><![CDATA[
		<p>最近在同事的建议下，看了一下SVN的一些东西，感觉不错，下边是看完后发现的一些比较好的文章，这里提供一个索引，便于大家学习，另说说SVN的本地<br />一，索引:<br />SVN官方网站：<a href="http://subversion.tigris.org/">http://subversion.tigris.org/</a><br />SVN中文官方网站：<a href="http://subversion.tigris.org.cn/">http://subversion.tigris.org.cn/</a><br />SVN和其它版本控制软件的比较：<a href="http://robinlet.bokee.com/2866408.html">http://robinlet.bokee.com/2866408.html</a><br />如何从CVS过渡到SVN:<a href="http://cvs2svn.tigris.org/">http://cvs2svn.tigris.org/</a><br />SVN的客户端:<a href="http://tortoisesvn.tigris.org/">http://tortoisesvn.tigris.org<br /></a>SVN的Eclipse集成：建议直接从官方网站直接update<br /><br />二，平时是否经常会自己写一些东西呢，或者为了兴趣，或者为了测试某些东西，这些东西不知道那天就用的到，如果不小心丢了挺可惜的，而且过程有时也很重要。这个时候，使用一个版本控制软件是好的选择，但是哪个更好用呢，这里介绍一下SVN的本地方式，个人感觉很好用:<br />1,安装本地SVN:<br />到这里:<a href="http://tortoisesvn.tigris.org/">http://tortoisesvn.tigris.org</a>下载SVN的客户端<u><font color="#0000ff">tortoisesvn</font></u>，然後安装，完成后重起，他就自动集成到Windows的资源管理器中了，如图所示这个时候本地SVN就安装完了，是否很简单呢<br /><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_01.png" /><br /><br />2，使用SVN:<br />建立Local Repository,在你想保存SVN版本控制文件的地方右键，如图选择<br /><br /><font size="4"><img height="400" alt="svn.JPG" src="http://www.blogjava.net/images/blogjava_net/dreamstone/svn.JPG" width="640" border="0" /><br />完成后，你就可以尝试添加工程:<br />对话框内填入的目录是你刚才选择的存放版本文件的目录<br /><img height="400" alt="svn2.JPG" src="http://www.blogjava.net/images/blogjava_net/dreamstone/svn2.JPG" width="640" border="0" /><br />好了，换一个文件夹，尝试checkout,更改，提交，对比等功能吧,基本和cvs使用差不多，但是增加了原子递交等功能.<br />3,可以安装了eclipse的插件，这样使用起来会更方便些</font></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/83940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-28 01:28 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/28/83940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mysql 基本知识和phpMyAdmin的配制Faq</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/24/83351.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 24 Nov 2006 11:02:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/24/83351.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/83351.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/24/83351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/83351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/83351.html</trackback:ping><description><![CDATA[
		<p>平时都是在用oracle，这次做项目开始用mysql，写一下mysql的一些基本知识和phpMyAdmin的配制Faq<br />一,mysql的常用操做<br />1.导出整个数据库<br />　　mysqldump -u 用户名 -p 数据库名 &gt; 导出的文件名<br />　　mysqldump -u wcnc -p smgp_apps_wcnc &gt; wcnc.sql<br />2.导出一个表<br />　　mysqldump -u 用户名 -p 数据库名 表名&gt; 导出的文件名<br />　　mysqldump -u wcnc -p smgp_apps_wcnc users&gt; wcnc_users.sql<br />3.导出一个数据库结构<br />　　mysqldump -u wcnc -p -d --add-drop-table smgp_apps_wcnc &gt;d:\wcnc_db.sql<br />　　-d 没有数据 --add-drop-table 在每个create语句之前增加一个drop table<br />4.导入数据库<br />　　常用source 命令<br />　　进入mysql数据库控制台，<br />　　如mysql -u root -p<br />　　mysql&gt;use 数据库<br />　　然后使用source命令，后面参数为脚本文件(如这里用到的.sql)<br />　　mysql&gt;source d:\wcnc_db.sql<br />5,更改mysql数据库的编码<br /> /etc/my.cnf 加入<br /> default-character-set=utf8<br />二,mysql的常见问题<br />1,能本机登陆，不能远程登陆<br />mysql的系统数据库是mysql，里边有一个表user,user表的一个字段host，决定了能在什么地方访问mysql<br /> localhost代表本机 <br /> %代表任何机器<br /> 如果你想在远程使用root，同时还要给本机的一些服务提供使用，那么可以建立两个root用户<br />三,phpMyAdmin的配制<br />虽然还有一些工具也很好用，但是phpMyAdmin无疑是其中的佼佼者，至少使用人数上是，安装网上有很多，<br />这里写一下安装过程中常遇到的问题和解决办法.<br />1,不能加载mysql扩展<br />须要安装一个类似php-mysql的包。<br />2,每次进入要求登陆,加上这两句:<br />$cfg['Servers'][$i]['user'] = 'username';<br />$cfg['Servers'][$i]['password'] = 'password';<br />3,一些页面的下方提示sql语句错误<br />原因：没有导入数据库<br />找到你的phpMyAdmin的目录，里边有个script目录，导入里边的脚本。create_tables.sql<br />mysql版本高的话导入另一个create_tables_mysql_4_1_2+.sql<br />解决办法 mysql -u root -p <br />mysql&gt; source create_tables.sql</p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/83351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-24 19:02 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/24/83351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Native2Ascii的JavaScript实现 (便于平时使用)</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/20/82185.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 20 Nov 2006 02:46:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/20/82185.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/82185.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/20/82185.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/82185.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/82185.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Native2Ascii  Javascript&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2006/11/20/82185.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/82185.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-20 10:46 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/20/82185.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两个简单的makefile</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71414.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:49:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71414.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71414.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71414.html</trackback:ping><description><![CDATA[
		<p>一：<br />case = case1<br />all:${case}<br />#test wildcard ,patsubst<br />#source := $(wildcard *.c) $(wildcard *.cc)<br />source := $(wildcard *.c)<br />#objs := $(patsubst %.c,%.o,$(patsubst %.cc %.o,$(source)))<br />objs := $(patsubst %.c,%.o,$(source))<br />kobjs := $(filter k%.o,$(objs))<br />mobjs := $(filter m%.o,$(objs))<br />case1:$(objs)<br />        cc -o mdis $(mobjs)<br />        cc -o kdis $(kobjs)<br />        rm *.o<br />$(objs):%.o:%.c<br />        $(CC) -c $(CFLAGS) $&lt; -o $@</p>
		<p>二：<br />case = case1<br />all:${case}<br />#test wildcard ,patsubst<br />#source := $(wildcard *.c) $(wildcard *.cc)<br />source := $(wildcard *.c)<br />#objs := $(patsubst %.c,%.o,$(patsubst %.cc %.o,$(source)))<br />objs := $(patsubst %.c,%.o,$(source))<br />case1:$(objs)<br />        cc -o dis $(objs)<br />        rm *.o<br />$(objs):%.o:%.c<br />        $(CC) -c $(CFLAGS) $&lt; -o $@<br /></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:49 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起学make十四</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71412.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:38:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71412.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71412.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71412.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71412.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71412.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Courier New" size="4">
						<strong>使用make更新函数库文件<br />———————————</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">函数库文件也就是对Object文件（程序编译的中间文件）的打包文件。在Unix下，一般是由命令"ar"来完成打包工作。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>一、函数库文件的成员</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">一个函数库文件由多个文件组成。你可以以如下格式指定函数库文件及其组成：</font>
		</p>
		<p>
				<font face="Courier New">    archive(member)</font>
		</p>
		<p>
				<font face="Courier New">这个不是一个命令，而一个目标和依赖的定义。一般来说，这种用法基本上就是为了"ar"命令来服务的。如：</font>
		</p>
		<p>
				<font face="Courier New">    foolib(hack.o) : hack.o<br />            ar cr foolib hack.o</font>
		</p>
		<p>
				<font face="Courier New">如果要指定多个member，那就以空格分开，如：</font>
		</p>
		<p>
				<font face="Courier New">    foolib(hack.o kludge.o)</font>
		</p>
		<p>
				<font face="Courier New">其等价于：</font>
		</p>
		<p>
				<font face="Courier New">    foolib(hack.o) foolib(kludge.o)</font>
		</p>
		<p>
				<font face="Courier New">你还可以使用Shell的文件通配符来定义，如：</font>
		</p>
		<p>
				<font face="Courier New">    foolib(*.o)</font>
		</p>
		<p>
				<br />
				<font face="Courier New">
						<strong>二、函数库成员的隐含规则</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">当make搜索一个目标的隐含规则时，一个特殊的特性是，如果这个目标是"a(m)"形式的，其会把目标变成"(m)"。于是，如果我们的成员是"%.o"的模式定义，并且如果我们使用"make foo.a(bar.o)"的形式调用Makefile时，隐含规则会去找"bar.o"的规则，如果没有定义bar.o的规则，那么内建隐含规则生效，make会去找bar.c文件来生成bar.o，如果找得到的话，make执行的命令大致如下：</font>
		</p>
		<p>
				<font face="Courier New">    cc -c bar.c -o bar.o<br />    ar r foo.a bar.o<br />    rm -f bar.o</font>
		</p>
		<p>
				<font face="Courier New">还有一个变量要注意的是"$%"，这是专属函数库文件的自动化变量，有关其说明请参见"自动化变量"一节。</font>
		</p>
		<p>
				<br />
				<font face="Courier New">
						<strong>三、函数库文件的后缀规则</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">你可以使用"后缀规则"和"隐含规则"来生成函数库打包文件，如：</font>
		</p>
		<p>
				<font face="Courier New">    .c.a:<br />            $(CC) $(CFLAGS) $(CPPFLAGS) -c $&lt; -o $*.o<br />            $(AR) r $@ $*.o<br />            $(RM) $*.o</font>
		</p>
		<p>
				<font face="Courier New">其等效于：</font>
		</p>
		<p>
				<font face="Courier New">    (%.o) : %.c<br />            $(CC) $(CFLAGS) $(CPPFLAGS) -c $&lt; -o $*.o<br />            $(AR) r $@ $*.o<br />            $(RM) $*.o</font>
		</p>
		<p>
				<br />
				<font face="Courier New">
						<strong>四、注意事项</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">在进行函数库打包文件生成时，请小心使用make的并行机制（"-j"参数）。如果多个ar命令在同一时间运行在同一个函数库打包文件上，就很有可以损坏这个函数库文件。所以，在make未来的版本中，应该提供一种机制来避免并行操作发生在函数打包文件上。</font>
		</p>
		<p>
				<font face="Courier New">但就目前而言，你还是应该不要尽量不要使用"-j"参数。</font>
		</p>
		<p>
				<font face="Courier New">
				</font> </p>
		<p>
				<font face="Courier New" size="4">
						<strong>后序<br />——</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">终于到写结束语的时候了，以上基本上就是GNU make的Makefile的所有细节了。其它的产商的make基本上也就是这样的，无论什么样的make，都是以文件的依赖性为基础的，其基本是都是遵循一个标准的。这篇文档中80%的技术细节都适用于任何的make，我猜测"函数"那一章的内容可能不是其它make所支持的，而隐含规则方面，我想不同的make会有不同的实现，我没有精力来查看GNU的make和VC的nmake、BCB的make，或是别的UNIX下的make有些什么样的差别，一是时间精力不够，二是因为我基本上都是在Unix下使用make，以前在SCO Unix和IBM的AIX，现在在Linux、Solaris、HP-UX、AIX和Alpha下使用，Linux和Solaris下更多一点。不过，我可以肯定的是，在Unix下的make，无论是哪种平台，几乎都使用了Richard Stallman开发的make和cc/gcc的编译器，而且，基本上都是GNU的make（公司里所有的UNIX机器上都被装上了GNU的东西，所以，使用GNU的程序也就多了一些）。GNU的东西还是很不错的，特别是使用得深了以后，越来越觉得GNU的软件的强大，也越来越觉得GNU的在操作系统中（主要是Unix，甚至Windows）"杀伤力"。</font>
		</p>
		<p>
				<font face="Courier New">对于上述所有的make的细节，我们不但可以利用make这个工具来编译我们的程序，还可以利用make来完成其它的工作，因为规则中的命令可以是任何Shell之下的命令，所以，在Unix下，你不一定只是使用程序语言的编译器，你还可以在Makefile中书写其它的命令，如：tar、awk、mail、sed、cvs、compress、ls、rm、yacc、rpm、ftp……等等，等等，来完成诸如"程序打包"、"程序备份"、"制作程序安装包"、"提交代码"、"使用程序模板"、"合并文件"等等五花八门的功能，文件操作，文件管理，编程开发设计，或是其它一些异想天开的东西。比如，以前在书写银行交易程序时，由于银行的交易程序基本一样，就见到有人书写了一些交易的通用程序模板，在该模板中把一些网络通讯、数据库操作的、业务操作共性的东西写在一个文件中，在这些文件中用些诸如"@@@N、###N"奇怪字串标注一些位置，然后书写交易时，只需按照一种特定的规则书写特定的处理，最后在make时，使用awk和sed，把模板中的"@@@N、###N"等字串替代成特定的程序，形成C文件，然后再编译。这个动作很像数据库的"扩展C"语言（即在C语言中用"EXEC　SQL"的样子执行SQL语句，在用cc/gcc编译之前，需要使用"扩展C"的翻译程序，如cpre，把其翻译成标准C）。如果你在使用make时有一些更为绝妙的方法，请记得告诉我啊。</font>
		</p>
		<font face="Courier New">
				<p class="CourierNew" style="MARGIN: 0cm 0cm 0pt">
				</p>
		</font>
		<font face="Courier New">
				<strong>
				</strong> </font>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:38 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转) 跟我一起写 Makefile（十三）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71411.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:34:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71411.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71411.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71411.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71411.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2898</p>
				<p>
						<br />
						<strong>
								<font face="Courier New">五、定义模式规则</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">你可以使用模式规则来定义一个隐含规则。一个模式规则就好像一个一般的规则，只是在规则中，目标的定义需要有"%"字符。"%"的意思是表示一个或多个任意字符。在依赖目标中同样可以使用"%"，只是依赖目标中的"%"的取值，取决于其目标。</font>
				</p>
				<p>
						<font face="Courier New">有一点需要注意的是，"%"的展开发生在变量和函数的展开之后，变量和函数的展开发生在make载入Makefile时，而模式规则中的"%"则发生在运行时。</font>
				</p>
				<p>
						<br />
						<strong>
								<font face="Courier New">1、模式规则介绍</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">模式规则中，至少在规则的目标定义中要包含"%"，否则，就是一般的规则。目标中的"%"定义表示对文件名的匹配，"%"表示长度任意的非空字符串。例如："%.c"表示以".c"结尾的文件名（文件名的长度至少为3），而"s.%.c"则表示以"s."开头，".c"结尾的文件名（文件名的长度至少为5）。</font>
				</p>
				<p>
						<font face="Courier New">如果"%"定义在目标中，那么，目标中的"%"的值决定了依赖目标中的"%"的值，也就是说，目标中的模式的"%"决定了依赖目标中"%"的样子。例如有一个模式规则如下：</font>
				</p>
				<p>
						<font face="Courier New">    %.o : %.c ; &lt;command ......&gt;</font>
				</p>
				<p>
						<font face="Courier New">其含义是，指出了怎么从所有的[.c]文件生成相应的[.o]文件的规则。如果要生成的目标是"a.o b.o"，那么"%c"就是"a.c b.c"。</font>
				</p>
				<p>
						<font face="Courier New">一旦依赖目标中的"%"模式被确定，那么，make会被要求去匹配当前目录下所有的文件名，一旦找到，make就会规则下的命令，所以，在模式规则中，目标可能会是多个的，如果有模式匹配出多个目标，make就会产生所有的模式目标，此时，make关心的是依赖的文件名和生成目标的命令这两件事。</font>
				</p>
				<p>
						<br />
						<strong>
								<font face="Courier New">2、模式规则示例</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">下面这个例子表示了,把所有的[.c]文件都编译成[.o]文件.</font>
				</p>
				<p>
						<font face="Courier New">    %.o : %.c<br />            $(CC) -c $(CFLAGS) $(CPPFLAGS) $&lt; -o $@</font>
				</p>
				<p>
						<font face="Courier New">其中，"$@"表示所有的目标的挨个值，"$&lt;"表示了所有依赖目标的挨个值。这些奇怪的变量我们叫"自动化变量"，后面会详细讲述。</font>
				</p>
				<p>
						<font face="Courier New">下面的这个例子中有两个目标是模式的：</font>
				</p>
				<p>
						<font face="Courier New">    %.tab.c %.tab.h: %.y<br />            bison -d $&lt;</font>
				</p>
				<p>
						<font face="Courier New">这条规则告诉make把所有的[.y]文件都以"bison -d &lt;n&gt;.y"执行，然后生成"&lt;n&gt;.tab.c"和"&lt;n&gt;.tab.h"文件。（其中，"&lt;n&gt;"表示一个任意字符串）。如果我们的执行程序"foo"依赖于文件"parse.tab.o"和"scan.o"，并且文件"scan.o"依赖于文件"parse.tab.h"，如果"parse.y"文件被更新了，那么根据上述的规则，"bison -d parse.y"就会被执行一次，于是，"parse.tab.o"和"scan.o"的依赖文件就齐了。（假设，"parse.tab.o"由"parse.tab.c"生成，和"scan.o"由"scan.c"生成，而"foo"由"parse.tab.o"和"scan.o"链接生成，而且foo和其[.o]文件的依赖关系也写好，那么，所有的目标都会得到满足）</font>
				</p>
				<p>
						<br />
						<strong>
								<font face="Courier New">3、自动化变量</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">在上述的模式规则中，目标和依赖文件都是一系例的文件，那么我们如何书写一个命令来完成从不同的依赖文件生成相应的目标？因为在每一次的对模式规则的解析时，都会是不同的目标和依赖文件。</font>
				</p>
				<p>
						<font face="Courier New">自动化变量就是完成这个功能的。在前面，我们已经对自动化变量有所提涉，相信你看到这里已对它有一个感性认识了。所谓自动化变量，就是这种变量会把模式中所定义的一系列的文件自动地挨个取出，直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。</font>
				</p>
				<p>
						<font face="Courier New">下面是所有的自动化变量及其说明：</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$@</strong>
								<br />    表示规则中的目标文件集。在模式规则中，如果有多个目标，那么，"$@"就是匹配于目标中模式定义的集合。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$%</strong>
								<br />    仅当目标是函数库文件中，表示规则中的目标成员名。例如，如果一个目标是"foo.a(bar.o)"，那么，"$%"就是"bar.o"，"$@"就是"foo.a"。如果目标不是函数库文件（Unix下是[.a]，Windows下是[.lib]），那么，其值为空。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$&lt;</strong>
								<br />    依赖目标中的第一个目标名字。如果依赖目标是以模式（即"%"）定义的，那么"$&lt;"将是符合模式的一系列的文件集。注意，其是一个一个取出来的。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$?</strong>
								<br />    所有比目标新的依赖目标的集合。以空格分隔。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$^</strong>
								<br />    所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的，那个这个变量会去除重复的依赖目标，只保留一份。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$+</strong>
								<br />    这个变量很像"$^"，也是所有依赖目标的集合。只是它不去除重复的依赖目标。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$*</strong>
								<br />   这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b"，并且目标的模式是"a.%.b"，那么，"$*"的值就是"dir/a.foo"。这个变量对于构造有关联的文件名是比较有较。如果目标中没有模式的定义，那么"$*"也就不能被推导出，但是，如果目标文件的后缀是make所识别的，那么"$*"就是除了后缀的那一部分。例如：如果目标是"foo.c"，因为".c"是make所能识别的后缀名，所以，"$*"的值就是"foo"。这个特性是GNU make的，很有可能不兼容于其它版本的make，所以，你应该尽量避免使用"$*"，除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的，那么"$*"就是空值。</font>
				</p>
				<p>
						<font face="Courier New">当你希望只对更新过的依赖文件进行操作时，"$?"在显式规则中很有用，例如，假设有一个函数库文件叫"lib"，其由其它几个object文件更新。那么把object文件打包的比较有效率的Makefile规则是：</font>
				</p>
				<p>
						<font face="Courier New">    lib : foo.o bar.o lose.o win.o<br />            ar r lib $?</font>
				</p>
				<p>
						<font face="Courier New">在上述所列出来的自动量变量中。四个变量（$@、$&lt;、$%、$*）在扩展时只会有一个文件，而另三个的值是一个文件列表。这七个自动化变量还可以取得文件的目录名或是在当前目录下的符合模式的文件名，只需要搭配上"D"或"F"字样。这是GNU make中老版本的特性，在新版本中，我们使用函数"dir"或"notdir"就可以做到了。"D"的含义就是Directory，就是目录，"F"的含义就是File，就是文件。</font>
				</p>
				<p>
						<font face="Courier New">下面是对于上面的七个变量分别加上"D"或是"F"的含义：</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(@D)</strong>
								<br />    表示"$@"的目录部分（不以斜杠作为结尾），如果"$@"值是"dir/foo.o"，那么"$(@D)"就是"dir"，而如果"$@"中没有包含斜杠的话，其值就是"."（当前目录）。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(@F)</strong>
								<br />    表示"$@"的文件部分，如果"$@"值是"dir/foo.o"，那么"$(@F)"就是"foo.o"，"$(@F)"相当于函数"$(notdir $@)"。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>"$(*D)"<br />"$(*F)"</strong>
								<br />    和上面所述的同理，也是取文件的目录部分和文件部分。对于上面的那个例子，"$(*D)"返回"dir"，而"$(*F)"返回"foo"</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>"$(%D)"<br />"$(%F)"</strong>
								<br />    分别表示了函数包文件成员的目录部分和文件部分。这对于形同"archive(member)"形式的目标中的"member"中包含了不同的目录很有用。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>"$(&lt;D)"<br />"$(&lt;F)"</strong>
								<br />    分别表示依赖文件的目录部分和文件部分。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>"$(^D)"<br />"$(^F)"</strong>
								<br />    分别表示所有依赖文件的目录部分和文件部分。（无相同的）</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>"$(+D)"<br />"$(+F)"</strong>
								<br />    分别表示所有依赖文件的目录部分和文件部分。（可以有相同的）</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>"$(?D)"<br />"$(?F)"</strong>
								<br />    分别表示被更新的依赖文件的目录部分和文件部分。</font>
				</p>
				<p>
						<font face="Courier New">最后想提醒一下的是，对于"$&lt;"，为了避免产生不必要的麻烦，我们最好给$后面的那个特定字符都加上圆括号，比如，"$(&lt;)"就要比"$&lt;"要好一些。</font>
				</p>
				<p>
						<font face="Courier New">还得要注意的是，这些变量只使用在规则的命令中，而且一般都是"显式规则"和"静态模式规则"（参见前面"书写规则"一章）。其在隐含规则中并没有意义。</font>
				</p>
				<p>
						<strong>
								<font face="Courier New">4、模式的匹配</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">一般来说，一个目标的模式有一个有前缀或是后缀的"%"，或是没有前后缀，直接就是一个"%"。因为"%"代表一个或多个字符，所以在定义好了的模式中，我们把"%"所匹配的内容叫做"茎"，例如"%.c"所匹配的文件"test.c"中"test"就是"茎"。因为在目标和依赖目标中同时有"%"时，依赖目标的"茎"会传给目标，当做目标中的"茎"。</font>
				</p>
				<p>
						<font face="Courier New">当一个模式匹配包含有斜杠（实际也不经常包含）的文件时，那么在进行模式匹配时，目录部分会首先被移开，然后进行匹配，成功后，再把目录加回去。在进行"茎"的传递时，我们需要知道这个步骤。例如有一个模式"e%t"，文件"src/eat"匹配于该模式，于是"src/a"就是其"茎"，如果这个模式定义在依赖目标中，而被依赖于这个模式的目标中又有个模式"c%r"，那么，目标就是"src/car"。（"茎"被传递）</font>
				</p>
				<p>
						<br />
						<strong>
								<font face="Courier New">5、重载内建隐含规则</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">你可以重载内建的隐含规则（或是定义一个全新的），例如你可以重新构造和内建隐含规则不同的命令，如：</font>
				</p>
				<p>
						<font face="Courier New">    %.o : %.c<br />            $(CC) -c $(CPPFLAGS) $(CFLAGS) -D$(date)</font>
				</p>
				<p>
						<font face="Courier New">你可以取消内建的隐含规则，只要不在后面写命令就行。如：</font>
				</p>
				<p>
						<font face="Courier New">    %.o : %.s</font>
				</p>
				<p>
						<font face="Courier New">同样，你也可以重新定义一个全新的隐含规则，其在隐含规则中的位置取决于你在哪里写下这个规则。朝前的位置就靠前。</font>
				</p>
				<p>
						<br />
						<strong>
								<font face="Courier New">六、老式风格的"后缀规则"</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">后缀规则是一个比较老式的定义隐含规则的方法。后缀规则会被模式规则逐步地取代。因为模式规则更强更清晰。为了和老版本的Makefile兼容，GNU make同样兼容于这些东西。后缀规则有两种方式："双后缀"和"单后缀"。</font>
				</p>
				<p>
						<font face="Courier New">双后缀规则定义了一对后缀：目标文件的后缀和依赖目标（源文件）的后缀。如".c.o"相当于"%o : %c"。单后缀规则只定义一个后缀，也就是源文件的后缀。如".c"相当于"% : %.c"。</font>
				</p>
				<p>
						<font face="Courier New">后缀规则中所定义的后缀应该是make所认识的，如果一个后缀是make所认识的，那么这个规则就是单后缀规则，而如果两个连在一起的后缀都被make所认识，那就是双后缀规则。例如：".c"和".o"都是make所知道。因而，如果你定义了一个规则是".c.o"那么其就是双后缀规则，意义就是".c"是源文件的后缀，".o"是目标文件的后缀。如下示例：</font>
				</p>
				<p>
						<font face="Courier New">    .c.o:<br />            $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $&lt;</font>
				</p>
				<p>
						<font face="Courier New">后缀规则不允许任何的依赖文件，如果有依赖文件的话，那就不是后缀规则，那些后缀统统被认为是文件名，如：</font>
				</p>
				<p>
						<font face="Courier New">    .c.o: foo.h<br />            $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $&lt;</font>
				</p>
				<p>
						<font face="Courier New">这个例子，就是说，文件".c.o"依赖于文件"foo.h"，而不是我们想要的这样：</font>
				</p>
				<p>
						<font face="Courier New">    %.o: %.c foo.h<br />            $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $&lt;</font>
				</p>
				<p>
						<font face="Courier New">后缀规则中，如果没有命令，那是毫无意义的。因为他也不会移去内建的隐含规则。</font>
				</p>
				<p>
						<font face="Courier New">而要让make知道一些特定的后缀，我们可以使用伪目标".SUFFIXES"来定义或是删除，如：</font>
				</p>
				<p>
						<font face="Courier New">    .SUFFIXES: .hack .win</font>
				</p>
				<p>
						<font face="Courier New">把后缀.hack和.win加入后缀列表中的末尾。</font>
				</p>
				<p>
						<font face="Courier New">    .SUFFIXES:              # 删除默认的后缀<br />    .SUFFIXES: .c .o .h   # 定义自己的后缀</font>
				</p>
				<p>
						<font face="Courier New">先清楚默认后缀，后定义自己的后缀列表。</font>
				</p>
				<p>
						<font face="Courier New">make的参数"-r"或"-no-builtin-rules"也会使用得默认的后缀列表为空。而变量"SUFFIXE"被用来定义默认的后缀列表，你可以用".SUFFIXES"来改变后缀列表，但请不要改变变量"SUFFIXE"的值。</font>
				</p>
				<p>
						<strong>
								<br />
								<font face="Courier New">七、隐含规则搜索算法</font>
						</strong>
				</p>
				<p>
						<font face="Courier New">比如我们有一个目标叫 T。下面是搜索目标T的规则的算法。请注意，在下面，我们没有提到后缀规则，原因是，所有的后缀规则在Makefile被载入内存时，会被转换成模式规则。如果目标是"archive(member)"的函数库文件模式，那么这个算法会被运行两次，第一次是找目标T，如果没有找到的话，那么进入第二次，第二次会把"member"当作T来搜索。</font>
				</p>
				<p>
						<font face="Courier New">1、把T的目录部分分离出来。叫D，而剩余部分叫N。（如：如果T是"src/foo.o"，那么，D就是"src/"，N就是"foo.o"）</font>
				</p>
				<p>
						<font face="Courier New">2、创建所有匹配于T或是N的模式规则列表。</font>
				</p>
				<p>
						<font face="Courier New">3、如果在模式规则列表中有匹配所有文件的模式，如"%"，那么从列表中移除其它的模式。</font>
				</p>
				<p>
						<font face="Courier New">4、移除列表中没有命令的规则。</font>
				</p>
				<p>
						<font face="Courier New">5、对于第一个在列表中的模式规则：<br />    1）推导其"茎"S，S应该是T或是N匹配于模式中"%"非空的部分。<br />    2）计算依赖文件。把依赖文件中的"%"都替换成"茎"S。如果目标模式中没有包含斜框字符，而把D加在第一个依赖文件的开头。<br />3）测试是否所有的依赖文件都存在或是理当存在。（如果有一个文件被定义成另外一个规则的目标文件，或者是一个显式规则的依赖文件，那么这个文件就叫"理当存在"）<br />    4）如果所有的依赖文件存在或是理当存在，或是就没有依赖文件。那么这条规则将被采用，退出该算法。</font>
				</p>
				<p>
						<font face="Courier New">6、如果经过第5步，没有模式规则被找到，那么就做更进一步的搜索。对于存在于列表中的第一个模式规则：<br />    1）如果规则是终止规则，那就忽略它，继续下一条模式规则。<br />2）计算依赖文件。（同第5步）<br />3）测试所有的依赖文件是否存在或是理当存在。<br />4）对于不存在的依赖文件，递归调用这个算法查找他是否可以被隐含规则找到。<br />5）如果所有的依赖文件存在或是理当存在，或是就根本没有依赖文件。那么这条规则被采用，退出该算法。</font>
				</p>
				<p>
						<font face="Courier New">7、如果没有隐含规则可以使用，查看".DEFAULT"规则，如果有，采用，把".DEFAULT"的命令给T使用。</font>
				</p>
				<p>
						<font face="Courier New">一旦规则被找到，就会执行其相当的命令，而此时，我们的自动化变量的值才会生成。<br /></font>
				</p>
				<br />
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:34 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起写 Makefile（十二）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71410.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:33:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71410.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71410.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71410.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71410.html</trackback:ping><description><![CDATA[
		<strong>
				<font face="Courier New">
						<p id="TBPingURL">Trackback: <a href="http://tb.blog.csdn.net/TrackBack.aspx?PostId=2897">http://tb.blog.csdn.net/TrackBack.aspx?PostId=2897</a><br />隐含规则<br />————</p>
				</font>
		</strong>
		<p>
				<font face="Courier New">在我们使用Makefile时，有一些我们会经常使用，而且使用频率非常高的东西，比如，我们编译C/C++的源程序为中间目标文件（Unix下是[.o]文件，Windows下是[.obj]文件）。本章讲述的就是一些在Makefile中的“隐含的”，早先约定了的，不需要我们再写出来的规则。</font>
		</p>
		<p>
				<font face="Courier New">“隐含规则”也就是一种惯例，make会按照这种“惯例”心照不喧地来运行，那怕我们的Makefile中没有书写这样的规则。例如，把[.c]文件编译成[.o]文件这一规则，你根本就不用写出来，make会自动推导出这种规则，并生成我们需要的[.o]文件。</font>
		</p>
		<p>
				<font face="Courier New">“隐含规则”会使用一些我们系统变量，我们可以改变这些系统变量的值来定制隐含规则的运行时的参数。如系统变量“CFLAGS”可以控制编译时的编译器参数。</font>
		</p>
		<p>
				<font face="Courier New">我们还可以通过“模式规则”的方式写下自己的隐含规则。用“后缀规则”来定义隐含规则会有许多的限制。使用“模式规则”会更回得智能和清楚，但“后缀规则”可以用来保证我们Makefile的兼容性。<br />我们了解了“隐含规则”，可以让其为我们更好的服务，也会让我们知道一些“约定俗成”了的东西，而不至于使得我们在运行Makefile时出现一些我们觉得莫名其妙的东西。当然，任何事物都是矛盾的，水能载舟，亦可覆舟，所以，有时候“隐含规则”也会给我们造成不小的麻烦。只有了解了它，我们才能更好地使用它。</font>
		</p>
		<p>
				<font face="Courier New">
						<br />
						<strong>一、使用隐含规则<br /></strong>
						<br />如果要使用隐含规则生成你需要的目标，你所需要做的就是不要写出这个目标的规则。那么，make会试图去自动推导产生这个目标的规则和命令，如果make可以自动推导生成这个目标的规则和命令，那么这个行为就是隐含规则的自动推导。当然，隐含规则是make事先约定好的一些东西。例如，我们有下面的一个Makefile：</font>
		</p>
		<p>
				<font face="Courier New">    foo : foo.o bar.o<br />            cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)</font>
		</p>
		<p>
				<font face="Courier New">我们可以注意到，这个Makefile中并没有写下如何生成foo.o和bar.o这两目标的规则和命令。因为make的“隐含规则”功能会自动为我们自动去推导这两个目标的依赖目标和生成命令。</font>
		</p>
		<p>
				<font face="Courier New">make会在自己的“隐含规则”库中寻找可以用的规则，如果找到，那么就会使用。如果找不到，那么就会报错。在上面的那个例子中，make调用的隐含规则是，把[.o]的目标的依赖文件置成[.c]，并使用C的编译命令“cc –c $(CFLAGS) [.c]”来生成[.o]的目标。也就是说，我们完全没有必要写下下面的两条规则：</font>
		</p>
		<p>
				<font face="Courier New">    foo.o : foo.c<br />            cc –c foo.c $(CFLAGS)<br />    bar.o : bar.c<br />        cc –c bar.c $(CFLAGS)</font>
		</p>
		<p>
				<font face="Courier New">因为，这已经是“约定”好了的事了，make和我们约定好了用C编译器“cc”生成[.o]文件的规则，这就是隐含规则。</font>
		</p>
		<p>
				<font face="Courier New">当然，如果我们为[.o]文件书写了自己的规则，那么make就不会自动推导并调用隐含规则，它会按照我们写好的规则忠实地执行。</font>
		</p>
		<p>
				<font face="Courier New">还有，在make的“隐含规则库”中，每一条隐含规则都在库中有其顺序，越靠前的则是越被经常使用的，所以，这会导致我们有些时候即使我们显示地指定了目标依赖，make也不会管。如下面这条规则（没有命令）：</font>
		</p>
		<p>
				<font face="Courier New">    foo.o : foo.p</font>
		</p>
		<p>
				<font face="Courier New">依赖文件“foo.p”（Pascal程序的源文件）有可能变得没有意义。如果目录下存在了“foo.c”文件，那么我们的隐含规则一样会生效，并会通过“foo.c”调用C的编译器生成foo.o文件。因为，在隐含规则中，Pascal的规则出现在C的规则之后，所以，make找到可以生成foo.o的C的规则就不再寻找下一条规则了。如果你确实不希望任何隐含规则推导，那么，你就不要只写出“依赖规则”，而不写命令。</font>
		</p>
		<p>
				<br />
				<font face="Courier New">
						<strong>二、隐含规则一览<br /></strong>
						<br />这里我们将讲述所有预先设置（也就是make内建）的隐含规则，如果我们不明确地写下规则，那么，make就会在这些规则中寻找所需要规则和命令。当然，我们也可以使用make的参数“-r”或“--no-builtin-rules”选项来取消所有的预设置的隐含规则。</font>
		</p>
		<p>
				<font face="Courier New">当然，即使是我们指定了“-r”参数，某些隐含规则还是会生效，因为有许多的隐含规则都是使用了“后缀规则”来定义的，所以，只要隐含规则中有“后缀列表”（也就一系统定义在目标.SUFFIXES的依赖目标），那么隐含规则就会生效。默认的后缀列表是：.out, .a, .ln, .o, .c, .cc, .C, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el。具体的细节，我们会在后面讲述。</font>
		</p>
		<p>
				<font face="Courier New">还是先来看一看常用的隐含规则吧。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>1、编译C程序的隐含规则。</strong>
						<br />“&lt;n&gt;.o”的目标的依赖目标会自动推导为“&lt;n&gt;.c”，并且其生成命令是“$(CC) –c $(CPPFLAGS) $(CFLAGS)”</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>2、编译C++程序的隐含规则。</strong>
						<br />“&lt;n&gt;.o”的目标的依赖目标会自动推导为“&lt;n&gt;.cc”或是“&lt;n&gt;.C”，并且其生成命令是“$(CXX) –c $(CPPFLAGS) $(CFLAGS)”。（建议使用“.cc”作为C++源文件的后缀，而不是“.C”）</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>3、编译Pascal程序的隐含规则。<br /></strong>“&lt;n&gt;.o”的目标的依赖目标会自动推导为“&lt;n&gt;.p”，并且其生成命令是“$(PC) –c  $(PFLAGS)”。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>4、编译Fortran/Ratfor程序的隐含规则。<br /></strong>“&lt;n&gt;.o”的目标的依赖目标会自动推导为“&lt;n&gt;.r”或“&lt;n&gt;.F”或“&lt;n&gt;.f”，并且其生成命令是:<br />    “.f”  “$(FC) –c  $(FFLAGS)”<br />    “.F”  “$(FC) –c  $(FFLAGS) $(CPPFLAGS)”<br />    “.f”  “$(FC) –c  $(FFLAGS) $(RFLAGS)”</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>5、预处理Fortran/Ratfor程序的隐含规则。</strong>
						<br />“&lt;n&gt;.f”的目标的依赖目标会自动推导为“&lt;n&gt;.r”或“&lt;n&gt;.F”。这个规则只是转换Ratfor或有预处理的Fortran程序到一个标准的Fortran程序。其使用的命令是：<br />    “.F”  “$(FC) –F $(CPPFLAGS) $(FFLAGS)”<br />    “.r”  “$(FC) –F $(FFLAGS) $(RFLAGS)”</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>6、编译Modula-2程序的隐含规则。<br /></strong>“&lt;n&gt;.sym”的目标的依赖目标会自动推导为“&lt;n&gt;.def”，并且其生成命令是：“$(M2C) $(M2FLAGS) $(DEFFLAGS)”。“&lt;n.o&gt;” 的目标的依赖目标会自动推导为“&lt;n&gt;.mod”，并且其生成命令是：“$(M2C) $(M2FLAGS) $(MODFLAGS)”。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>7、汇编和汇编预处理的隐含规则。<br /></strong>“&lt;n&gt;.o” 的目标的依赖目标会自动推导为“&lt;n&gt;.s”，默认使用编译品“as”，并且其生成命令是：“$(AS) $(ASFLAGS)”。“&lt;n&gt;.s” 的目标的依赖目标会自动推导为“&lt;n&gt;.S”，默认使用C预编译器“cpp”，并且其生成命令是：“$(AS) $(ASFLAGS)”。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>8、链接Object文件的隐含规则。</strong>
						<br />“&lt;n&gt;”目标依赖于“&lt;n&gt;.o”，通过运行C的编译器来运行链接程序生成（一般是“ld”），其生成命令是：“$(CC) $(LDFLAGS) &lt;n&gt;.o $(LOADLIBES) $(LDLIBS)”。这个规则对于只有一个源文件的工程有效，同时也对多个Object文件（由不同的源文件生成）的也有效。例如如下规则：</font>
		</p>
		<p>
				<font face="Courier New">    x : y.o z.o</font>
		</p>
		<p>
				<font face="Courier New">并且“x.c”、“y.c”和“z.c”都存在时，隐含规则将执行如下命令：</font>
		</p>
		<p>
				<font face="Courier New">    cc -c x.c -o x.o<br />    cc -c y.c -o y.o<br />    cc -c z.c -o z.o<br />    cc x.o y.o z.o -o x<br />    rm -f x.o<br />    rm -f y.o<br />    rm -f z.o</font>
		</p>
		<p>
				<font face="Courier New">如果没有一个源文件（如上例中的x.c）和你的目标名字（如上例中的x）相关联，那么，你最好写出自己的生成规则，不然，隐含规则会报错的。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>9、Yacc C程序时的隐含规则。<br /></strong>“&lt;n&gt;.c”的依赖文件被自动推导为“n.y”（Yacc生成的文件），其生成命令是：“$(YACC) $(YFALGS)”。（“Yacc”是一个语法分析器，关于其细节请查看相关资料）</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>10、Lex C程序时的隐含规则。</strong>
						<br />“&lt;n&gt;.c”的依赖文件被自动推导为“n.l”（Lex生成的文件），其生成命令是：“$(LEX) $(LFALGS)”。（关于“Lex”的细节请查看相关资料）</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>11、Lex Ratfor程序时的隐含规则。</strong>
						<br />“&lt;n&gt;.r”的依赖文件被自动推导为“n.l”（Lex生成的文件），其生成命令是：“$(LEX) $(LFALGS)”。<br /><br /><strong>12、从C程序、Yacc文件或Lex文件创建Lint库的隐含规则。</strong><br />“&lt;n&gt;.ln” （lint生成的文件）的依赖文件被自动推导为“n.c”，其生成命令是：“$(LINT) $(LINTFALGS) $(CPPFLAGS) -i”。对于“&lt;n&gt;.y”和“&lt;n&gt;.l”也是同样的规则。<br /></font>
		</p>
		<p>
				<font face="Courier New">
						<strong>三、隐含规则使用的变量<br /></strong>
						<br />在隐含规则中的命令中，基本上都是使用了一些预先设置的变量。你可以在你的makefile中改变这些变量的值，或是在make的命令行中传入这些值，或是在你的环境变量中设置这些值，无论怎么样，只要设置了这些特定的变量，那么其就会对隐含规则起作用。当然，你也可以利用make的“-R”或“--no–builtin-variables”参数来取消你所定义的变量对隐含规则的作用。</font>
		</p>
		<p>
				<font face="Courier New">例如，第一条隐含规则——编译C程序的隐含规则的命令是“$(CC) –c $(CFLAGS) $(CPPFLAGS)”。Make默认的编译命令是“cc”，如果你把变量“$(CC)”重定义成“gcc”，把变量“$(CFLAGS)”重定义成“-g”，那么，隐含规则中的命令全部会以“gcc –c -g $(CPPFLAGS)”的样子来执行了。</font>
		</p>
		<p>
				<font face="Courier New">我们可以把隐含规则中使用的变量分成两种：一种是命令相关的，如“CC”；一种是参数相的关，如“CFLAGS”。下面是所有隐含规则中会用到的变量：</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>1、关于命令的变量。</strong>
				</font>
		</p>
		<p>
				<font face="Courier New">AR <br />    函数库打包程序。默认命令是“ar”。 <br />AS <br />    汇编语言编译程序。默认命令是“as”。<br />CC <br />    C语言编译程序。默认命令是“cc”。<br />CXX <br />    C++语言编译程序。默认命令是“g++”。<br />CO <br />    从 RCS文件中扩展文件程序。默认命令是“co”。<br />CPP <br />    C程序的预处理器（输出是标准输出设备）。默认命令是“$(CC) –E”。<br />FC <br />    Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。<br />GET <br />    从SCCS文件中扩展文件的程序。默认命令是“get”。 <br />LEX <br />    Lex方法分析器程序（针对于C或Ratfor）。默认命令是“lex”。<br />PC <br />    Pascal语言编译程序。默认命令是“pc”。<br />YACC <br />    Yacc文法分析器（针对于C程序）。默认命令是“yacc”。<br />YACCR <br />    Yacc文法分析器（针对于Ratfor程序）。默认命令是“yacc –r”。<br />MAKEINFO <br />    转换Texinfo源文件（.texi）到Info文件程序。默认命令是“makeinfo”。<br />TEX <br />    从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。<br />TEXI2DVI <br />    从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。<br />WEAVE <br />    转换Web到TeX的程序。默认命令是“weave”。<br />CWEAVE <br />    转换C Web 到 TeX的程序。默认命令是“cweave”。<br />TANGLE <br />    转换Web到Pascal语言的程序。默认命令是“tangle”。<br />CTANGLE <br />    转换C Web 到 C。默认命令是“ctangle”。<br />RM <br />    删除文件命令。默认命令是“rm –f”。</font>
		</p>
		<p>
				<font face="Courier New">
						<strong>2、关于命令参数的变量<br /></strong>
						<br />下面的这些变量都是相关上面的命令的参数。如果没有指明其默认值，那么其默认值都是空。<br /><br />ARFLAGS <br />    函数库打包程序AR命令的参数。默认值是“rv”。<br />ASFLAGS <br />    汇编语言编译器参数。（当明显地调用“.s”或“.S”文件时）。 <br />CFLAGS <br />    C语言编译器参数。<br />CXXFLAGS <br />    C++语言编译器参数。<br />COFLAGS <br />    RCS命令参数。 <br />CPPFLAGS <br />    C预处理器参数。（ C 和 Fortran 编译器也会用到）。<br />FFLAGS <br />    Fortran语言编译器参数。<br />GFLAGS <br />    SCCS “get”程序参数。<br />LDFLAGS <br />    链接器参数。（如：“ld”）<br />LFLAGS <br />    Lex文法分析器参数。<br />PFLAGS <br />    Pascal语言编译器参数。<br />RFLAGS <br />    Ratfor 程序的Fortran 编译器参数。<br />YFLAGS <br />    Yacc文法分析器参数。 </font>
		</p>
		<p>
				<font face="Courier New">
						<strong>
								<br />四、隐含规则链</strong>
						<br />
						<br />有些时候，一个目标可能被一系列的隐含规则所作用。例如，一个[.o]的文件生成，可能会是先被Yacc的[.y]文件先成[.c]，然后再被C的编译器生成。我们把这一系列的隐含规则叫做“隐含规则链”。</font>
		</p>
		<p>
				<font face="Courier New">在上面的例子中，如果文件[.c]存在，那么就直接调用C的编译器的隐含规则，如果没有[.c]文件，但有一个[.y]文件，那么Yacc的隐含规则会被调用，生成[.c]文件，然后，再调用C编译的隐含规则最终由[.c]生成[.o]文件，达到目标。</font>
		</p>
		<p>
				<font face="Courier New">我们把这种[.c]的文件（或是目标），叫做中间目标。不管怎么样，make会努力自动推导生成目标的一切方法，不管中间目标有多少，其都会执着地把所有的隐含规则和你书写的规则全部合起来分析，努力达到目标，所以，有些时候，可能会让你觉得奇怪，怎么我的目标会这样生成？怎么我的makefile发疯了？</font>
		</p>
		<p>
				<font face="Courier New">在默认情况下，对于中间目标，它和一般的目标有两个地方所不同：第一个不同是除非中间的目标不存在，才会引发中间规则。第二个不同的是，只要目标成功产生，那么，产生最终目标过程中，所产生的中间目标文件会被以“rm -f”删除。</font>
		</p>
		<p>
				<font face="Courier New">通常，一个被makefile指定成目标或是依赖目标的文件不能被当作中介。然而，你可以明显地说明一个文件或是目标是中介目标，你可以使用伪目标“.INTERMEDIATE”来强制声明。（如：.INTERMEDIATE ： mid ）</font>
		</p>
		<p>
				<font face="Courier New">你也可以阻止make自动删除中间目标，要做到这一点，你可以使用伪目标“.SECONDARY”来强制声明（如：.SECONDARY : sec）。你还可以把你的目标，以模式的方式来指定（如：%.o）成伪目标“.PRECIOUS”的依赖目标，以保存被隐含规则所生成的中间文件。</font>
		</p>
		<p>
				<font face="Courier New">在“隐含规则链”中，禁止同一个目标出现两次或两次以上，这样一来，就可防止在make自动推导时出现无限递归的情况。</font>
		</p>
		<p>
				<font face="Courier New">Make会优化一些特殊的隐含规则，而不生成中间文件。如，从文件“foo.c”生成目标程序“foo”，按道理，make会编译生成中间文件“foo.o”，然后链接成“foo”，但在实际情况下，这一动作可以被一条“cc”的命令完成（cc –o foo foo.c），于是优化过的规则就不会生成中间文件。</font>
				<font face="Courier New">
				</font>
		</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:33 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)跟我一起写 Makefile（十一）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71409.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:32:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71409.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71409.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71409.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71409.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71409.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Courier New" size="4">
						<strong>
								<p id="TBPingURL">Trackback: <a href="http://tb.blog.csdn.net/TrackBack.aspx?PostId=2896">http://tb.blog.csdn.net/TrackBack.aspx?PostId=2896</a><br />make 的运行<br />——————</p>
						</strong>
				</font>
				<p>
						<font face="Courier New">一般来说，最简单的就是直接在命令行下输入make命令，make命令会找当前目录的makefile来执行，一切都是自动的。但也有时你也许只想让make重编译某些文件，而不是整个工程，而又有的时候你有几套编译规则，你想在不同的时候使用不同的编译规则，等等。本章节就是讲述如何使用make命令的。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>一、make的退出码</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">make命令执行后有三个退出码：</font>
				</p>
				<p>
						<font face="Courier New">    0 —— 表示成功执行。<br />    1 —— 如果make运行时出现任何错误，其返回1。<br />    2 —— 如果你使用了make的“-q”选项，并且make使得一些目标不需要更新，那么返回2。</font>
				</p>
				<p>
						<font face="Courier New">Make的相关参数我们会在后续章节中讲述。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>二、指定Makefile</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">前面我们说过，GNU make找寻默认的Makefile的规则是在当前目录下依次找三个文件——“GNUmakefile”、“makefile”和“Makefile”。其按顺序找这三个文件，一旦找到，就开始读取这个文件并执行。</font>
				</p>
				<p>
						<font face="Courier New">当前，我们也可以给make命令指定一个特殊名字的Makefile。要达到这个功能，我们要使用make的“-f”或是“--file”参数（“--makefile”参数也行）。例如，我们有个makefile的名字是“hchen.mk”，那么，我们可以这样来让make来执行这个文件：</font>
				</p>
				<p>
						<font face="Courier New">    make –f hchen.mk</font>
				</p>
				<p>
						<font face="Courier New">如果在make的命令行是，你不只一次地使用了“-f”参数，那么，所有指定的makefile将会被连在一起传递给make执行。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>三、指定目标</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">一般来说，make的最终目标是makefile中的第一个目标，而其它目标一般是由这个目标连带出来的。这是make的默认行为。当然，一般来说，你的makefile中的第一个目标是由许多个目标组成，你可以指示make，让其完成你所指定的目标。要达到这一目的很简单，需在make命令后直接跟目标的名字就可以完成（如前面提到的“make clean”形式）</font>
				</p>
				<p>
						<font face="Courier New">任何在makefile中的目标都可以被指定成终极目标，但是除了以“-”打头，或是包含了“=”的目标，因为有这些字符的目标，会被解析成命令行参数或是变量。甚至没有被我们明确写出来的目标也可以成为make的终极目标，也就是说，只要make可以找到其隐含规则推导规则，那么这个隐含目标同样可以被指定成终极目标。</font>
				</p>
				<p>
						<font face="Courier New">有一个make的环境变量叫“MAKECMDGOALS”，这个变量中会存放你所指定的终极目标的列表，如果在命令行上，你没有指定目标，那么，这个变量是空值。这个变量可以让你使用在一些比较特殊的情形下。比如下面的例子：</font>
				</p>
				<p>
						<font face="Courier New">    sources = foo.c bar.c<br />    ifneq ( $(MAKECMDGOALS),clean)<br />    include $(sources:.c=.d)<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">基于上面的这个例子，只要我们输入的命令不是“make clean”，那么makefile会自动包含“foo.d”和“bar.d”这两个makefile。</font>
				</p>
				<p>
						<font face="Courier New">使用指定终极目标的方法可以很方便地让我们编译我们的程序，例如下面这个例子：</font>
				</p>
				<p>
						<font face="Courier New">    .PHONY: all<br />    all: prog1 prog2 prog3 prog4</font>
				</p>
				<p>
						<font face="Courier New">从这个例子中，我们可以看到，这个makefile中有四个需要编译的程序——“prog1”， “prog2”， “prog3”和 “prog4”，我们可以使用“make all”命令来编译所有的目标（如果把all置成第一个目标，那么只需执行“make”），我们也可以使用“make prog2”来单独编译目标“prog2”。</font>
				</p>
				<p>
						<font face="Courier New">即然make可以指定所有makefile中的目标，那么也包括“伪目标”，于是我们可以根据这种性质来让我们的makefile根据指定的不同的目标来完成不同的事。在Unix世界中，软件发布时，特别是GNU这种开源软件的发布时，其makefile都包含了编译、安装、打包等功能。我们可以参照这种规则来书写我们的makefile中的目标。</font>
				</p>
				<p>
						<font face="Courier New">     “all”<br />        这个伪目标是所有目标的目标，其功能一般是编译所有的目标。<br />     “clean”<br />        这个伪目标功能是删除所有被make创建的文件。<br />     “install”<br />        这个伪目标功能是安装已编译好的程序，其实就是把目标执行文件拷贝到指定的目标中去。<br />     “print”<br />        这个伪目标的功能是例出改变过的源文件。<br />     “tar”<br />        这个伪目标功能是把源程序打包备份。也就是一个tar文件。<br />     “dist”<br />        这个伪目标功能是创建一个压缩文件，一般是把tar文件压成Z文件。或是gz文件。<br />     “TAGS”<br />        这个伪目标功能是更新所有的目标，以备完整地重编译使用。<br />     “check”和“test”<br />        这两个伪目标一般用来测试makefile的流程。</font>
				</p>
				<p>
						<font face="Courier New">当然一个项目的makefile中也不一定要书写这样的目标，这些东西都是GNU的东西，但是我想，GNU搞出这些东西一定有其可取之处（等你的UNIX下的程序文件一多时你就会发现这些功能很有用了），这里只不过是说明了，如果你要书写这种功能，最好使用这种名字命名你的目标，这样规范一些，规范的好处就是——不用解释，大家都明白。而且如果你的makefile中有这些功能，一是很实用，二是可以显得你的makefile很专业（不是那种初学者的作品）。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>四、检查规则</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">有时候，我们不想让我们的makefile中的规则执行起来，我们只想检查一下我们的命令，或是执行的序列。于是我们可以使用make命令的下述参数：</font>
				</p>
				<p>
						<font face="Courier New">    “-n”<br />    “--just-print”<br />    “--dry-run”<br />    “--recon”<br />    不执行参数，这些参数只是打印命令，不管目标是否更新，把规则和连带规则下的命令打印出来，但不执行，这些参数对于我们调试makefile很有用处。</font>
				</p>
				<p>
						<font face="Courier New">    “-t”<br />    “--touch”<br />    这个参数的意思就是把目标文件的时间更新，但不更改目标文件。也就是说，make假装编译目标，但不是真正的编译目标，只是把目标变成已编译过的状态。</font>
				</p>
				<p>
						<font face="Courier New">    “-q”<br />    “--question”<br />    这个参数的行为是找目标的意思，也就是说，如果目标存在，那么其什么也不会输出，当然也不会执行编译，如果目标不存在，其会打印出一条出错信息。</font>
				</p>
				<p>
						<font face="Courier New">    “-W &lt;file&gt;”<br />    “--what-if=&lt;file&gt;”<br />    “--assume-new=&lt;file&gt;”<br />    “--new-file=&lt;file&gt;”<br />    这个参数需要指定一个文件。一般是是源文件（或依赖文件），Make会根据规则推导来运行依赖于这个文件的命令，一般来说，可以和“-n”参数一同使用，来查看这个依赖文件所发生的规则命令。</font>
				</p>
				<p>
						<font face="Courier New">另外一个很有意思的用法是结合“-p”和“-v”来输出makefile被执行时的信息（这个将在后面讲述）。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>五、make的参数</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">下面列举了所有GNU make 3.80版的参数定义。其它版本和产商的make大同小异，不过其它产商的make的具体参数还是请参考各自的产品文档。</font>
				</p>
				<p>
						<font face="Courier New">“-b”<br />“-m”<br />这两个参数的作用是忽略和其它版本make的兼容性。</font>
				</p>
				<p>
						<font face="Courier New">“-B”<br />“--always-make”<br />认为所有的目标都需要更新（重编译）。</font>
				</p>
				<p>
						<font face="Courier New">“-C &lt;dir&gt;”<br />“--directory=&lt;dir&gt;”<br />指定读取makefile的目录。如果有多个“-C”参数，make的解释是后面的路径以前面的作为相对路径，并以最后的目录作为被指定目录。如：“make –C ~hchen/test –C prog”等价于“make –C ~hchen/test/prog”。</font>
				</p>
				<p>
						<font face="Courier New">“—debug[=&lt;options&gt;]”<br />输出make的调试信息。它有几种不同的级别可供选择，如果没有参数，那就是输出最简单的调试信息。下面是&lt;options&gt;的取值：<br />    a —— 也就是all，输出所有的调试信息。（会非常的多）<br />    b —— 也就是basic，只输出简单的调试信息。即输出不需要重编译的目标。<br />    v —— 也就是verbose，在b选项的级别之上。输出的信息包括哪个makefile被解析，不需要被重编译的依赖文件（或是依赖目标）等。<br />    i —— 也就是implicit，输出所以的隐含规则。<br />    j —— 也就是jobs，输出执行规则中命令的详细信息，如命令的PID、返回码等。<br />    m —— 也就是makefile，输出make读取makefile，更新makefile，执行makefile的信息。</font>
				</p>
				<p>
						<font face="Courier New">“-d”<br />相当于“--debug=a”。</font>
				</p>
				<p>
						<font face="Courier New">“-e”<br />“--environment-overrides”<br />指明环境变量的值覆盖makefile中定义的变量的值。</font>
				</p>
				<p>
						<font face="Courier New">“-f=&lt;file&gt;”<br />“--file=&lt;file&gt;”<br />“--makefile=&lt;file&gt;”<br />指定需要执行的makefile。</font>
				</p>
				<p>
						<font face="Courier New">“-h”<br />“--help”<br />显示帮助信息。</font>
				</p>
				<p>
						<font face="Courier New">“-i”<br />“--ignore-errors”<br />在执行时忽略所有的错误。</font>
				</p>
				<p>
						<font face="Courier New">“-I &lt;dir&gt;”<br />“--include-dir=&lt;dir&gt;”<br />指定一个被包含makefile的搜索目标。可以使用多个“-I”参数来指定多个目录。</font>
				</p>
				<p>
						<font face="Courier New">“-j [&lt;jobsnum&gt;]”<br />“--jobs[=&lt;jobsnum&gt;]”<br />指同时运行命令的个数。如果没有这个参数，make运行命令时能运行多少就运行多少。如果有一个以上的“-j”参数，那么仅最后一个“-j”才是有效的。（注意这个参数在MS-DOS中是无用的）</font>
				</p>
				<p>
						<font face="Courier New">“-k”<br />“--keep-going”<br />出错也不停止运行。如果生成一个目标失败了，那么依赖于其上的目标就不会被执行了。</font>
				</p>
				<p>
						<font face="Courier New">“-l &lt;load&gt;”<br />“--load-average[=&lt;load]”<br />“—max-load[=&lt;load&gt;]”<br />指定make运行命令的负载。</font>
				</p>
				<p>
						<font face="Courier New">“-n”<br />“--just-print”<br />“--dry-run”<br />“--recon”<br />仅输出执行过程中的命令序列，但并不执行。</font>
				</p>
				<p>
						<font face="Courier New">“-o &lt;file&gt;”<br />“--old-file=&lt;file&gt;”<br />“--assume-old=&lt;file&gt;”<br />不重新生成的指定的&lt;file&gt;，即使这个目标的依赖文件新于它。</font>
				</p>
				<p>
						<font face="Courier New">“-p”<br />“--print-data-base”<br />输出makefile中的所有数据，包括所有的规则和变量。这个参数会让一个简单的makefile都会输出一堆信息。如果你只是想输出信息而不想执行makefile，你可以使用“make -qp”命令。如果你想查看执行makefile前的预设变量和规则，你可以使用“make –p –f /dev/null”。这个参数输出的信息会包含着你的makefile文件的文件名和行号，所以，用这个参数来调试你的makefile会是很有用的，特别是当你的环境变量很复杂的时候。</font>
				</p>
				<p>
						<font face="Courier New">“-q”<br />“--question”<br />不运行命令，也不输出。仅仅是检查所指定的目标是否需要更新。如果是0则说明要更新，如果是2则说明有错误发生。</font>
				</p>
				<p>
						<font face="Courier New">“-r”<br />“--no-builtin-rules”<br />禁止make使用任何隐含规则。</font>
				</p>
				<p>
						<font face="Courier New">“-R”<br />“--no-builtin-variabes”<br />禁止make使用任何作用于变量上的隐含规则。</font>
				</p>
				<p>
						<font face="Courier New">“-s”<br />“--silent”<br />“--quiet”<br />在命令运行时不输出命令的输出。</font>
				</p>
				<p>
						<font face="Courier New">“-S”<br />“--no-keep-going”<br />“--stop”<br />取消“-k”选项的作用。因为有些时候，make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项失效。</font>
				</p>
				<p>
						<font face="Courier New">“-t”<br />“--touch”<br />相当于UNIX的touch命令，只是把目标的修改日期变成最新的，也就是阻止生成目标的命令运行。</font>
				</p>
				<p>
						<font face="Courier New">“-v”<br />“--version”<br />输出make程序的版本、版权等关于make的信息。</font>
				</p>
				<p>
						<font face="Courier New">“-w”<br />“--print-directory”<br />输出运行makefile之前和之后的信息。这个参数对于跟踪嵌套式调用make时很有用。</font>
				</p>
				<p>
						<font face="Courier New">“--no-print-directory”<br />禁止“-w”选项。</font>
				</p>
				<p>
						<font face="Courier New">“-W &lt;file&gt;”<br />“--what-if=&lt;file&gt;”<br />“--new-file=&lt;file&gt;”<br />“--assume-file=&lt;file&gt;”<br />假定目标&lt;file&gt;需要更新，如果和“-n”选项使用，那么这个参数会输出该目标更新时的运行动作。如果没有“-n”那么就像运行UNIX的“touch”命令一样，使得&lt;file&gt;的修改时间为当前时间。</font>
				</p>
				<p>
						<font face="Courier New">“--warn-undefined-variables”<br />只要make发现有未定义的变量，那么就输出警告信息。</font>
						<br />
				</p>
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71409.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:32 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71409.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起写 Makefile（十）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71408.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:30:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71408.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71408.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71408.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71408.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2895																																				四、								foreach 								函数																												 														...&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2006/09/23/71408.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/71408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:30 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起写 Makefile（八）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71406.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71406.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71406.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71406.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71406.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71406.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Courier New">
						<strong>
								<p id="TBPingURL">转载自: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2893</p>
								<p>
										<br />六、多行变量</p>
						</strong>
						<br /> <br />还有一种设置变量值的方法是使用define关键字。使用define关键字设置变量的值可以有换行，这有利于定义一系列的命令（前面我们讲过“命令包”的技术就是利用这个关键字）。</font>
				<p>
						<font face="Courier New">define指示符后面跟的是变量的名字，而重起一行定义变量的值，定义是以endef关键字结束。其工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字，或是其它变量。因为命令需要以[Tab]键开头，所以如果你用define定义的命令变量中没有以[Tab]键开头，那么make就不会把其认为是命令。</font>
				</p>
				<p>
						<font face="Courier New">下面的这个示例展示了define的用法：</font>
				</p>
				<p>
						<font face="Courier New">    define two-lines<br />    echo foo<br />    echo $(bar)<br />    endef</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>七、环境变量</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">make运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中，但是如果Makefile中已定义了这个变量，或是这个变量由make命令行带入，那么系统的环境变量的值将被覆盖。（如果make指定了“-e”参数，那么，系统环境变量将覆盖Makefile中定义的变量）</font>
				</p>
				<p>
						<font face="Courier New">因此，如果我们在环境变量中设置了“CFLAGS”环境变量，那么我们就可以在所有的Makefile中使用这个变量了。这对于我们使用统一的编译参数有比较大的好处。如果Makefile中定义了CFLAGS，那么则会使用Makefile中的这个变量，如果没有定义则使用系统环境变量的值，一个共性和个性的统一，很像“全局变量”和“局部变量”的特性。</font>
				</p>
				<p>
						<font face="Courier New">当make嵌套调用时（参见前面的“嵌套调用”章节），上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。当然，默认情况下，只有通过命令行设置的变量会被传递。而定义在文件中的变量，如果要向下层Makefile传递，则需要使用exprot关键字来声明。（参见前面章节）</font>
				</p>
				<p>
						<font face="Courier New">当然，我并不推荐把许多的变量都定义在系统环境中，这样，在我们执行不用的Makefile时，拥有的是同一套系统变量，这可能会带来更多的麻烦。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>八、目标变量</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">前面我们所讲的在Makefile中定义的变量都是“全局变量”，在整个文件，我们都可以访问这些变量。当然，“自动化变量”除外，如“$&lt;”等这种类量的自动化变量就属于“规则型变量”，这种变量的值依赖于规则的目标和依赖目标的定义。</font>
				</p>
				<p>
						<font face="Courier New">当然，我样同样可以为某个目标设置局部变量，这种变量被称为“Target-specific Variable”，它可以和“全局变量”同名，因为它的作用范围只在这条规则以及连带规则中，所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。</font>
				</p>
				<p>
						<font face="Courier New">其语法是：</font>
				</p>
				<p>
						<font face="Courier New">    &lt;target ...&gt; : &lt;variable-assignment&gt;</font>
				</p>
				<p>
						<font face="Courier New">    &lt;target ...&gt; : overide &lt;variable-assignment&gt;</font>
				</p>
				<p>
						<font face="Courier New">&lt;variable-assignment&gt;可以是前面讲过的各种赋值表达式，如“=”、“:=”、“+=”或是“？=”。第二个语法是针对于make命令行带入的变量，或是系统环境变量。</font>
				</p>
				<p>
						<font face="Courier New">这个特性非常的有用，当我们设置了这样一个变量，这个变量会作用到由这个目标所引发的所有的规则中去。如：</font>
				</p>
				<p>
						<font face="Courier New">    prog : CFLAGS = -g<br />    prog : prog.o foo.o bar.o<br />            $(CC) $(CFLAGS) prog.o foo.o bar.o</font>
				</p>
				<p>
						<font face="Courier New">    prog.o : prog.c<br />            $(CC) $(CFLAGS) prog.c</font>
				</p>
				<p>
						<font face="Courier New">    foo.o : foo.c<br />            $(CC) $(CFLAGS) foo.c</font>
				</p>
				<p>
						<font face="Courier New">    bar.o : bar.c<br />            $(CC) $(CFLAGS) bar.c<br /> <br />在这个示例中，不管全局的$(CFLAGS)的值是什么，在prog目标，以及其所引发的所有规则中（prog.o foo.o bar.o的规则），$(CFLAGS)的值都是“-g”</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>九、模式变量</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">在GNU的make中，还支持模式变量（Pattern-specific Variable），通过上面的目标变量中，我们知道，变量可以定义在某个目标上。模式变量的好处就是，我们可以给定一种“模式”，可以把变量定义在符合这种模式的所有目标上。</font>
				</p>
				<p>
						<font face="Courier New">我们知道，make的“模式”一般是至少含有一个“%”的，所以，我们可以以如下方式给所有以[.o]结尾的目标定义目标变量：</font>
				</p>
				<p>
						<font face="Courier New">    %.o : CFLAGS = -O</font>
				</p>
				<p>
						<font face="Courier New">同样，模式变量的语法和“目标变量”一样：</font>
				</p>
				<p>
						<font face="Courier New">    &lt;pattern ...&gt; : &lt;variable-assignment&gt;</font>
				</p>
				<p>
						<font face="Courier New">    &lt;pattern ...&gt; : override &lt;variable-assignment&gt;</font>
				</p>
				<p>
						<font face="Courier New">override同样是针对于系统环境传入的变量，或是make命令行指定的变量。<br /> </font>
				</p>
				<p>
						<br />
						<font face="Courier New" size="4">
								<strong>使用条件判断<br />——————</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">使用条件判断，可以让make根据运行时的不同情况选择不同的执行分支。条件表达式可以是比较变量的值，或是比较变量和常量的值。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>一、示例</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">下面的例子，判断$(CC)变量是否“gcc”，如果是的话，则使用GNU函数编译目标。</font>
				</p>
				<p>
						<font face="Courier New">    libs_for_gcc = -lgnu<br />    normal_libs =</font>
				</p>
				<p>
						<font face="Courier New">    foo: $(objects)<br />    ifeq ($(CC),gcc)<br />            $(CC) -o foo $(objects) $(libs_for_gcc)<br />    else<br />            $(CC) -o foo $(objects) $(normal_libs)<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">可见，在上面示例的这个规则中，目标“foo”可以根据变量“$(CC)”值来选取不同的函数库来编译程序。</font>
				</p>
				<p>
						<font face="Courier New">我们可以从上面的示例中看到三个关键字：ifeq、else和endif。ifeq的意思表示条件语句的开始，并指定一个条件表达式，表达式包含两个参数，以逗号分隔，表达式以圆括号括起。else表示条件表达式为假的情况。endif表示一个条件语句的结束，任何一个条件表达式都应该以endif结束。</font>
				</p>
				<p>
						<font face="Courier New">当我们的变量$(CC)值是“gcc”时，目标foo的规则是：</font>
				</p>
				<p>
						<font face="Courier New">    foo: $(objects)<br />            $(CC) -o foo $(objects) $(libs_for_gcc)</font>
				</p>
				<p>
						<font face="Courier New">而当我们的变量$(CC)值不是“gcc”时（比如“cc”），目标foo的规则是：</font>
				</p>
				<p>
						<font face="Courier New">    foo: $(objects)<br />            $(CC) -o foo $(objects) $(normal_libs)</font>
				</p>
				<p>
						<font face="Courier New">当然，我们还可以把上面的那个例子写得更简洁一些：</font>
				</p>
				<p>
						<font face="Courier New">    libs_for_gcc = -lgnu<br />    normal_libs =</font>
				</p>
				<p>
						<font face="Courier New">    ifeq ($(CC),gcc)<br />      libs=$(libs_for_gcc)<br />    else<br />      libs=$(normal_libs)<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">    foo: $(objects)<br />            $(CC) -o foo $(objects) $(libs)</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>二、语法</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">条件表达式的语法为：</font>
				</p>
				<p>
						<font face="Courier New">    &lt;conditional-directive&gt;<br />    &lt;text-if-true&gt;<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">以及：</font>
				</p>
				<p>
						<font face="Courier New">    &lt;conditional-directive&gt;<br />    &lt;text-if-true&gt;<br />    else<br />    &lt;text-if-false&gt;<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">其中&lt;conditional-directive&gt;表示条件关键字，如“ifeq”。这个关键字有四个。</font>
				</p>
				<p>
						<font face="Courier New">第一个是我们前面所见过的“ifeq”</font>
				</p>
				<p>
						<font face="Courier New">    ifeq (&lt;arg1&gt;, &lt;arg2&gt;) <br />    ifeq '&lt;arg1&gt;' '&lt;arg2&gt;' <br />    ifeq "&lt;arg1&gt;" "&lt;arg2&gt;" <br />    ifeq "&lt;arg1&gt;" '&lt;arg2&gt;' <br />    ifeq '&lt;arg1&gt;' "&lt;arg2&gt;" </font>
				</p>
				<p>
						<font face="Courier New">比较参数“arg1”和“arg2”的值是否相同。当然，参数中我们还可以使用make的函数。如：</font>
				</p>
				<p>
						<font face="Courier New">    ifeq ($(strip $(foo)),)<br />    &lt;text-if-empty&gt;<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">这个示例中使用了“strip”函数，如果这个函数的返回值是空（Empty），那么&lt;text-if-empty&gt;就生效。</font>
				</p>
				<p>
						<font face="Courier New">第二个条件关键字是“ifneq”。语法是：</font>
				</p>
				<p>
						<font face="Courier New">    ifneq (&lt;arg1&gt;, &lt;arg2&gt;) <br />    ifneq '&lt;arg1&gt;' '&lt;arg2&gt;' <br />    ifneq "&lt;arg1&gt;" "&lt;arg2&gt;" <br />    ifneq "&lt;arg1&gt;" '&lt;arg2&gt;' <br />    ifneq '&lt;arg1&gt;' "&lt;arg2&gt;" </font>
				</p>
				<p>
						<font face="Courier New">其比较参数“arg1”和“arg2”的值是否相同，如果不同，则为真。和“ifeq”类似。</font>
				</p>
				<p>
						<font face="Courier New">第三个条件关键字是“ifdef”。语法是：</font>
				</p>
				<p>
						<font face="Courier New">    ifdef &lt;variable-name&gt; </font>
				</p>
				<p>
						<font face="Courier New">如果变量&lt;variable-name&gt;的值非空，那到表达式为真。否则，表达式为假。当然，&lt;variable-name&gt;同样可以是一个函数的返回值。注意，ifdef只是测试一个变量是否有值，其并不会把变量扩展到当前位置。还是来看两个例子：</font>
				</p>
				<p>
						<font face="Courier New">    示例一：<br />    bar =<br />    foo = $(bar)<br />    ifdef foo<br />    frobozz = yes<br />    else<br />    frobozz = no<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">    示例二：<br />    foo =<br />    ifdef foo<br />    frobozz = yes<br />    else<br />    frobozz = no<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">第一个例子中，“$(frobozz)”值是“yes”，第二个则是“no”。</font>
				</p>
				<p>
						<font face="Courier New">第四个条件关键字是“ifndef”。其语法是：</font>
				</p>
				<p>
						<font face="Courier New">    ifndef &lt;variable-name&gt;</font>
				</p>
				<p>
						<font face="Courier New">这个我就不多说了，和“ifdef”是相反的意思。</font>
				</p>
				<p>
						<font face="Courier New">在&lt;conditional-directive&gt;这一行上，多余的空格是被允许的，但是不能以[Tab]键做为开始（不然就被认为是命令）。而注释符“#”同样也是安全的。“else”和“endif”也一样，只要不是以[Tab]键开始就行了。</font>
				</p>
				<p>
						<font face="Courier New">特别注意的是，make是在读取Makefile时就计算条件表达式的值，并根据条件表达式的值来选择语句，所以，你最好不要把自动化变量（如“$@”等）放入条件表达式中，因为自动化变量是在运行时才有的。</font>
				</p>
				<p>
						<font face="Courier New">而且，为了避免混乱，make不允许把整个条件语句分成两部分放在不同的文件中。</font>
				</p>
				<br />
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71406.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:29 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71406.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起写 Makefile（九）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71407.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71407.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71407.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71407.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71407.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Courier New" size="3">
						<strong>
								<p id="TBPingURL">Trackback: <a href="http://tb.blog.csdn.net/TrackBack.aspx?PostId=2894">http://tb.blog.csdn.net/TrackBack.aspx?PostId=2894</a><br />使用函数<br />————</p>
						</strong>
				</font>
				<p>
						<font face="Courier New">在Makefile中可以使用函数来处理变量，从而让我们的命令或是规则更为的灵活和具有智能。make所支持的函数也不算很多，不过已经足够我们的操作了。函数调用后，函数的返回值可以当做变量来使用。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>一、函数的调用语法</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">函数调用，很像变量的使用，也是以“$”来标识的，其语法如下：</font>
				</p>
				<p>
						<font face="Courier New">    $(&lt;function&gt; &lt;arguments&gt;)</font>
				</p>
				<p>
						<font face="Courier New">或是</font>
				</p>
				<p>
						<font face="Courier New">    ${&lt;function&gt; &lt;arguments&gt;}</font>
				</p>
				<p>
						<font face="Courier New">这里，&lt;function&gt;就是函数名，make支持的函数不多。&lt;arguments&gt;是函数的参数，参数间以逗号“,”分隔，而函数名和参数之间以“空格”分隔。函数调用以“$”开头，以圆括号或花括号把函数名和参数括起。感觉很像一个变量，是不是？函数中的参数可以使用变量，为了风格的统一，函数和变量的括号最好一样，如使用“$(subst a,b,$(x))”这样的形式，而不是“$(subst a,b,${x})”的形式。因为统一会更清楚，也会减少一些不必要的麻烦。</font>
				</p>
				<p>
						<font face="Courier New">还是来看一个示例：</font>
				</p>
				<p>
						<font face="Courier New">    comma:= ,<br />    empty:=<br />    space:= $(empty) $(empty)<br />    foo:= a b c<br />    bar:= $(subst $(space),$(comma),$(foo))</font>
				</p>
				<p>
						<font face="Courier New">在这个示例中，$(comma)的值是一个逗号。$(space)使用了$(empty)定义了一个空格，$(foo)的值是“a b c”，$(bar)的定义用，调用了函数“subst”，这是一个替换函数，这个函数有三个参数，第一个参数是被替换字串，第二个参数是替换字串，第三个参数是替换操作作用的字串。这个函数也就是把$(foo)中的空格替换成逗号，所以$(bar)的值是“a,b,c”。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>二、字符串处理函数</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(subst &lt;from&gt;,&lt;to&gt;,&lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：字符串替换函数——subst。<br />    功能：把字串&lt;text&gt;中的&lt;from&gt;字符串替换成&lt;to&gt;。<br />    返回：函数返回被替换过后的字符串。</font>
				</p>
				<p>
						<font face="Courier New">    示例：<br />        <br />        $(subst ee,EE,feet on the street)，<br />        <br />        把“feet on the street”中的“ee”替换成“EE”，返回结果是“fEEt on the strEEt”。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>$(patsubst &lt;pattern&gt;,&lt;replacement&gt;,&lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：模式字符串替换函数——patsubst。<br />    功能：查找&lt;text&gt;中的单词（单词以“空格”、“Tab”或“回车”“换行”分隔）是否符合模式&lt;pattern&gt;，如果匹配的话，则以&lt;replacement&gt;替换。这里，&lt;pattern&gt;可以包括通配符“%”，表示任意长度的字串。如果&lt;replacement&gt;中也包含“%”，那么，&lt;replacement&gt;中的这个“%”将是&lt;pattern&gt;中的那个“%”所代表的字串。（可以用“\”来转义，以“\%”来表示真实含义的“%”字符）<br />    返回：函数返回被替换过后的字符串。</font>
				</p>
				<p>
						<font face="Courier New">    示例：</font>
				</p>
				<p>
						<font face="Courier New">        $(patsubst %.c,%.o,x.c.c bar.c)</font>
				</p>
				<p>
						<font face="Courier New">        把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o]，返回结果是“x.c.o bar.o”</font>
				</p>
				<p>
						<font face="Courier New">    备注：</font>
				</p>
				<p>
						<font face="Courier New">        这和我们前面“变量章节”说过的相关知识有点相似。如：<br /><br />        “$(var:&lt;pattern&gt;=&lt;replacement&gt;)”<br />         相当于<br />        “$(patsubst &lt;pattern&gt;,&lt;replacement&gt;,$(var))”，<br /><br />         而“$(var: &lt;suffix&gt;=&lt;replacement&gt;)”<br />         则相当于<br />         “$(patsubst %&lt;suffix&gt;,%&lt;replacement&gt;,$(var))”。<br /><br />         例如有：objects = foo.o bar.o baz.o，<br />         那么，“$(objects:.o=.c)”和“$(patsubst %.o,%.c,$(objects))”是一样的。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(strip &lt;string&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：去空格函数——strip。<br />    功能：去掉&lt;string&gt;字串中开头和结尾的空字符。<br />    返回：返回被去掉空格的字符串值。<br />    示例：<br />        <br />        $(strip a b c )</font>
				</p>
				<p>
						<font face="Courier New">        把字串“a b c ”去到开头和结尾的空格，结果是“a b c”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(findstring &lt;find&gt;,&lt;in&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：查找字符串函数——findstring。<br />    功能：在字串&lt;in&gt;中查找&lt;find&gt;字串。<br />    返回：如果找到，那么返回&lt;find&gt;，否则返回空字符串。<br />    示例：</font>
				</p>
				<p>
						<font face="Courier New">        $(findstring a,a b c)<br />        $(findstring a,b c)</font>
				</p>
				<p>
						<font face="Courier New">        第一个函数返回“a”字符串，第二个返回“”字符串（空字符串）</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(filter &lt;pattern...&gt;,&lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：过滤函数——filter。<br />    功能：以&lt;pattern&gt;模式过滤&lt;text&gt;字符串中的单词，保留符合模式&lt;pattern&gt;的单词。可以有多个模式。<br />    返回：返回符合模式&lt;pattern&gt;的字串。<br />    示例：</font>
				</p>
				<p>
						<font face="Courier New">        sources := foo.c bar.c baz.s ugh.h<br />        foo: $(sources)<br />                cc $(filter %.c %.s,$(sources)) -o foo</font>
				</p>
				<p>
						<font face="Courier New">        $(filter %.c %.s,$(sources))返回的值是“foo.c bar.c baz.s”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(filter-out &lt;pattern...&gt;,&lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：反过滤函数——filter-out。<br />    功能：以&lt;pattern&gt;模式过滤&lt;text&gt;字符串中的单词，去除符合模式&lt;pattern&gt;的单词。可以有多个模式。<br />    返回：返回不符合模式&lt;pattern&gt;的字串。<br />    示例：</font>
				</p>
				<p>
						<font face="Courier New">        objects=main1.o foo.o main2.o bar.o<br />        mains=main1.o main2.o<br />        <br />        $(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o”。<br />        <br /><strong>$(sort &lt;list&gt;)</strong></font>
				</p>
				<p>
						<font face="Courier New">    名称：排序函数——sort。<br />    功能：给字符串&lt;list&gt;中的单词排序（升序）。<br />    返回：返回排序后的字符串。<br />    示例：$(sort foo bar lose)返回“bar foo lose” 。<br />    备注：sort函数会去掉&lt;list&gt;中相同的单词。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(word &lt;n&gt;,&lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：取单词函数——word。<br />    功能：取字符串&lt;text&gt;中第&lt;n&gt;个单词。（从一开始）<br />    返回：返回字符串&lt;text&gt;中第&lt;n&gt;个单词。如果&lt;n&gt;比&lt;text&gt;中的单词数要大，那么返回空字符串。<br />    示例：$(word 2, foo bar baz)返回值是“bar”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(wordlist &lt;s&gt;,&lt;e&gt;,&lt;text&gt;)</strong>  </font>
				</p>
				<p>
						<font face="Courier New">    名称：取单词串函数——wordlist。<br />    功能：从字符串&lt;text&gt;中取从&lt;s&gt;开始到&lt;e&gt;的单词串。&lt;s&gt;和&lt;e&gt;是一个数字。<br />    返回：返回字符串&lt;text&gt;中从&lt;s&gt;到&lt;e&gt;的单词字串。如果&lt;s&gt;比&lt;text&gt;中的单词数要大，那么返回空字符串。如果&lt;e&gt;大于&lt;text&gt;的单词数，那么返回从&lt;s&gt;开始，到&lt;text&gt;结束的单词串。<br />    示例： $(wordlist 2, 3, foo bar baz)返回值是“bar baz”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(words &lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：单词个数统计函数——words。<br />    功能：统计&lt;text&gt;中字符串中的单词个数。<br />    返回：返回&lt;text&gt;中的单词数。<br />    示例：$(words, foo bar baz)返回值是“3”。<br />    备注：如果我们要取&lt;text&gt;中最后的一个单词，我们可以这样：$(word $(words &lt;text&gt;),&lt;text&gt;)。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(firstword &lt;text&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：首单词函数——firstword。<br />    功能：取字符串&lt;text&gt;中的第一个单词。<br />    返回：返回字符串&lt;text&gt;的第一个单词。<br />    示例：$(firstword foo bar)返回值是“foo”。<br />    备注：这个函数可以用word函数来实现：$(word 1,&lt;text&gt;)。</font>
				</p>
				<p>
						<font face="Courier New">以上，是所有的字符串操作函数，如果搭配混合使用，可以完成比较复杂的功能。这里，举一个现实中应用的例子。我们知道，make使用“VPATH”变量来指定“依赖文件”的搜索路径。于是，我们可以利用这个搜索路径来指定编译器对头文件的搜索路径参数CFLAGS，如：</font>
				</p>
				<p>
						<font face="Courier New">    override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))</font>
				</p>
				<p>
						<font face="Courier New">    如果我们的“$(VPATH)”值是“src:../headers”，那么“$(patsubst %,-I%,$(subst :, ,$(VPATH)))”将返回“-Isrc -I../headers”，这正是cc或gcc搜索头文件路径的参数。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>三、文件名操作函数</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">下面我们要介绍的函数主要是处理文件名的。每个函数的参数字符串都会被当做一个或是一系列的文件名来对待。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(dir &lt;names...&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：取目录函数——dir。<br />    功能：从文件名序列&lt;names&gt;中取出目录部分。目录部分是指最后一个反斜杠（“/”）之前的部分。如果没有反斜杠，那么返回“./”。<br />    返回：返回文件名序列&lt;names&gt;的目录部分。<br />    示例： $(dir src/foo.c hacks)返回值是“src/ ./”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(notdir &lt;names...&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：取文件函数——notdir。<br />    功能：从文件名序列&lt;names&gt;中取出非目录部分。非目录部分是指最后一个反斜杠（“/”）之后的部分。<br />    返回：返回文件名序列&lt;names&gt;的非目录部分。<br />    示例： $(notdir src/foo.c hacks)返回值是“foo.c hacks”。<br /> <br /><strong>$(suffix &lt;names...&gt;)</strong><br />    <br />    名称：取后缀函数——suffix。<br />    功能：从文件名序列&lt;names&gt;中取出各个文件名的后缀。<br />    返回：返回文件名序列&lt;names&gt;的后缀序列，如果文件没有后缀，则返回空字串。<br />    示例：$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(basename &lt;names...&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：取前缀函数——basename。<br />    功能：从文件名序列&lt;names&gt;中取出各个文件名的前缀部分。<br />    返回：返回文件名序列&lt;names&gt;的前缀序列，如果文件没有前缀，则返回空字串。<br />    示例：$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar hacks”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(addsuffix &lt;suffix&gt;,&lt;names...&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：加后缀函数——addsuffix。<br />    功能：把后缀&lt;suffix&gt;加到&lt;names&gt;中的每个单词后面。<br />    返回：返回加过后缀的文件名序列。<br />    示例：$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(addprefix &lt;prefix&gt;,&lt;names...&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：加前缀函数——addprefix。<br />    功能：把前缀&lt;prefix&gt;加到&lt;names&gt;中的每个单词后面。<br />    返回：返回加过前缀的文件名序列。<br />    示例：$(addprefix src/,foo bar)返回值是“src/foo src/bar”。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>$(join &lt;list1&gt;,&lt;list2&gt;)</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    名称：连接函数——join。<br />    功能：把&lt;list2&gt;中的单词对应地加到&lt;list1&gt;的单词后面。如果&lt;list1&gt;的单词个数要比&lt;list2&gt;的多，那么，&lt;list1&gt;中的多出来的单词将保持原样。如果&lt;list2&gt;的单词个数要比&lt;list1&gt;多，那么，&lt;list2&gt;多出来的单词将被复制到&lt;list2&gt;中。<br />    返回：返回连接过后的字符串。<br />    示例：$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。</font>
						<font face="宋体, MS Song"> </font>
				</p>
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:29 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起写 Makefile（七）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71405.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:28:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71405.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71405.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71405.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71405.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p>
						<font face="Courier New" size="4">
								<font size="3">
										<a href="http://tb.blog.csdn.net/TrackBack.aspx?PostId=2892">
												<font color="#000000">转自：</font>http://tb.blog.csdn.net/TrackBack.aspx?PostId=2892</a>
								</font>
								<br />
								<strong>使用变量<br />————</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">在Makefile中的定义的变量，就像是C/C++语言中的宏一样，他代表了一个文本字串，在Makefile中执行的时候其会自动原模原样地展开在所使用的地方。其与C/C++所不同的是，你可以在Makefile中改变其值。在Makefile中，变量可以使用在“目标”，“依赖目标”，“命令”或是Makefile的其它部分中。</font>
				</p>
				<p>
						<font face="Courier New">变量的命名字可以包含字符、数字，下划线（可以是数字开头），但不应该含有“:”、“#”、“=”或是空字符（空格、回车等）。变量是大小写敏感的，“foo”、“Foo”和“FOO”是三个不同的变量名。传统的Makefile的变量名是全大写的命名方式，但我推荐使用大小写搭配的变量名，如：MakeFlags。这样可以避免和系统的变量冲突，而发生意外的事情。</font>
				</p>
				<p>
						<font face="Courier New">有一些变量是很奇怪字串，如“$&lt;”、“$@”等，这些是自动化变量，我会在后面介绍。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>一、变量的基础</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">变量在声明时需要给予初值，而在使用时，需要给在变量名前加上“$”符号，但最好用小括号“（）”或是大括号“{}”把变量给包括起来。如果你要使用真实的“$”字符，那么你需要用“$$”来表示。</font>
				</p>
				<p>
						<font face="Courier New">变量可以使用在许多地方，如规则中的“目标”、“依赖”、“命令”以及新的变量中。先看一个例子：</font>
				</p>
				<p>
						<font face="Courier New">    objects = program.o foo.o utils.o<br />    program : $(objects)<br />            cc -o program $(objects)</font>
				</p>
				<p>
						<font face="Courier New">    $(objects) : defs.h</font>
				</p>
				<p>
						<font face="Courier New">变量会在使用它的地方精确地展开，就像C/C++中的宏一样，例如：</font>
				</p>
				<p>
						<font face="Courier New">    foo = c<br />    prog.o : prog.$(foo)<br />            $(foo)$(foo) -$(foo) prog.$(foo)</font>
				</p>
				<p>
						<font face="Courier New">展开后得到：</font>
				</p>
				<p>
						<font face="Courier New">    prog.o : prog.c<br />            cc -c prog.c</font>
				</p>
				<p>
						<font face="Courier New">当然，千万不要在你的Makefile中这样干，这里只是举个例子来表明Makefile中的变量在使用处展开的真实样子。可见其就是一个“替代”的原理。</font>
				</p>
				<p>
						<font face="Courier New">另外，给变量加上括号完全是为了更加安全地使用这个变量，在上面的例子中，如果你不想给变量加上括号，那也可以，但我还是强烈建议你给变量加上括号。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>二、变量中的变量</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">在定义变量的值时，我们可以使用其它变量来构造变量的值，在Makefile中有两种方式来在用变量定义变量的值。</font>
				</p>
				<p>
						<font face="Courier New">先看第一种方式，也就是简单的使用“=”号，在“=”左侧是变量，右侧是变量的值，右侧变量的值可以定义在文件的任何一处，也就是说，右侧中的变量不一定非要是已定义好的值，其也可以使用后面定义的值。如：</font>
				</p>
				<p>
						<font face="Courier New">    foo = $(bar)<br />    bar = $(ugh)<br />    ugh = Huh?</font>
				</p>
				<p>
						<font face="Courier New">    all:<br />            echo $(foo)</font>
				</p>
				<p>
						<font face="Courier New">我们执行“make all”将会打出变量$(foo)的值是“Huh?”（ $(foo)的值是$(bar)，$(bar)的值是$(ugh)，$(ugh)的值是“Huh?”）可见，变量是可以使用后面的变量来定义的。</font>
				</p>
				<p>
						<font face="Courier New">这个功能有好的地方，也有不好的地方，好的地方是，我们可以把变量的真实值推到后面来定义，如：</font>
				</p>
				<p>
						<font face="Courier New">    CFLAGS = $(include_dirs) -O<br />    include_dirs = -Ifoo -Ibar</font>
				</p>
				<p>
						<font face="Courier New">当“CFLAGS”在命令中被展开时，会是“-Ifoo -Ibar -O”。但这种形式也有不好的地方，那就是递归定义，如：</font>
				</p>
				<p>
						<font face="Courier New">    CFLAGS = $(CFLAGS) -O</font>
				</p>
				<p>
						<font face="Courier New">    或：</font>
				</p>
				<p>
						<font face="Courier New">    A = $(B)<br />    B = $(A)</font>
				</p>
				<p>
						<font face="Courier New">这会让make陷入无限的变量展开过程中去，当然，我们的make是有能力检测这样的定义，并会报错。还有就是如果在变量中使用函数，那么，这种方式会让我们的make运行时非常慢，更糟糕的是，他会使用得两个make的函数“wildcard”和“shell”发生不可预知的错误。因为你不会知道这两个函数会被调用多少次。</font>
				</p>
				<p>
						<font face="Courier New">为了避免上面的这种方法，我们可以使用make中的另一种用变量来定义变量的方法。这种方法使用的是“:=”操作符，如：</font>
				</p>
				<p>
						<font face="Courier New">    x := foo<br />    y := $(x) bar<br />    x := later</font>
				</p>
				<p>
						<font face="Courier New">其等价于：</font>
				</p>
				<p>
						<font face="Courier New">    y := foo bar<br />    x := later</font>
				</p>
				<p>
						<font face="Courier New">值得一提的是，这种方法，前面的变量不能使用后面的变量，只能使用前面已定义好了的变量。如果是这样：</font>
				</p>
				<p>
						<font face="Courier New">    y := $(x) bar<br />    x := foo</font>
				</p>
				<p>
						<font face="Courier New">那么，y的值是“bar”，而不是“foo bar”。</font>
				</p>
				<p>
						<font face="Courier New">上面都是一些比较简单的变量使用了，让我们来看一个复杂的例子，其中包括了make的函数、条件表达式和一个系统变量“MAKELEVEL”的使用：</font>
				</p>
				<p>
						<font face="Courier New">    ifeq (0,${MAKELEVEL})<br />    cur-dir   := $(shell pwd)<br />    whoami    := $(shell whoami)<br />    host-type := $(shell arch)<br />    MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">关于条件表达式和函数，我们在后面再说，对于系统变量“MAKELEVEL”，其意思是，如果我们的make有一个嵌套执行的动作（参见前面的“嵌套使用make”），那么，这个变量会记录了我们的当前Makefile的调用层数。</font>
				</p>
				<p>
						<font face="Courier New">下面再介绍两个定义变量时我们需要知道的，请先看一个例子，如果我们要定义一个变量，其值是一个空格，那么我们可以这样来：</font>
				</p>
				<p>
						<font face="Courier New">    nullstring :=<br />    space := $(nullstring) # end of the line</font>
				</p>
				<p>
						<font face="Courier New">nullstring是一个Empty变量，其中什么也没有，而我们的space的值是一个空格。因为在操作符的右边是很难描述一个空格的，这里采用的技术很管用，先用一个Empty变量来标明变量的值开始了，而后面采用“#”注释符来表示变量定义的终止，这样，我们可以定义出其值是一个空格的变量。请注意这里关于“#”的使用，注释符“#”的这种特性值得我们注意，如果我们这样定义一个变量：</font>
				</p>
				<p>
						<font face="Courier New">    dir := /foo/bar    # directory to put the frobs in</font>
				</p>
				<p>
						<font face="Courier New">dir这个变量的值是“/foo/bar”，后面还跟了4个空格，如果我们这样使用这样变量来指定别的目录——“$(dir)/file”那么就完蛋了。</font>
				</p>
				<p>
						<font face="Courier New">还有一个比较有用的操作符是“?=”，先看示例：</font>
				</p>
				<p>
						<font face="Courier New">    FOO ?= bar</font>
				</p>
				<p>
						<font face="Courier New">其含义是，如果FOO没有被定义过，那么变量FOO的值就是“bar”，如果FOO先前被定义过，那么这条语将什么也不做，其等价于：</font>
				</p>
				<p>
						<font face="Courier New">    ifeq ($(origin FOO), undefined)<br />      FOO = bar<br />    endif</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>三、变量高级用法</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">这里介绍两种变量的高级使用方法，第一种是变量值的替换。</font>
				</p>
				<p>
						<font face="Courier New">我们可以替换变量中的共有的部分，其格式是“$(var:a=b)”或是“${var:a=b}”，其意思是，把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。</font>
				</p>
				<p>
						<font face="Courier New">还是看一个示例吧：</font>
				</p>
				<p>
						<font face="Courier New">    foo := a.o b.o c.o<br />    bar := $(foo:.o=.c)</font>
				</p>
				<p>
						<font face="Courier New">这个示例中，我们先定义了一个“$(foo)”变量，而第二行的意思是把“$(foo)”中所有以“.o”字串“结尾”全部替换成“.c”，所以我们的“$(bar)”的值就是“a.c b.c c.c”。</font>
				</p>
				<p>
						<font face="Courier New">另外一种变量替换的技术是以“静态模式”（参见前面章节）定义的，如：</font>
				</p>
				<p>
						<font face="Courier New">    foo := a.o b.o c.o<br />    bar := $(foo:%.o=%.c)</font>
				</p>
				<p>
						<font face="Courier New">这依赖于被替换字串中的有相同的模式，模式中必须包含一个“%”字符，这个例子同样让$(bar)变量的值为“a.c b.c c.c”。 </font>
				</p>
				<p>
						<font face="Courier New">第二种高级用法是——“把变量的值再当成变量”。先看一个例子：</font>
				</p>
				<p>
						<font face="Courier New">    x = y<br />    y = z<br />    a := $($(x))</font>
				</p>
				<p>
						<font face="Courier New">在这个例子中，$(x)的值是“y”，所以$($(x))就是$(y)，于是$(a)的值就是“z”。（注意，是“x=y”，而不是“x=$(y)”）</font>
				</p>
				<p>
						<font face="Courier New">我们还可以使用更多的层次：</font>
				</p>
				<p>
						<font face="Courier New">    x = y<br />    y = z<br />    z = u<br />    a := $($($(x)))</font>
				</p>
				<p>
						<font face="Courier New">这里的$(a)的值是“u”，相关的推导留给读者自己去做吧。</font>
				</p>
				<p>
						<font face="Courier New">让我们再复杂一点，使用上“在变量定义中使用变量”的第一个方式，来看一个例子：</font>
				</p>
				<p>
						<font face="Courier New">    x = $(y)<br />    y = z<br />    z = Hello<br />    a := $($(x))</font>
				</p>
				<p>
						<font face="Courier New">这里的$($(x))被替换成了$($(y))，因为$(y)值是“z”，所以，最终结果是：a:=$(z)，也就是“Hello”。</font>
				</p>
				<p>
						<font face="Courier New">再复杂一点，我们再加上函数：</font>
				</p>
				<p>
						<font face="Courier New">    x = variable1<br />    variable2 := Hello<br />    y = $(subst 1,2,$(x))<br />    z = y<br />    a := $($($(z)))</font>
				</p>
				<p>
						<font face="Courier New">这个例子中，“$($($(z)))”扩展为“$($(y))”，而其再次被扩展为“$($(subst 1,2,$(x)))”。$(x)的值是“variable1”，subst函数把“variable1”中的所有“1”字串替换成“2”字串，于是，“variable1”变成“variable2”，再取其值，所以，最终，$(a)的值就是$(variable2)的值——“Hello”。（喔，好不容易）</font>
				</p>
				<p>
						<font face="Courier New">在这种方式中，或要可以使用多个变量来组成一个变量的名字，然后再取其值：</font>
				</p>
				<p>
						<font face="Courier New">    first_second = Hello<br />    a = first<br />    b = second<br />    all = $($a_$b)</font>
				</p>
				<p>
						<font face="Courier New">这里的“$a_$b”组成了“first_second”，于是，$(all)的值就是“Hello”。</font>
				</p>
				<p>
						<font face="Courier New">再来看看结合第一种技术的例子：</font>
				</p>
				<p>
						<font face="Courier New">    a_objects := a.o b.o c.o<br />    1_objects := 1.o 2.o 3.o</font>
				</p>
				<p>
						<font face="Courier New">    sources := $($(a1)_objects:.o=.c)</font>
				</p>
				<p>
						<font face="Courier New">这个例子中，如果$(a1)的值是“a”的话，那么，$(sources)的值就是“a.c b.c c.c”；如果$(a1)的值是“1”，那么$(sources)的值是“1.c 2.c 3.c”。</font>
				</p>
				<p>
						<font face="Courier New">再来看一个这种技术和“函数”与“条件语句”一同使用的例子：</font>
				</p>
				<p>
						<font face="Courier New">    ifdef do_sort<br />    func := sort<br />    else<br />    func := strip<br />    endif</font>
				</p>
				<p>
						<font face="Courier New">    bar := a d b g q c</font>
				</p>
				<p>
						<font face="Courier New">    foo := $($(func) $(bar))</font>
				</p>
				<p>
						<font face="Courier New">这个示例中，如果定义了“do_sort”，那么：foo := $(sort a d b g q c)，于是$(foo)的值就是“a b c d g q”，而如果没有定义“do_sort”，那么：foo := $(sort a d b g q c)，调用的就是strip函数。</font>
				</p>
				<p>
						<font face="Courier New">当然，“把变量的值再当成变量”这种技术，同样可以用在操作符的左边：</font>
				</p>
				<p>
						<font face="Courier New">    dir = foo<br />    $(dir)_sources := $(wildcard $(dir)/*.c)<br />    define $(dir)_print<br />    lpr $($(dir)_sources)<br />    endef</font>
				</p>
				<p>
						<font face="Courier New">这个例子中定义了三个变量：“dir”，“foo_sources”和“foo_print”。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>四、追加变量值</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">我们可以使用“+=”操作符给变量追加值，如：</font>
				</p>
				<p>
						<font face="Courier New">    objects = main.o foo.o bar.o utils.o<br />    objects += another.o</font>
				</p>
				<p>
						<font face="Courier New">于是，我们的$(objects)值变成：“main.o foo.o bar.o utils.o another.o”（another.o被追加进去了）</font>
				</p>
				<p>
						<font face="Courier New">使用“+=”操作符，可以模拟为下面的这种例子：</font>
				</p>
				<p>
						<font face="Courier New">    objects = main.o foo.o bar.o utils.o<br />    objects := $(objects) another.o</font>
				</p>
				<p>
						<font face="Courier New">所不同的是，用“+=”更为简洁。</font>
				</p>
				<p>
						<font face="Courier New">如果变量之前没有定义过，那么，“+=”会自动变成“=”，如果前面有变量定义，那么“+=”会继承于前次操作的赋值符。如果前一次的是“:=”，那么“+=”会以“:=”作为其赋值符，如：</font>
				</p>
				<p>
						<font face="Courier New">    variable := value<br />    variable += more</font>
				</p>
				<p>
						<font face="Courier New">等价于：</font>
				</p>
				<p>
						<font face="Courier New">    variable := value<br />    variable := $(variable) more</font>
				</p>
				<p>
						<font face="Courier New">但如果是这种情况： </font>
				</p>
				<p>
						<font face="Courier New">    variable = value<br />    variable += more</font>
				</p>
				<p>
						<font face="Courier New">由于前次的赋值符是“=”，所以“+=”也会以“=”来做为赋值，那么岂不会发生变量的递补归定义，这是很不好的，所以make会自动为我们解决这个问题，我们不必担心这个问题。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>五、override 指示符</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">如果有变量是通常make的命令行参数设置的，那么Makefile中对这个变量的赋值会被忽略。如果你想在Makefile中设置这类参数的值，那么，你可以使用“override”指示符。其语法是：</font>
				</p>
				<p>
						<font face="Courier New">    override &lt;variable&gt; = &lt;value&gt;</font>
				</p>
				<p>
						<font face="Courier New">    override &lt;variable&gt; := &lt;value&gt;</font>
				</p>
				<p>
						<font face="Courier New">当然，你还可以追加：</font>
				</p>
				<p>
						<font face="Courier New">    override &lt;variable&gt; += &lt;more text&gt;</font>
				</p>
				<p>
						<font face="Courier New">对于多行的变量定义，我们用define指示符，在define指示符前，也同样可以使用ovveride指示符，如：</font>
				</p>
				<p>
						<font face="Courier New">    override define foo<br />    bar<br />    endef</font>
						<font face="Courier New">
								<br />
						</font>
						<font face="宋体, MS Song"> </font>
				</p>
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:28 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起写 Makefile（六）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71404.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:27:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71404.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71404.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71404.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71404.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71404.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Courier New" size="4">
						<strong>
								<p id="TBPingURL">转自: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2891</p>
								<p>
										<br />书写命令<br />————</p>
						</strong>
				</font>
				<p>
						<font face="Courier New">每条规则中的命令和操作系统Shell的命令行是一致的。make会一按顺序一条一条的执行命令，每条命令的开头必须以[Tab]键开头，除非，命令是紧跟在依赖规则后面的分号后的。在命令行之间中的空格或是空行会被忽略，但是如果该空格或空行是以Tab键开头的，那么make会认为其是一个空命令。</font>
				</p>
				<p>
						<font face="Courier New">我们在UNIX下可能会使用不同的Shell，但是make的命令默认是被“/bin/sh”——UNIX的标准Shell解释执行的。除非你特别指定一个其它的Shell。Makefile中，“#”是注释符，很像C/C++中的“//”，其后的本行字符都被注释。</font>
				</p>
				<p>
						<font face="Courier New">
								<strong>一、显示命令</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">通常，make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前，那么，这个命令将不被make显示出来，最具代表性的例子是，我们用这个功能来像屏幕显示一些信息。如：</font>
				</p>
				<p>
						<font face="Courier New">    @echo 正在编译XXX模块......</font>
				</p>
				<p>
						<font face="Courier New">当make执行时，会输出“正在编译XXX模块......”字串，但不会输出命令，如果没有“@”，那么，make将输出：</font>
				</p>
				<p>
						<font face="Courier New">    echo 正在编译XXX模块......<br />    正在编译XXX模块......</font>
				</p>
				<p>
						<font face="Courier New">如果make执行时，带入make参数“-n”或“--just-print”，那么其只是显示命令，但不会执行命令，这个功能很有利于我们调试我们的Makefile，看看我们书写的命令是执行起来是什么样子的或是什么顺序的。</font>
				</p>
				<p>
						<font face="Courier New">而make参数“-s”或“--slient”则是全面禁止命令的显示。</font>
				</p>
				<p>
						<font face="Courier New">
						</font> </p>
				<p>
						<font face="Courier New">
								<strong>二、命令执行</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">当依赖目标新于目标时，也就是当规则的目标需要被更新时，make会一条一条的执行其后的命令。需要注意的是，如果你要让上一条命令的结果应用在下一条命令时，你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令，你希望第二条命令得在cd之后的基础上运行，那么你就不能把这两条命令写在两行上，而应该把这两条命令写在一行上，用分号分隔。如：</font>
				</p>
				<p>
						<font face="Courier New">    示例一：<br />        exec:<br />                cd /home/hchen<br />                pwd</font>
				</p>
				<p>
						<font face="Courier New">    示例二：<br />        exec:<br />                cd /home/hchen; pwd</font>
				</p>
				<p>
						<font face="Courier New">当我们执行“make exec”时，第一个例子中的cd没有作用，pwd会打印出当前的Makefile目录，而第二个例子中，cd就起作用了，pwd会打印出“/home/hchen”。</font>
				</p>
				<p>
						<font face="Courier New">make一般是使用环境变量SHELL中所定义的系统Shell来执行命令，默认情况下使用UNIX的标准Shell——/bin/sh来执行命令。但在MS-DOS下有点特殊，因为MS-DOS下没有SHELL环境变量，当然你也可以指定。如果你指定了UNIX风格的目录形式，首先，make会在SHELL所指定的路径中找寻命令解释器，如果找不到，其会在当前盘符中的当前目录中寻找，如果再找不到，其会在PATH环境变量中所定义的所有路径中寻找。MS-DOS中，如果你定义的命令解释器没有找到，其会给你的命令解释器加上诸如“.exe”、“.com”、“.bat”、“.sh”等后缀。</font>
				</p>
				<p>
						<br />
						<br />
						<font face="Courier New">
								<strong>三、命令出错</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">每当命令运行完后，make会检测每个命令的返回码，如果命令返回成功，那么make会执行下一条命令，当规则中所有的命令成功返回后，这个规则就算是成功完成了。如果一个规则中的某个命令出错了（命令退出码非零），那么make就会终止执行当前规则，这将有可能终止所有规则的执行。</font>
				</p>
				<p>
						<font face="Courier New">有些时候，命令的出错并不表示就是错误的。例如mkdir命令，我们一定需要建立一个目录，如果目录不存在，那么mkdir就成功执行，万事大吉，如果目录存在，那么就出错了。我们之所以使用mkdir的意思就是一定要有这样的一个目录，于是我们就不希望mkdir出错而终止规则的运行。</font>
				</p>
				<p>
						<font face="Courier New">为了做到这一点，忽略命令的出错，我们可以在Makefile的命令行前加一个减号“-”（在Tab键之后），标记为不管命令出不出错都认为是成功的。如：</font>
				</p>
				<p>
						<font face="Courier New">   clean:<br />            -rm -f *.o</font>
				</p>
				<p>
						<font face="Courier New">还有一个全局的办法是，给make加上“-i”或是“--ignore-errors”参数，那么，Makefile中所有命令都会忽略错误。而如果一个规则是以“.IGNORE”作为目标的，那么这个规则中的所有命令将会忽略错误。这些是不同级别的防止命令出错的方法，你可以根据你的不同喜欢设置。</font>
				</p>
				<p>
						<font face="Courier New">还有一个要提一下的make的参数的是“-k”或是“--keep-going”，这个参数的意思是，如果某规则中的命令出错了，那么就终目该规则的执行，但继续执行其它规则。</font>
				</p>
				<p>
						<br />
						<br />
						<font face="Courier New">
								<strong>四、嵌套执行make</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">在一些大的工程中，我们会把我们不同模块或是不同功能的源文件放在不同的目录中，我们可以在每个目录中都书写一个该目录的Makefile，这有利于让我们的Makefile变得更加地简洁，而不至于把所有的东西全部写在一个Makefile中，这样会很难维护我们的Makefile，这个技术对于我们模块编译和分段编译有着非常大的好处。</font>
				</p>
				<p>
						<font face="Courier New">例如，我们有一个子目录叫subdir，这个目录下有个Makefile文件，来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写：</font>
				</p>
				<p>
						<font face="Courier New">    subsystem:<br />            cd subdir &amp;&amp; $(MAKE)</font>
				</p>
				<p>
						<font face="Courier New">其等价于：</font>
				</p>
				<p>
						<font face="Courier New">    subsystem:<br />            $(MAKE) -C subdir</font>
				</p>
				<p>
						<font face="Courier New">定义$(MAKE)宏变量的意思是，也许我们的make需要一些参数，所以定义成一个变量比较利于维护。这两个例子的意思都是先进入“subdir”目录，然后执行make命令。</font>
				</p>
				<p>
						<font face="Courier New">我们把这个Makefile叫做“总控Makefile”，总控Makefile的变量可以传递到下级的Makefile中（如果你显示的声明），但是不会覆盖下层的Makefile中所定义的变量，除非指定了“-e”参数。</font>
				</p>
				<p>
						<font face="Courier New">如果你要传递变量到下级Makefile中，那么你可以使用这样的声明：</font>
				</p>
				<p>
						<font face="Courier New">    export &lt;variable ...&gt;</font>
				</p>
				<p>
						<font face="Courier New">如果你不想让某些变量传递到下级Makefile中，那么你可以这样声明： </font>
				</p>
				<p>
						<font face="Courier New">    unexport &lt;variable ...&gt;</font>
				</p>
				<p>
						<font face="Courier New">如：<br />    <br />    示例一：</font>
				</p>
				<p>
						<font face="Courier New">        export variable = value</font>
				</p>
				<p>
						<font face="Courier New">        其等价于：</font>
				</p>
				<p>
						<font face="Courier New">        variable = value<br />        export variable</font>
				</p>
				<p>
						<font face="Courier New">        其等价于：</font>
				</p>
				<p>
						<font face="Courier New">        export variable := value</font>
				</p>
				<p>
						<font face="Courier New">        其等价于：</font>
				</p>
				<p>
						<font face="Courier New">        variable := value<br />        export variable</font>
				</p>
				<p>
						<font face="Courier New">    示例二：</font>
				</p>
				<p>
						<font face="Courier New">        export variable += value</font>
				</p>
				<p>
						<font face="Courier New">        其等价于：</font>
				</p>
				<p>
						<font face="Courier New">        variable += value<br />        export variable</font>
				</p>
				<p>
						<font face="Courier New">如果你要传递所有的变量，那么，只要一个export就行了。后面什么也不用跟，表示传递所有的变量。</font>
				</p>
				<p>
						<font face="Courier New">需要注意的是，有两个变量，一个是SHELL，一个是MAKEFLAGS，这两个变量不管你是否export，其总是要传递到下层Makefile中，特别是MAKEFILES变量，其中包含了make的参数信息，如果我们执行“总控Makefile”时有make参数或是在上层Makefile中定义了这个变量，那么MAKEFILES变量将会是这些参数，并会传递到下层Makefile中，这是一个系统级的环境变量。</font>
				</p>
				<p>
						<font face="Courier New">但是make命令中的有几个参数并不往下传递，它们是“-C”,“-f”,“-h”“-o”和“-W”（有关Makefile参数的细节将在后面说明），如果你不想往下层传递参数，那么，你可以这样来：</font>
				</p>
				<p>
						<font face="Courier New">    subsystem:<br />            cd subdir &amp;&amp; $(MAKE) MAKEFLAGS=</font>
				</p>
				<p>
						<font face="Courier New">如果你定义了环境变量MAKEFLAGS，那么你得确信其中的选项是大家都会用到的，如果其中有“-t”,“-n”,和“-q”参数，那么将会有让你意想不到的结果，或许会让你异常地恐慌。</font>
				</p>
				<p>
						<font face="Courier New">还有一个在“嵌套执行”中比较有用的参数，“-w”或是“--print-directory”会在make的过程中输出一些信息，让你看到目前的工作目录。比如，如果我们的下级make目录是“/home/hchen/gnu/make”，如果我们使用“make -w”来执行，那么当进入该目录时，我们会看到：</font>
				</p>
				<p>
						<font face="Courier New">    make: Entering directory `/home/hchen/gnu/make'.</font>
				</p>
				<p>
						<font face="Courier New">而在完成下层make后离开目录时，我们会看到：</font>
				</p>
				<p>
						<font face="Courier New">    make: Leaving directory `/home/hchen/gnu/make'</font>
				</p>
				<p>
						<font face="Courier New">当你使用“-C”参数来指定make下层Makefile时，“-w”会被自动打开的。如果参数中有“-s”（“--slient”）或是“--no-print-directory”，那么，“-w”总是失效的。</font>
				</p>
				<p>
						<br />
						<br />
						<font face="Courier New">
								<strong>五、定义命令包</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">如果Makefile中出现一些相同命令序列，那么我们可以为这些相同的命令序列定义一个变量。定义这种命令序列的语法以“define”开始，以“endef”结束，如：</font>
				</p>
				<p>
						<font face="Courier New">    define run-yacc<br />    yacc $(firstword $^)<br />    mv y.tab.c $@<br />    endef</font>
				</p>
				<p>
						<font face="Courier New">这里，“run-yacc”是这个命令包的名字，其不要和Makefile中的变量重名。在“define”和“endef”中的两行就是命令序列。这个命令包中的第一个命令是运行Yacc程序，因为Yacc程序总是生成“y.tab.c”的文件，所以第二行的命令就是把这个文件改改名字。还是把这个命令包放到一个示例中来看看吧。</font>
				</p>
				<p>
						<font face="Courier New">    foo.c : foo.y<br />            $(run-yacc)</font>
				</p>
				<p>
						<font face="Courier New">我们可以看见，要使用这个命令包，我们就好像使用变量一样。在这个命令包的使用中，命令包“run-yacc”中的“$^”就是“foo.y”，“$@”就是“foo.c”（有关这种以“$”开头的特殊变量，我们会在后面介绍），make在执行命令包时，命令包中的每个命令会被依次独立执行。</font>
				</p>
				<p id="TBPingURL"> </p>
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:27 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转载）跟我一起写 Makefile（五）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71403.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:26:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71403.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71403.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71403.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71403.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Courier New">
						<strong>
								<p id="TBPingURL">转自: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2890</p>
								<p>
										<br />六、多目标</p>
						</strong>
				</font>
				<p>
						<font face="Courier New">Makefile的规则中的目标可以不止一个，其支持多目标，有可能我们的多个目标同时依赖于一个文件，并且其生成的命令大体类似。于是我们就能把其合并起来。当然，多个目标的生成规则的执行命令是同一个，这可能会可我们带来麻烦，不过好在我们的可以使用一个自动化变量“$@”（关于自动化变量，将在后面讲述），这个变量表示着目前规则中所有的目标的集合，这样说可能很抽象，还是看一个例子吧。</font>
				</p>
				<p>
						<font face="Courier New">    bigoutput littleoutput : text.g<br />            generate text.g -$(subst output,,$@) &gt; $@</font>
				</p>
				<p>
						<font face="Courier New">    上述规则等价于：</font>
				</p>
				<p>
						<font face="Courier New">    bigoutput : text.g<br />            generate text.g -big &gt; bigoutput<br />    littleoutput : text.g<br />            generate text.g -little &gt; littleoutput</font>
				</p>
				<p>
						<font face="Courier New">    其中，-$(subst output,,$@)中的“$”表示执行一个Makefile的函数，函数名为subst，后面的为参数。关于函数，将在后面讲述。这里的这个函数是截取字符串的意思，“$@”表示目标的集合，就像一个数组，“$@”依次取出目标，并执于命令。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>七、静态模式</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">静态模式可以更加容易地定义多目标的规则，可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法：</font>
				</p>
				<p>
						<font face="Courier New">    &lt;targets ...&gt;: &lt;target-pattern&gt;: &lt;prereq-patterns ...&gt;<br />            &lt;commands&gt;<br />            ...</font>
				</p>
				<p>
						<br />
						<font face="Courier New">    targets定义了一系列的目标文件，可以有通配符。是目标的一个集合。</font>
				</p>
				<p>
						<font face="Courier New">    target-parrtern是指明了targets的模式，也就是的目标集模式。</font>
				</p>
				<p>
						<font face="Courier New">    prereq-parrterns是目标的依赖模式，它对target-parrtern形成的模式再进行一次依赖目标的定义。</font>
				</p>
				<p>
						<font face="Courier New">这样描述这三个东西，可能还是没有说清楚，还是举个例子来说明一下吧。如果我们的&lt;target-parrtern&gt;定义成“%.o”，意思是我们的&lt;target&gt;集合中都是以“.o”结尾的，而如果我们的&lt;prereq-parrterns&gt;定义成“%.c”，意思是对&lt;target-parrtern&gt;所形成的目标集进行二次定义，其计算方法是，取&lt;target-parrtern&gt;模式中的“%”（也就是去掉了[.o]这个结尾），并为其加上[.c]这个结尾，形成的新集合。</font>
				</p>
				<p>
						<font face="Courier New">所以，我们的“目标模式”或是“依赖模式”中都应该有“%”这个字符，如果你的文件名中有“%”那么你可以使用反斜杠“\”进行转义，来标明真实的“%”字符。</font>
				</p>
				<p>
						<font face="Courier New">看一个例子：</font>
				</p>
				<p>
						<font face="Courier New">    objects = foo.o bar.o</font>
				</p>
				<p>
						<font face="Courier New">    all: $(objects)</font>
				</p>
				<p>
						<font face="Courier New">    $(objects): %.o: %.c<br />            $(CC) -c $(CFLAGS) $&lt; -o $@</font>
				</p>
				<p>
						<font face="Courier New">
								<br />上面的例子中，指明了我们的目标从$object中获取，“%.o”表明要所有以“.o”结尾的目标，也就是“foo.o bar.o”，也就是变量$object集合的模式，而依赖模式“%.c”则取模式“%.o”的“%”，也就是“foo bar”，并为其加下“.c”的后缀，于是，我们的依赖目标就是“foo.c bar.c”。而命令中的“$&lt;”和“$@”则是自动化变量，“$&lt;”表示所有的依赖目标集（也就是“foo.c bar.c”），“$@”表示目标集（也就是“foo.o bar.o”）。于是，上面的规则展开后等价于下面的规则：</font>
				</p>
				<p>
						<font face="Courier New">    foo.o : foo.c<br />            $(CC) -c $(CFLAGS) foo.c -o foo.o<br />    bar.o : bar.c<br />            $(CC) -c $(CFLAGS) bar.c -o bar.o</font>
				</p>
				<p>
						<font face="Courier New">试想，如果我们的“%.o”有几百个，那种我们只要用这种很简单的“静态模式规则”就可以写完一堆规则，实在是太有效率了。“静态模式规则”的用法很灵活，如果用得好，那会一个很强大的功能。再看一个例子：</font>
				</p>
				<p>
						<br />
						<font face="Courier New">    files = foo.elc bar.o lose.o</font>
				</p>
				<p>
						<font face="Courier New">    $(filter %.o,$(files)): %.o: %.c<br />            $(CC) -c $(CFLAGS) $&lt; -o $@<br />    $(filter %.elc,$(files)): %.elc: %.el<br />            emacs -f batch-byte-compile $&lt;</font>
				</p>
				<p>
						<font face="Courier New">
								<br />$(filter %.o,$(files))表示调用Makefile的filter函数，过滤“$filter”集，只要其中模式为“%.o”的内容。其的它内容，我就不用多说了吧。这个例字展示了Makefile中更大的弹性。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>八、自动生成依赖性</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">在Makefile中，我们的依赖关系可能会需要包含一系列的头文件，比如，如果我们的main.c中有一句“#include "defs.h"”，那么我们的依赖关系应该是：</font>
				</p>
				<p>
						<font face="Courier New">    main.o : main.c defs.h</font>
				</p>
				<p>
						<font face="Courier New">但是，如果是一个比较大型的工程，你必需清楚哪些C文件包含了哪些头文件，并且，你在加入或删除头文件时，也需要小心地修改Makefile，这是一个很没有维护性的工作。为了避免这种繁重而又容易出错的事情，我们可以使用C/C++编译的一个功能。大多数的C/C++编译器都支持一个“-M”的选项，即自动找寻源文件中包含的头文件，并生成一个依赖关系。例如，如果我们执行下面的命令：</font>
				</p>
				<p>
						<font face="Courier New">    cc -M main.c</font>
				</p>
				<p>
						<font face="Courier New">其输出是：</font>
				</p>
				<p>
						<font face="Courier New">    main.o : main.c defs.h</font>
				</p>
				<p>
						<font face="Courier New">于是由编译器自动生成的依赖关系，这样一来，你就不必再手动书写若干文件的依赖关系，而由编译器自动生成了。需要提醒一句的是，如果你使用GNU的C/C++编译器，你得用“-MM”参数，不然，“-M”参数会把一些标准库的头文件也包含进来。</font>
				</p>
				<p>
						<font face="Courier New">    gcc -M main.c的输出是：</font>
				</p>
				<p>
						<font face="Courier New">    main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h \<br />         /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \<br />         /usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h \<br />         /usr/include/bits/types.h /usr/include/bits/pthreadtypes.h \<br />         /usr/include/bits/sched.h /usr/include/libio.h \<br />         /usr/include/_G_config.h /usr/include/wchar.h \<br />         /usr/include/bits/wchar.h /usr/include/gconv.h \<br />         /usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h \<br />         /usr/include/bits/stdio_lim.h</font>
				</p>
				<p>
						<br />
						<font face="Courier New">    gcc -MM main.c的输出则是：</font>
				</p>
				<p>
						<font face="Courier New">    main.o: main.c defs.h</font>
				</p>
				<p>
						<font face="Courier New">那么，编译器的这个功能如何与我们的Makefile联系在一起呢。因为这样一来，我们的Makefile也要根据这些源文件重新生成，让Makefile自已依赖于源文件？这个功能并不现实，不过我们可以有其它手段来迂回地实现这一功能。GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中，为每一个“name.c”的文件都生成一个“name.d”的Makefile文件，[.d]文件中就存放对应[.c]文件的依赖关系。</font>
				</p>
				<p>
						<font face="Courier New">于是，我们可以写出[.c]文件和[.d]文件的依赖关系，并让make自动更新或自成[.d]文件，并把其包含在我们的主Makefile中，这样，我们就可以自动化地生成每个文件的依赖关系了。</font>
				</p>
				<p>
						<font face="Courier New">这里，我们给出了一个模式规则来产生[.d]文件：</font>
				</p>
				<p>
						<font face="Courier New">    %.d: %.c<br />            @set -e; rm -f $@; \<br />             $(CC) -M $(CPPFLAGS) $&lt; &gt; </font>
						<a href="mailto:$@.$$$$">
								<font face="Courier New">$@.$$$$</font>
						</a>
						<font face="Courier New">; \<br />             sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' &lt; </font>
						<a href="mailto:$@.$$$$">
								<font face="Courier New">$@.$$$$</font>
						</a>
						<font face="Courier New"> &gt; $@; \<br />             rm -f </font>
						<a href="mailto:$@.$$$$">
								<font face="Courier New">$@.$$$$</font>
						</a>
				</p>
				<p>
						<font face="Courier New">
								<br />这个规则的意思是，所有的[.d]文件依赖于[.c]文件，“rm -f $@”的意思是删除所有的目标，也就是[.d]文件，第二行的意思是，为每个依赖文件“$&lt;”，也就是[.c]文件生成依赖文件，“$@”表示模式“%.d”文件，如果有一个C文件是name.c，那么“%”就是“name”，“$$$$”意为一个随机编号，第二行生成的文件有可能是“name.d.12345”，第三行使用sed命令做了一个替换，关于sed命令的用法请参看相关的使用文档。第四行就是删除临时文件。</font>
				</p>
				<p>
						<font face="Courier New">总而言之，这个模式要做的事就是在编译器生成的依赖关系中加入[.d]文件的依赖，即把依赖关系：</font>
				</p>
				<p>
						<font face="Courier New">    main.o : main.c defs.h</font>
				</p>
				<p>
						<font face="Courier New">转成：</font>
				</p>
				<p>
						<font face="Courier New">    main.o main.d : main.c defs.h</font>
				</p>
				<p>
						<font face="Courier New">于是，我们的[.d]文件也会自动更新了，并会自动生成了，当然，你还可以在这个[.d]文件中加入的不只是依赖关系，包括生成的命令也可一并加入，让每个[.d]文件都包含一个完赖的规则。一旦我们完成这个工作，接下来，我们就要把这些自动生成的规则放进我们的主Makefile中。我们可以使用Makefile的“include”命令，来引入别的Makefile文件（前面讲过），例如：</font>
				</p>
				<p>
						<font face="Courier New">    sources = foo.c bar.c</font>
				</p>
				<p>
						<font face="Courier New">    include $(sources:.c=.d)</font>
				</p>
				<p>
						<font face="Courier New">上述语句中的“$(sources:.c=.d)”中的“.c=.d”的意思是做一个替换，把变量$(sources)所有[.c]的字串都替换成[.d]，关于这个“替换”的内容，在后面我会有更为详细的讲述。当然，你得注意次序，因为include是按次来载入文件，最先载入的[.d]文件中的目标会成为默认目标。</font>
				</p>
				<br />
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:26 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）跟我一起学make四</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/23/71402.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Fri, 22 Sep 2006 16:24:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/23/71402.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71402.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/23/71402.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71402.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font face="Courier New" size="4">
						<strong>
								<p id="TBPingURL">转自: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2889</p>
								<p>
										<br />书写规则<br />————</p>
						</strong>
				</font>
				<p>
						<font face="Courier New">规则包含两个部分，一个是依赖关系，一个是生成目标的方法。</font>
				</p>
				<p>
						<font face="Courier New">在Makefile中，规则的顺序是很重要的，因为，Makefile中只应该有一个最终目标，其它的目标都是被这个目标所连带出来的，所以一定要让make知道你的最终目标是什么。一般来说，定义在Makefile中的目标可能会有很多，但是第一条规则中的目标将被确立为最终的目标。如果第一条规则中的目标有很多个，那么，第一个目标会成为最终的目标。make所完成的也就是这个目标。</font>
				</p>
				<p>
						<font face="Courier New">好了，还是让我们来看一看如何书写规则。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>一、规则举例</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">    foo.o : foo.c defs.h       # foo模块<br />            cc -c -g foo.c</font>
				</p>
				<p>
						<font face="Courier New">看到这个例子，各位应该不是很陌生了，前面也已说过，foo.o是我们的目标，foo.c和defs.h是目标所依赖的源文件，而只有一个命令“cc -c -g foo.c”（以Tab键开头）。这个规则告诉我们两件事：</font>
				</p>
				<p>
						<font face="Courier New">    1、文件的依赖关系，foo.o依赖于foo.c和defs.h的文件，如果foo.c和defs.h的文件日期要比foo.o文件日期要新，或是foo.o不存在，那么依赖关系发生。<br />    2、如果生成（或更新）foo.o文件。也就是那个cc命令，其说明了，如何生成foo.o这个文件。（当然foo.c文件include了defs.h文件）</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>二、规则的语法</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">      targets : prerequisites<br />        command<br />        ...</font>
				</p>
				<p>
						<font face="Courier New">      或是这样： </font>
				</p>
				<p>
						<font face="Courier New">      targets : prerequisites ; command<br />            command<br />            ...</font>
				</p>
				<p>
						<font face="Courier New">targets是文件名，以空格分开，可以使用通配符。一般来说，我们的目标基本上是一个文件，但也有可能是多个文件。</font>
				</p>
				<p>
						<font face="Courier New">command是命令行，如果其不与“target:prerequisites”在一行，那么，必须以[Tab键]开头，如果和prerequisites在一行，那么可以用分号做为分隔。（见上）</font>
				</p>
				<p>
						<font face="Courier New">prerequisites也就是目标所依赖的文件（或依赖目标）。如果其中的某个文件要比目标文件要新，那么，目标就被认为是“过时的”，被认为是需要重生成的。这个在前面已经讲过了。</font>
				</p>
				<p>
						<font face="Courier New">如果命令太长，你可以使用反斜框（‘\’）作为换行符。make对一行上有多少个字符没有限制。规则告诉make两件事，文件的依赖关系和如何成成目标文件。</font>
				</p>
				<p>
						<font face="Courier New">一般来说，make会以UNIX的标准Shell，也就是/bin/sh来执行命令。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>三、在规则中使用通配符</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">如果我们想定义一系列比较类似的文件，我们很自然地就想起使用通配符。make支持三各通配符：“*”，“?”和“[...]”。这是和Unix的B-Shell是相同的。</font>
				</p>
				<p>
						<font face="Courier New">波浪号（“~”）字符在文件名中也有比较特殊的用途。如果是“~/test”，这就表示当前用户的$HOME目录下的test目录。而“~hchen/test”则表示用户hchen的宿主目录下的test目录。（这些都是Unix下的小知识了，make也支持）而在Windows或是MS-DOS下，用户没有宿主目录，那么波浪号所指的目录则根据环境变量“HOME”而定。</font>
				</p>
				<p>
						<font face="Courier New">通配符代替了你一系列的文件，如“*.c”表示所以后缀为c的文件。一个需要我们注意的是，如果我们的文件名中有通配符，如：“*”，那么可以用转义字符“\”，如“\*”来表示真实的“*”字符，而不是任意长度的字符串。</font>
				</p>
				<p>
						<font face="Courier New">好吧，还是先来看几个例子吧：</font>
				</p>
				<p>
						<font face="Courier New">    clean:<br />         rm -f *.o</font>
				</p>
				<p>
						<font face="Courier New">    上面这个例子我不不多说了，这是操作系统Shell所支持的通配符。这是在命令中的通配符。</font>
				</p>
				<p>
						<font face="Courier New">    print: *.c<br />         lpr -p $?<br />         touch print</font>
				</p>
				<p>
						<font face="Courier New">    上面这个例子说明了通配符也可以在我们的规则中，目标print依赖于所有的[.c]文件。其中的“$?”是一个自动化变量，我会在后面给你讲述。</font>
				</p>
				<p>
						<font face="Courier New">    objects = *.o</font>
				</p>
				<p>
						<font face="Courier New">    上面这个例子，表示了，通符同样可以用在变量中。并不是说[*.o]会展开，不！objects的值就是“*.o”。Makefile中的变量其实就是C/C++中的宏。如果你要让通配符在变量中展开，也就是让objects的值是所有[.o]的文件名的集合，那么，你可以这样：</font>
				</p>
				<p>
						<font face="Courier New">    objects := $(wildcard *.o)</font>
				</p>
				<p>
						<font face="Courier New">这种用法由关键字“wildcard”指出，关于Makefile的关键字，我们将在后面讨论。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>四、文件搜寻</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">在一些大的工程中，有大量的源文件，我们通常的做法是把这许多的源文件分类，并存放在不同的目录中。所以，当make需要去找寻文件的依赖关系时，你可以在文件前加上路径，但最好的方法是把一个路径告诉make，让make在自动去找。</font>
				</p>
				<p>
						<font face="Courier New">Makefile文件中的特殊变量“VPATH”就是完成这个功能的，如果没有指明这个变量，make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量，那么，make就会在当当前目录找不到的情况下，到所指定的目录中去找寻文件了。</font>
				</p>
				<p>
						<font face="Courier New">    VPATH = src:../headers</font>
				</p>
				<p>
						<font face="Courier New">上面的的定义指定两个目录，“src”和“../headers”，make会按照这个顺序进行搜索。目录由“冒号”分隔。（当然，当前目录永远是最高优先搜索的地方）</font>
				</p>
				<p>
						<font face="Courier New">另一个设置文件搜索路径的方法是使用make的“vpath”关键字（注意，它是全小写的），这不是变量，这是一个make的关键字，这和上面提到的那个VPATH变量很类似，但是它更为灵活。它可以指定不同的文件在不同的搜索目录中。这是一个很灵活的功能。它的使用方法有三种：</font>
				</p>
				<p>
						<font face="Courier New">    1、vpath &lt;pattern&gt; &lt;directories&gt;</font>
				</p>
				<p>
						<font face="Courier New">    为符合模式&lt;pattern&gt;的文件指定搜索目录&lt;directories&gt;。</font>
				</p>
				<p>
						<font face="Courier New">    2、vpath &lt;pattern&gt;</font>
				</p>
				<p>
						<font face="Courier New">    清除符合模式&lt;pattern&gt;的文件的搜索目录。</font>
				</p>
				<p>
						<font face="Courier New">    3、vpath</font>
				</p>
				<p>
						<font face="Courier New">    清除所有已被设置好了的文件搜索目录。</font>
				</p>
				<p>
						<font face="Courier New">vapth使用方法中的&lt;pattern&gt;需要包含“%”字符。“%”的意思是匹配零或若干字符，例如，“%.h”表示所有以“.h”结尾的文件。&lt;pattern&gt;指定了要搜索的文件集，而&lt;directories&gt;则指定了&lt;pattern&gt;的文件集的搜索的目录。例如：</font>
				</p>
				<p>
						<font face="Courier New">    vpath %.h ../headers</font>
				</p>
				<p>
						<font face="Courier New">该语句表示，要求make在“../headers”目录下搜索所有以“.h”结尾的文件。（如果某文件在当前目录没有找到的话）</font>
				</p>
				<p>
						<font face="Courier New">我们可以连续地使用vpath语句，以指定不同搜索策略。如果连续的vpath语句中出现了相同的&lt;pattern&gt;，或是被重复了的&lt;pattern&gt;，那么，make会按照vpath语句的先后顺序来执行搜索。如：</font>
				</p>
				<p>
						<font face="Courier New">    vpath %.c foo<br />    vpath %   blish<br />    vpath %.c bar</font>
				</p>
				<p>
						<font face="Courier New">其表示“.c”结尾的文件，先在“foo”目录，然后是“blish”，最后是“bar”目录。</font>
				</p>
				<p>
						<font face="Courier New">    vpath %.c foo:bar<br />    vpath %   blish</font>
				</p>
				<p>
						<font face="Courier New">而上面的语句则表示“.c”结尾的文件，先在“foo”目录，然后是“bar”目录，最后才是“blish”目录。</font>
				</p>
				<p>
						<br />
						<font face="Courier New">
								<strong>五、伪目标</strong>
						</font>
				</p>
				<p>
						<font face="Courier New">最早先的一个例子中，我们提到过一个“clean”的目标，这是一个“伪目标”，</font>
				</p>
				<p>
						<font face="Courier New">    clean:<br />            rm *.o temp</font>
				</p>
				<p>
						<font face="Courier New">正像我们前面例子中的“clean”一样，即然我们生成了许多文件编译文件，我们也应该提供一个清除它们的“目标”以备完整地重编译而用。 （以“make clean”来使用该目标）</font>
				</p>
				<p>
						<font face="Courier New">因为，我们并不生成“clean”这个文件。“伪目标”并不是一个文件，只是一个标签，由于“伪目标”不是文件，所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。当然，“伪目标”的取名不能和文件名重名，不然其就失去了“伪目标”的意义了。</font>
				</p>
				<p>
						<font face="Courier New">当然，为了避免和文件重名的这种情况，我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”，向make说明，不管是否有这个文件，这个目标就是“伪目标”。</font>
				</p>
				<p>
						<font face="Courier New">    .PHONY : clean</font>
				</p>
				<p>
						<font face="Courier New">只要有这个声明，不管是否有“clean”文件，要运行“clean”这个目标，只有“make clean”这样。于是整个过程可以这样写：</font>
				</p>
				<p>
						<font face="Courier New">     .PHONY: clean<br />    clean:<br />            rm *.o temp</font>
				</p>
				<p>
						<font face="Courier New">伪目标一般没有依赖的文件。但是，我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”，只要将其放在第一个。一个示例就是，如果你的Makefile需要一口气生成若干个可执行文件，但你只想简单地敲一个make完事，并且，所有的目标文件都写在一个Makefile中，那么你可以使用“伪目标”这个特性：</font>
				</p>
				<p>
						<font face="Courier New">    all : prog1 prog2 prog3<br />    .PHONY : all</font>
				</p>
				<p>
						<font face="Courier New">    prog1 : prog1.o utils.o<br />            cc -o prog1 prog1.o utils.o</font>
				</p>
				<p>
						<font face="Courier New">    prog2 : prog2.o<br />            cc -o prog2 prog2.o</font>
				</p>
				<p>
						<font face="Courier New">    prog3 : prog3.o sort.o utils.o<br />            cc -o prog3 prog3.o sort.o utils.o</font>
				</p>
				<p>
						<font face="Courier New">我们知道，Makefile中的第一个目标会被作为其默认目标。我们声明了一个“all”的伪目标，其依赖于其它三个目标。由于伪目标的特性是，总是被执行的，所以其依赖的那三个目标就总是不如“all”这个目标新。所以，其它三个目标的规则总是会被决议。也就达到了我们一口气生成多个目标的目的。“.PHONY : all”声明了“all”这个目标为“伪目标”。</font>
				</p>
				<p>
						<font face="Courier New">随便提一句，从上面的例子我们可以看出，目标也可以成为依赖。所以，伪目标同样也可成为依赖。看下面的例子：</font>
				</p>
				<p>
						<font face="Courier New">    .PHONY: cleanall cleanobj cleandiff</font>
				</p>
				<p>
						<font face="Courier New">    cleanall : cleanobj cleandiff<br />            rm program</font>
				</p>
				<p>
						<font face="Courier New">    cleanobj :<br />            rm *.o</font>
				</p>
				<p>
						<font face="Courier New">    cleandiff :<br />            rm *.diff</font>
				</p>
				<p>
						<font face="Courier New">“make clean”将清除所有要被清除的文件。“cleanobj”和“cleandiff”这两个伪目标有点像“子程序”的意思。我们可以输入“make cleanall”和“make cleanobj”和“make cleandiff”命令来达到清除不同种类文件的目的。</font>
						<br />
				</p>
		</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-23 00:24 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/23/71402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>