﻿<?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>C++博客-Qt programing</title><link>http://www.cppblog.com/qcylxfy/</link><description>MFC Qt</description><language>zh-cn</language><lastBuildDate>Tue, 14 Apr 2026 23:09:20 GMT</lastBuildDate><pubDate>Tue, 14 Apr 2026 23:09:20 GMT</pubDate><ttl>60</ttl><item><title>Visual C++/MFC入门教程</title><link>http://www.cppblog.com/qcylxfy/archive/2010/03/02/108747.html</link><dc:creator>丁念念</dc:creator><author>丁念念</author><pubDate>Tue, 02 Mar 2010 14:35:00 GMT</pubDate><guid>http://www.cppblog.com/qcylxfy/archive/2010/03/02/108747.html</guid><wfw:comment>http://www.cppblog.com/qcylxfy/comments/108747.html</wfw:comment><comments>http://www.cppblog.com/qcylxfy/archive/2010/03/02/108747.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qcylxfy/comments/commentRss/108747.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qcylxfy/services/trackbacks/108747.html</trackback:ping><description><![CDATA[<span class=large><font color=#000000>&nbsp;
<p align=left>目录 <br>+-- 第一章 VC入门<br>|------ 1.1 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_11.html" target=_blank><u><font color=#0000ff>如何学好VC</font></u></a><br>|------ 1.2 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_12.html" target=_blank><u><font color=#0000ff>理解Windows消息机制</font></u></a><br>|------ 1.3 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_13.html" target=_blank><u><font color=#0000ff>利用Visual C++/MFC开发Windows程序的优势</font></u></a><br>|------ 1.4 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_14.html" target=_blank><u><font color=#0000ff>利用MFC进行开发的通用方法介绍</font></u></a><br>|------ 1.5 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_15.html" target=_blank><u><font color=#0000ff>MFC中常用类，宏，函数介绍</font></u></a><br>+-- 第二章 图形输出<br>|------ 2.1 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_21.html" target=_blank><u><font color=#0000ff>和GUI有关的各种对象</font></u></a><br>|------ 2.2 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_22.html" target=_blank><u><font color=#0000ff>在窗口中输出文字</font></u></a><br>|------ 2.3 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_23.html" target=_blank><u><font color=#0000ff>使用点，刷子，笔进行绘图</font></u></a><br>|------ 2.4 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_24.html" target=_blank><u><font color=#0000ff>在窗口中绘制设备相关位图，图标，设备无关位图</font></u></a><br>|------ 2.5 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_25.html" target=_blank><u><font color=#0000ff>使用各种映射方式</font></u></a><br>|------ 2.6 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_26.html" target=_blank><u><font color=#0000ff>多边形和剪贴区域</font></u></a><br>+-- 第三章 文档视结构<br>|------ 3.1 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_31.html" target=_blank><u><font color=#0000ff>文档 视图 框架窗口间的关系和消息传送规律</font></u></a><br>|------ 3.2 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_32.html" target=_blank><u><font color=#0000ff>接收用户输入</font></u></a><br>|------ 3.3 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_33.html" target=_blank><u><font color=#0000ff>使用菜单</font></u></a><br>|------ 3.4 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_34.html" target=_blank><u><font color=#0000ff>文档，视，框架之间相互作用</font></u></a><br>|------ 3.5 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_35.html" target=_blank><u><font color=#0000ff>利用序列化进行文件读写</font></u></a><br>|------ 3.6 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_36.html" target=_blank><u><font color=#0000ff>MFC中所提供的各种视类介绍</font></u></a><br>+-- 第四章 窗口控件<br>|------ 4.1 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_41.html" target=_blank><u><font color=#0000ff>Button</font></u></a><br>|------ 4.2 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_42.html" target=_blank><u><font color=#0000ff>Static Box</font></u></a><br>|------ 4.3 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_43.html" target=_blank><u><font color=#0000ff>Edit Box</font></u></a><br>|------ 4.4 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_44.html" target=_blank><u><font color=#0000ff>Scroll Bar</font></u></a><br>|------ 4.5 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_45.html" target=_blank><u><font color=#0000ff>List Box/Check List Box</font></u></a><br>|------ 4.6 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_46.html" target=_blank><u><font color=#0000ff>Combo Box/Combo Box Ex</font></u></a><br>|------ 4.7 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_47.html" target=_blank><u><font color=#0000ff>Tree Ctrl</font></u></a><br>|------ 4.8 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_48.html" target=_blank><u><font color=#0000ff>List Ctrl</font></u></a><br>|------ 4.9 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_49.html" target=_blank><u><font color=#0000ff>Tab Ctrl</font></u></a><br>|------ 4.A <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_4a.html" target=_blank><u><font color=#0000ff>Tool Bar</font></u></a><br>|------ 4.B <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_4b.html" target=_blank><u><font color=#0000ff>Status Bar</font></u></a><br>|------ 4.C <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_4c.html" target=_blank><u><font color=#0000ff>Dialog Bar</font></u></a><br>|------ 4.D <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_4d.html" target=_blank><u><font color=#0000ff>利用AppWizard创建并使用ToolBar StatusBar Dialog Bar</font></u></a><br>|------ 4.E <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_4e.html" target=_blank><u><font color=#0000ff>General Window</font></u></a><br>|------ 4.F <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_4f.html" target=_blank><u><font color=#0000ff>关于WM_NOTIFY的使用方法</font></u></a><br>+-- 第五章 对话框<br>|------ 5.1 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_51.html" target=_blank><u><font color=#0000ff>使用资源编辑器编辑对话框</font></u></a><br>|------ 5.2 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_52.html" target=_blank><u><font color=#0000ff>创建有模式对话框</font></u></a><br>|------ 5.3 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_53.html" target=_blank><u><font color=#0000ff>创建无模式对话框</font></u></a><br>|------ 5.4 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_54.html" target=_blank><u><font color=#0000ff>在对话框中进行消息映射</font></u></a><br>|------ 5.5 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_55.html" target=_blank><u><font color=#0000ff>在对话框中进行数据交换和数据检查</font></u></a><br>|------ 5.6 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_56.html" target=_blank><u><font color=#0000ff>使用属性对话框</font></u></a><br>|------ 5.7 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_57.html" target=_blank><u><font color=#0000ff>使用通用对话框</font></u></a><br>|------ 5.8 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_58.html" target=_blank><u><font color=#0000ff>建立以对话框为基础的应用</font></u></a><br>|------ 5.9 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_59.html" target=_blank><u><font color=#0000ff>使用对话框作为子窗口</font></u></a><br>+-- 第六章 网络通信开发<br>|------ 6.1 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_61.html" target=_blank><u><font color=#0000ff>WinSock介绍</font></u></a><br>|------ 6.2 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_62.html" target=_blank><u><font color=#0000ff>利用WinSock进行无连接的通信</font></u></a><br>+------ 6.3 <a href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_63.html" target=_blank><u><font color=#0000ff>利用WinSock建立有连接的通信</font></u></a></p>
<p><u><font color=#0000ff></font></u></p>
<p>&nbsp;</p>
<p>　　《<a href="http://www.vchelp.net/" target=_blank><u><font color=#0000ff>Visual C++开发指南</font></u></a>》 闻怡洋/文 </p>
</font></span><!-- #EndEditable -->
<img src ="http://www.cppblog.com/qcylxfy/aggbug/108747.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qcylxfy/" target="_blank">丁念念</a> 2010-03-02 22:35 <a href="http://www.cppblog.com/qcylxfy/archive/2010/03/02/108747.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我希望在RHEL3下使用2.96的gcc中的g++来编译我的软件，怎么做？</title><link>http://www.cppblog.com/qcylxfy/archive/2010/01/31/106868.html</link><dc:creator>丁念念</dc:creator><author>丁念念</author><pubDate>Sun, 31 Jan 2010 02:10:00 GMT</pubDate><guid>http://www.cppblog.com/qcylxfy/archive/2010/01/31/106868.html</guid><wfw:comment>http://www.cppblog.com/qcylxfy/comments/106868.html</wfw:comment><comments>http://www.cppblog.com/qcylxfy/archive/2010/01/31/106868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qcylxfy/comments/commentRss/106868.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qcylxfy/services/trackbacks/106868.html</trackback:ping><description><![CDATA[<p>[英文原文] <a class=jive-link-wiki-small href="http://kbase.redhat.com/faq/docs/DOC-8188">I need the gcc 2.96 version of g++ to compile a program on Red Hat Enterprise Linux 3, where can I get it?</a></p>
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<p>RHEL3提供了一个compat-gcc-c+<em>的软件包，它包括含了g</em>+296，提供对gcc 2.96的支持。</p>
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<p>可以用up2date来安装：</p>
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<!--[codeblockstart:1e73d670-4f49-4a15-ae49-51c6aec8dd98]-->
<pre class=jive-pre><code class=jive-code>
# up2date -i compat-gcc-c++
</code></pre>
<!--[codeblockend:1e73d670-4f49-4a15-ae49-51c6aec8dd98]-->
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<p>当然也可以从RHN网站下载或者从光盘进行手工rpm命令安装。</p>
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<p>但是需要注意的是compat-gcc也需要安装，如果使用up2date来安装compat-gcc-c++，compat-gcc包作为依赖的包将被自动下载和安装，如果使用rpm命令手工安装，可以一次安装两个：</p>
<br><!--[codeblockstart:9f1664f1-dc29-42dc-a5c4-c468724547b8]-->
<pre class=jive-pre><code class=jive-code>
# rpm -ivh compat-gcc-c++-&lt;version&gt;.rpm; compat-gcc-&lt;version&gt;.rpm
</code></pre>
<!--[codeblockend:9f1664f1-dc29-42dc-a5c4-c468724547b8]-->
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<p>为了验证这些包，可以用rpm命令查看这些软件包提供了哪些文件：</p>
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<!--[codeblockstart:e54603b4-9d77-47cf-80f0-f0c3af5aea09]-->
<pre class=jive-pre><code class=jive-code>
# rpm -ql compat-gcc-c++
&nbsp; /usr/bin/g++296
&nbsp; /usr/bin/i386-redhat-linux7-c++
&nbsp; /usr/bin/i386-redhat-linux7-g++
&nbsp; /usr/lib/gcc-lib
&nbsp; ...
</code></pre>
<!--[codeblockend:e54603b4-9d77-47cf-80f0-f0c3af5aea09]-->
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<p>g++296版本可以用下面命令来确认：</p>
<p style="PADDING-BOTTOM: 0px; MIN-HEIGHT: 8pt; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 8pt; PADDING-TOP: 0px">&nbsp;</p>
<!--[codeblockstart:af6ed955-0065-4635-b363-5eca7d224881]-->
<pre class=jive-pre><code class=jive-code>
# g++296 -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux7/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-128)
</code></pre>
<img src ="http://www.cppblog.com/qcylxfy/aggbug/106868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qcylxfy/" target="_blank">丁念念</a> 2010-01-31 10:10 <a href="http://www.cppblog.com/qcylxfy/archive/2010/01/31/106868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[精华] 跟我一起写 Makefile</title><link>http://www.cppblog.com/qcylxfy/archive/2010/01/30/106843.html</link><dc:creator>丁念念</dc:creator><author>丁念念</author><pubDate>Sat, 30 Jan 2010 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/qcylxfy/archive/2010/01/30/106843.html</guid><wfw:comment>http://www.cppblog.com/qcylxfy/comments/106843.html</wfw:comment><comments>http://www.cppblog.com/qcylxfy/archive/2010/01/30/106843.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/qcylxfy/comments/commentRss/106843.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qcylxfy/services/trackbacks/106843.html</trackback:ping><description><![CDATA[<br>陈皓 <br><br>概述 <br>—— <br><br>什么是makefile？或许很多Winodws的程序员都不知道这个东西，因为那些Windows的IDE都为你做了这个工作，但我觉得要作一个好的和professional的程序员，makefile还是要懂。这就好像现在有这么多的HTML的编辑器，但如果你想成为一个专业人士，你还是要了解HTML的标识的含义。特别在Unix下的软件编译，你就不能不自己写makefile了，会不会写makefile，从一个侧面说明了一个人是否具备完成大型工程的能力。 <br><br>因为，makefile关系到了整个工程的编译规则。一个工程中的源文件不计数，其按类型、功能、模块分别放在若干个目录中，makefile定义了一系列的规则来指定，哪些文件需要先编译，哪些文件需要后编译，哪些文件需要重新编译，甚至于进行更复杂的功能操作，因为makefile就像一个Shell脚本一样，其中也可以执行操作系统的命令。 <br><br>makefile带来的好处就是——&#8220;自动化编译&#8221;，一旦写好，只需要一个make命令，整个工程完全自动编译，极大的提高了软件开发的效率。make是一个命令工具，是一个解释makefile中指令的命令工具，一般来说，大多数的IDE都有这个命令，比如：Delphi的make，Visual&nbsp;C++的nmake，Linux下GNU的make。可见，makefile都成为了一种在工程方面的编译方法。 <br><br>现在讲述如何写makefile的文章比较少，这是我想写这篇文章的原因。当然，不同产商的make各不相同，也有不同的语法，但其本质都是在&#8220;文件依赖性&#8221;上做文章，这里，我仅对GNU的make进行讲述，我的环境是RedHat&nbsp;Linux&nbsp;8.0，make的版本是3.80。必竟，这个make是应用最为广泛的，也是用得最多的。而且其还是最遵循于IEEE&nbsp;1003.2-1992&nbsp;标准的（POSIX.2）。 <br><br>在这篇文档中，将以C/C++的源码作为我们基础，所以必然涉及一些关于C/C++的编译的知识，相关于这方面的内容，还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。 <br><br>&nbsp; <br><br>关于程序的编译和链接 <br>—————————— <br><br>在此，我想多说关于程序编译的一些规范和方法，一般来说，无论是C、C++、还是pas，首先要把源文件编译成中间代码文件，在Windows下也就是&nbsp;.obj&nbsp;文件，UNIX下是&nbsp;.o&nbsp;文件，即&nbsp;Object&nbsp;File，这个动作叫做编译（compile）。然后再把大量的Object&nbsp;File合成执行文件，这个动作叫作链接（link）。 <br><br>编译时，编译器需要的是语法的正确，函数与变量的声明的正确。对于后者，通常是你需要告诉编译器头文件的所在位置（头文件中应该只是声明，而定义应该放在C/C++文件中），只要所有的语法正确，编译器就可以编译出中间目标文件。一般来说，每个源文件都应该对应于一个中间目标文件（O文件或是OBJ文件）。 <br><br>链接时，主要是链接函数和全局变量，所以，我们可以使用这些中间目标文件（O文件或是OBJ文件）来链接我们的应用程序。链接器并不管函数所在的源文件，只管函数的中间目标文件（Object&nbsp;File），在大多数时候，由于源文件太多，编译生成的中间目标文件太多，而在链接时需要明显地指出中间目标文件名，这对于编译很不方便，所以，我们要给中间目标文件打个包，在Windows下这种包叫&#8220;库文件&#8221;（Library&nbsp;File)，也就是&nbsp;.lib&nbsp;文件，在UNIX下，是Archive&nbsp;File，也就是&nbsp;.a&nbsp;文件。 <br><br>总结一下，源文件首先会生成中间目标文件，再由中间目标文件生成执行文件。在编译时，编译器只检测程序语法，和函数、变量是否被声明。如果函数未被声明，编译器会给出一个警告，但可以生成Object&nbsp;File。而在链接程序时，链接器会在所有的Object&nbsp;File中找寻函数的实现，如果找不到，那到就会报链接错误码（Linker&nbsp;Error），在VC下，这种错误一般是：Link&nbsp;2001错误，意思说是说，链接器未能找到函数的实现。你需要指定函数的Object&nbsp;File. <br><br>好，言归正传，GNU的make有许多的内容，闲言少叙，还是让我们开始吧。 <br><br>&nbsp; <br><br>Makefile&nbsp;介绍 <br>——————— <br><br>make命令执行时，需要一个&nbsp;Makefile&nbsp;文件，以告诉make命令需要怎么样的去编译和链接程序。 <br><br>首先，我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册，在这个示例中，我们的工程有8个C文件，和3个头文件，我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是： <br>&nbsp;&nbsp;&nbsp;&nbsp;1）如果这个工程没有编译过，那么我们的所有C文件都要编译并被链接。 <br>&nbsp;&nbsp;&nbsp;&nbsp;2）如果这个工程的某几个C文件被修改，那么我们只编译被修改的C文件，并链接目标程序。 <br>&nbsp;&nbsp;&nbsp;&nbsp;3）如果这个工程的头文件被改变了，那么我们需要编译引用了这几个头文件的C文件，并链接目标程序。 <br><br>只要我们的Makefile写得够好，所有的这一切，我们只用一个make命令就可以完成，make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译，从而自己编译所需要的文件和链接目标程序。 <br><br><br>一、Makefile的规则 <br><br>在讲述这个Makefile之前，还是让我们先来粗略地看一看Makefile的规则。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;target&nbsp;...&nbsp;:&nbsp;prerequisites&nbsp;... <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;command <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... <br><br>&nbsp;&nbsp;&nbsp;&nbsp;target也就是一个目标文件，可以是Object&nbsp;File，也可以是执行文件。还可以是一个标签（Label），对于标签这种特性，在后续的&#8220;伪目标&#8221;章节中会有叙述。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;prerequisites就是，要生成那个target所需要的文件或是目标。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;command也就是make需要执行的命令。（任意的Shell命令） <br><br>这是一个文件的依赖关系，也就是说，target这一个或多个的目标文件依赖于prerequisites中的文件，其生成规则定义在command中。说白一点就是说，prerequisites中如果有一个以上的文件比target文件要新的话，command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。 <br><br>说到底，Makefile的东西就是这样一点，好像我的这篇文档也该结束了。呵呵。还不尽然，这是Makefile的主线和核心，但要写好一个Makefile还不够，我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。：） <br><br><br>二、一个示例 <br><br>正如前面所说的，如果一个工程有3个头文件，和8个C文件，我们为了完成前面所述的那三个规则，我们的Makefile应该是下面的这个样子的。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;edit&nbsp;:&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-o&nbsp;edit&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;:&nbsp;main.c&nbsp;defs.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;main.c <br>&nbsp;&nbsp;&nbsp;&nbsp;kbd.o&nbsp;:&nbsp;kbd.c&nbsp;defs.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;kbd.c <br>&nbsp;&nbsp;&nbsp;&nbsp;command.o&nbsp;:&nbsp;command.c&nbsp;defs.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;command.c <br>&nbsp;&nbsp;&nbsp;&nbsp;display.o&nbsp;:&nbsp;display.c&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;display.c <br>&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;:&nbsp;insert.c&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;insert.c <br>&nbsp;&nbsp;&nbsp;&nbsp;search.o&nbsp;:&nbsp;search.c&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;search.c <br>&nbsp;&nbsp;&nbsp;&nbsp;files.o&nbsp;:&nbsp;files.c&nbsp;defs.h&nbsp;buffer.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;files.c <br>&nbsp;&nbsp;&nbsp;&nbsp;utils.o&nbsp;:&nbsp;utils.c&nbsp;defs.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;utils.c <br>&nbsp;&nbsp;&nbsp;&nbsp;clean&nbsp;: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;edit&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>反斜杠（\）是换行符的意思。这样比较便于Makefile的易读。我们可以把这个内容保存在文件为&#8220;Makefile&#8221;或&#8220;makefile&#8221;的文件中，然后在该目录下直接输入命令&#8220;make&#8221;就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件，那么，只要简单地执行一下&#8220;make&nbsp;clean&#8221;就可以了。 <br><br>在这个makefile中，目标文件（target）包含：执行文件edit和中间目标文件（*.o），依赖文件（prerequisites）就是冒号后面的那些&nbsp;.c&nbsp;文件和&nbsp;.h文件。每一个&nbsp;.o&nbsp;文件都有一组依赖文件，而这些&nbsp;.o&nbsp;文件又是执行文件&nbsp;edit&nbsp;的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的，换言之，目标文件是哪些文件更新的。 <br><br>在定义好依赖关系后，后续的那一行定义了如何生成目标文件的操作系统命令，一定要以一个Tab键作为开头。记住，make并不管命令是怎么工作的，他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期，如果prerequisites文件的日期要比targets文件的日期要新，或者target不存在的话，那么，make就会执行后续定义的命令。 <br><br>这里要说明一点的是，clean不是一个文件，它只不过是一个动作名字，有点像C语言中的lable一样，其冒号后什么也没有，那么，make就不会自动去找文件的依赖性，也就不会自动执行其后所定义的命令。要执行其后的命令，就要在make命令后明显得指出这个lable的名字。这样的方法非常有用，我们可以在一个makefile中定义不用的编译或是和编译无关的命令，比如程序的打包，程序的备份，等等。<br><br><strong>&nbsp;</strong><strong><br></strong>三、make是如何工作的 <br><br>在默认的方式下，也就是我们只输入make命令。那么， <br><br>&nbsp;&nbsp;&nbsp;&nbsp;1、make会在当前目录下找名字叫&#8220;Makefile&#8221;或&#8220;makefile&#8221;的文件。 <br>&nbsp;&nbsp;&nbsp;&nbsp;2、如果找到，它会找文件中的第一个目标文件（target），在上面的例子中，他会找到&#8220;edit&#8221;这个文件，并把这个文件作为最终的目标文件。 <br>&nbsp;&nbsp;&nbsp;&nbsp;3、如果edit文件不存在，或是edit所依赖的后面的&nbsp;.o&nbsp;文件的文件修改时间要比edit这个文件新，那么，他就会执行后面所定义的命令来生成edit这个文件。 <br>&nbsp;&nbsp;&nbsp;&nbsp;4、如果edit所依赖的.o文件也存在，那么make会在当前文件中找目标为.o文件的依赖性，如果找到则再根据那一个规则生成.o文件。（这有点像一个堆栈的过程） <br>&nbsp;&nbsp;&nbsp;&nbsp;5、当然，你的C文件和H文件是存在的啦，于是make会生成&nbsp;.o&nbsp;文件，然后再用&nbsp;.o&nbsp;文件生命make的终极任务，也就是执行文件edit了。 <br><br>这就是整个make的依赖性，make会一层又一层地去找文件的依赖关系，直到最终编译出第一个目标文件。在找寻的过程中，如果出现错误，比如最后被依赖的文件找不到，那么make就会直接退出，并报错，而对于所定义的命令的错误，或是编译不成功，make根本不理。make只管文件的依赖性，即，如果在我找了依赖关系之后，冒号后面的文件还是不在，那么对不起，我就不工作啦。 <br><br>通过上述分析，我们知道，像clean这种，没有被第一个目标文件直接或间接关联，那么它后面所定义的命令将不会被自动执行，不过，我们可以显示要make执行。即命令——&#8220;make&nbsp;clean&#8221;，以此来清除所有的目标文件，以便重编译。 <br><br>于是在我们编程中，如果这个工程已被编译过了，当我们修改了其中一个源文件，比如file.c，那么根据我们的依赖性，我们的目标file.o会被重编译（也就是在这个依性关系后面所定义的命令），于是file.o的文件也是最新的啦，于是file.o的文件修改时间要比edit要新，所以edit也会被重新链接了（详见edit目标文件后定义的命令）。 <br><br>而如果我们改变了&#8220;command.h&#8221;，那么，kdb.o、command.o和files.o都会被重编译，并且，edit会被重链接。 <br><br><br>四、makefile中使用变量 <br><br>在上面的例子中，先让我们看看edit的规则： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;edit&nbsp;:&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-o&nbsp;edit&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>我们可以看到[.o]文件的字符串被重复了两次，如果我们的工程需要加入一个新的[.o]文件，那么我们需要在两个地方加（应该是三个地方，还有一个地方在clean中）。当然，我们的makefile并不复杂，所以在两个地方加也不累，但如果makefile变得复杂，那么我们就有可能会忘掉一个需要加入的地方，而导致编译失败。所以，为了makefile的易维护，在makefile中我们可以使用变量。makefile的变量也就是一个字符串，理解成C语言中的宏可能会更好。 <br><br>比如，我们声明一个变量，叫objects,&nbsp;OBJECTS,&nbsp;objs,&nbsp;OBJS,&nbsp;obj,&nbsp;或是&nbsp;OBJ，反正不管什么啦，只要能够表示obj文件就行了。我们在makefile一开始就这样定义： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects&nbsp;=&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>于是，我们就可以很方便地在我们的makefile中以&#8220;$(objects)&#8221;的方式来使用这个变量了，于是我们的改良版makefile就变成下面这个样子： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;objects&nbsp;=&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>&nbsp;&nbsp;&nbsp;&nbsp;edit&nbsp;:&nbsp;$(objects) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-o&nbsp;edit&nbsp;$(objects) <br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;:&nbsp;main.c&nbsp;defs.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;main.c <br>&nbsp;&nbsp;&nbsp;&nbsp;kbd.o&nbsp;:&nbsp;kbd.c&nbsp;defs.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;kbd.c <br>&nbsp;&nbsp;&nbsp;&nbsp;command.o&nbsp;:&nbsp;command.c&nbsp;defs.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;command.c <br>&nbsp;&nbsp;&nbsp;&nbsp;display.o&nbsp;:&nbsp;display.c&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;display.c <br>&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;:&nbsp;insert.c&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;insert.c <br>&nbsp;&nbsp;&nbsp;&nbsp;search.o&nbsp;:&nbsp;search.c&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;search.c <br>&nbsp;&nbsp;&nbsp;&nbsp;files.o&nbsp;:&nbsp;files.c&nbsp;defs.h&nbsp;buffer.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;files.c <br>&nbsp;&nbsp;&nbsp;&nbsp;utils.o&nbsp;:&nbsp;utils.c&nbsp;defs.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-c&nbsp;utils.c <br>&nbsp;&nbsp;&nbsp;&nbsp;clean&nbsp;: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;edit&nbsp;$(objects) <br><br><br>于是如果有新的&nbsp;.o&nbsp;文件加入，我们只需简单地修改一下&nbsp;objects&nbsp;变量就可以了。 <br><br>关于变量更多的话题，我会在后续给你一一道来。 <br><br><br>五、让make自动推导 <br><br>GNU的make很强大，它可以自动推导文件以及文件依赖关系后面的命令，于是我们就没必要去在每一个[.o]文件后都写上类似的命令，因为，我们的make会自动识别，并自己推导命令。 <br><br>只要make看到一个[.o]文件，它就会自动的把[.c]文件加在依赖关系中，如果make找到一个whatever.o，那么whatever.c，就会是whatever.o的依赖文件。并且&nbsp;cc&nbsp;-c&nbsp;whatever.c&nbsp;也会被推导出来，于是，我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。 <br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;objects&nbsp;=&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>&nbsp;&nbsp;&nbsp;&nbsp;edit&nbsp;:&nbsp;$(objects) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-o&nbsp;edit&nbsp;$(objects) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;:&nbsp;defs.h <br>&nbsp;&nbsp;&nbsp;&nbsp;kbd.o&nbsp;:&nbsp;defs.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;command.o&nbsp;:&nbsp;defs.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;display.o&nbsp;:&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;:&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;search.o&nbsp;:&nbsp;defs.h&nbsp;buffer.h <br>&nbsp;&nbsp;&nbsp;&nbsp;files.o&nbsp;:&nbsp;defs.h&nbsp;buffer.h&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;utils.o&nbsp;:&nbsp;defs.h <br><br>&nbsp;&nbsp;&nbsp;&nbsp;.PHONY&nbsp;:&nbsp;clean <br>&nbsp;&nbsp;&nbsp;&nbsp;clean&nbsp;: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;edit&nbsp;$(objects) <br><br>这种方法，也就是make的&#8220;隐晦规则&#8221;。上面文件内容中，&#8220;.PHONY&#8221;表示，clean是个伪目标文件。 <br><br>关于更为详细的&#8220;隐晦规则&#8221;和&#8220;伪目标文件&#8221;，我会在后续给你一一道来。 <br><br><br>六、另类风格的makefile <br><br>即然我们的make可以自动推导命令，那么我看到那堆[.o]和[.h]的依赖就有点不爽，那么多的重复的[.h]，能不能把其收拢起来，好吧，没有问题，这个对于make来说很容易，谁叫它提供了自动推导命令和文件的功能呢？来看看最新风格的makefile吧。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;objects&nbsp;=&nbsp;main.o&nbsp;kbd.o&nbsp;command.o&nbsp;display.o&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;utils.o <br><br>&nbsp;&nbsp;&nbsp;&nbsp;edit&nbsp;:&nbsp;$(objects) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-o&nbsp;edit&nbsp;$(objects) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;$(objects)&nbsp;:&nbsp;defs.h <br>&nbsp;&nbsp;&nbsp;&nbsp;kbd.o&nbsp;command.o&nbsp;files.o&nbsp;:&nbsp;command.h <br>&nbsp;&nbsp;&nbsp;&nbsp;display.o&nbsp;insert.o&nbsp;search.o&nbsp;files.o&nbsp;:&nbsp;buffer.h <br><br>&nbsp;&nbsp;&nbsp;&nbsp;.PHONY&nbsp;:&nbsp;clean <br>&nbsp;&nbsp;&nbsp;&nbsp;clean&nbsp;: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;edit&nbsp;$(objects) <br><br>这种风格，让我们的makefile变得很简单，但我们的文件依赖关系就显得有点凌乱了。鱼和熊掌不可兼得。还看你的喜好了。我是不喜欢这种风格的，一是文件的依赖关系看不清楚，二是如果文件一多，要加入几个新的.o文件，那就理不清楚了。 <br><br><br>七、清空目标文件的规则 <br><br>每个Makefile中都应该写一个清空目标文件（.o和执行文件）的规则，这不仅便于重编译，也很利于保持文件的清洁。这是一个&#8220;修养&#8221;（呵呵，还记得我的《编程修养》吗）。一般的风格都是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clean: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;edit&nbsp;$(objects) <br><br>更为稳健的做法是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.PHONY&nbsp;:&nbsp;clean <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clean&nbsp;: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-rm&nbsp;edit&nbsp;$(objects) <br><br>前面说过，.PHONY意思表示clean是一个&#8220;伪目标&#8221;，。而在rm命令前面加了一个小减号的意思就是，也许某些文件出现问题，但不要管，继续做后面的事。当然，clean的规则不要放在文件的开头，不然，这就会变成make的默认目标，相信谁也不愿意这样。不成文的规矩是——&#8220;clean从来都是放在文件的最后&#8221;。 <br><br><br>上面就是一个makefile的概貌，也是makefile的基础，下面还有很多makefile的相关细节，准备好了吗？准备好了就来。&nbsp;<br><br><br><strong>&nbsp;</strong><a href="http://bbs.chinaunix.net/viewpro.php?uid=73892" target=_blank><font color=#0000ff><u><strong>gunguymadman</strong></u></font></a><strong> 回复于：2004-09-16 12:18:58<br><br></strong>一、Makefile里有什么？ <br><br>Makefile里主要包含了五个东西：显式规则、隐晦规则、变量定义、文件指示和注释。 <br><br>1、显式规则。显式规则说明了，如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出，要生成的文件，文件的依赖文件，生成的命令。 <br><br>2、隐晦规则。由于我们的make有自动推导的功能，所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile，这是由make所支持的。 <br><br>3、变量的定义。在Makefile中我们要定义一系列的变量，变量一般都是字符串，这个有点你C语言中的宏，当Makefile被执行时，其中的变量都会被扩展到相应的引用位置上。 <br><br>4、文件指示。其包括了三个部分，一个是在一个Makefile中引用另一个Makefile，就像C语言中的include一样；另一个是指根据某些情况指定Makefile中的有效部分，就像C语言中的预编译#if一样；还有就是定义一个多行的命令。有关这一部分的内容，我会在后续的部分中讲述。 <br><br>5、注释。Makefile中只有行注释，和UNIX的Shell脚本一样，其注释是用&#8220;#&#8221;字符，这个就像C/C++中的&#8220;//&#8221;一样。如果你要在你的Makefile中使用&#8220;#&#8221;字符，可以用反斜框进行转义，如：&#8220;\#&#8221;。 <br><br>最后，还值得一提的是，在Makefile中的命令，必须要以[Tab]键开始。 <br><br><br>二、Makefile的文件名 <br><br>默认的情况下，make命令会在当前目录下按顺序找寻文件名为&#8220;GNUmakefile&#8221;、&#8220;makefile&#8221;、&#8220;Makefile&#8221;的文件，找到了解释这个文件。在这三个文件名中，最好使用&#8220;Makefile&#8221;这个文件名，因为，这个文件名第一个字符为大写，这样有一种显目的感觉。最好不要用&#8220;GNUmakefile&#8221;，这个文件是GNU的make识别的。有另外一些make只对全小写的&#8220;makefile&#8221;文件名敏感，但是基本上来说，大多数的make都支持&#8220;makefile&#8221;和&#8220;Makefile&#8221;这两种默认文件名。 <br><br>当然，你可以使用别的文件名来书写Makefile，比如：&#8220;Make.Linux&#8221;，&#8220;Make.Solaris&#8221;，&#8220;Make.AIX&#8221;等，如果要指定特定的Makefile，你可以使用make的&#8220;-f&#8221;和&#8220;--file&#8221;参数，如：make&nbsp;-f&nbsp;Make.Linux或make&nbsp;--file&nbsp;Make.AIX。 <br><br><br>三、引用其它的Makefile <br><br>在Makefile使用include关键字可以把别的Makefile包含进来，这很像C语言的#include，被包含的文件会原模原样的放在当前文件的包含位置。include的语法是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;include&nbsp;&lt;filename&gt;; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;filename可以是当前操作系统Shell的文件模式（可以保含路径和通配符） <br><br>在include前面可以有一些空字符，但是绝不能是[Tab]键开始。include和&lt;filename&gt;;可以用一个或多个空格隔开。举个例子，你有这样几个Makefile：a.mk、b.mk、c.mk，还有一个文件叫foo.make，以及一个变量$(bar)，其包含了e.mk和f.mk，那么，下面的语句： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;include&nbsp;foo.make&nbsp;*.mk&nbsp;$(bar) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;等价于： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;include&nbsp;foo.make&nbsp;a.mk&nbsp;b.mk&nbsp;c.mk&nbsp;e.mk&nbsp;f.mk <br><br>make命令开始时，会把找寻include所指出的其它Makefile，并把其内容安置在当前的位置。就好像C/C++的#include指令一样。如果文件都没有指定绝对路径或是相对路径的话，make会在当前目录下首先寻找，如果当前目录下没有找到，那么，make还会在下面的几个目录下找： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;1、如果make执行时，有&#8220;-I&#8221;或&#8220;--include-dir&#8221;参数，那么make就会在这个参数所指定的目录下去寻找。 <br>&nbsp;&nbsp;&nbsp;&nbsp;2、如果目录&lt;prefix&gt;;/include（一般是：/usr/local/bin或/usr/include）存在的话，make也会去找。 <br><br>如果有文件没有找到的话，make会生成一条警告信息，但不会马上出现致命错误。它会继续载入其它的文件，一旦完成makefile的读取，make会再重试这些没有找到，或是不能读取的文件，如果还是不行，make才会出现一条致命信息。如果你想让make不理那些无法读取的文件，而继续执行，你可以在include前加一个减号&#8220;-&#8221;。如： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;-include&nbsp;&lt;filename&gt;; <br>&nbsp;&nbsp;&nbsp;&nbsp;其表示，无论include过程中出现什么错误，都不要报错继续执行。和其它版本make兼容的相关命令是sinclude，其作用和这一个是一样的。 <br><br><br>四、环境变量&nbsp;MAKEFILES&nbsp; <br><br>如果你的当前环境中定义了环境变量MAKEFILES，那么，make会把这个变量中的值做一个类似于include的动作。这个变量中的值是其它的Makefile，用空格分隔。只是，它和include不同的是，从这个环境变中引入的Makefile的&#8220;目标&#8221;不会起作用，如果环境变量中定义的文件发现错误，make也会不理。 <br><br>但是在这里我还是建议不要使用这个环境变量，因为只要这个变量一被定义，那么当你使用make时，所有的Makefile都会受到它的影响，这绝不是你想看到的。在这里提这个事，只是为了告诉大家，也许有时候你的Makefile出现了怪事，那么你可以看看当前环境中有没有定义这个变量。 <br><br><br>五、make的工作方式 <br><br>GNU的make工作时的执行步骤入下：（想来其它的make也是类似） <br><br>&nbsp;&nbsp;&nbsp;&nbsp;1、读入所有的Makefile。 <br>&nbsp;&nbsp;&nbsp;&nbsp;2、读入被include的其它Makefile。 <br>&nbsp;&nbsp;&nbsp;&nbsp;3、初始化文件中的变量。 <br>&nbsp;&nbsp;&nbsp;&nbsp;4、推导隐晦规则，并分析所有规则。 <br>&nbsp;&nbsp;&nbsp;&nbsp;5、为所有的目标文件创建依赖关系链。 <br>&nbsp;&nbsp;&nbsp;&nbsp;6、根据依赖关系，决定哪些目标要重新生成。 <br>&nbsp;&nbsp;&nbsp;&nbsp;7、执行生成命令。 <br><br>1-5步为第一个阶段，6-7为第二个阶段。第一个阶段中，如果定义的变量被使用了，那么，make会把其展开在使用的位置。但make并不会完全马上展开，make使用的是拖延战术，如果变量出现在依赖关系的规则中，那么仅当这条依赖被决定要使用了，变量才会在其内部展开。 <br><br>当然，这个工作方式你不一定要清楚，但是知道这个方式你也会对make更为熟悉。有了这个基础，后续部分也就容易看懂了。<br><br><br>
<img src ="http://www.cppblog.com/qcylxfy/aggbug/106843.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qcylxfy/" target="_blank">丁念念</a> 2010-01-30 20:41 <a href="http://www.cppblog.com/qcylxfy/archive/2010/01/30/106843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux GTK+界面编程(转)</title><link>http://www.cppblog.com/qcylxfy/archive/2010/01/29/106694.html</link><dc:creator>丁念念</dc:creator><author>丁念念</author><pubDate>Fri, 29 Jan 2010 01:35:00 GMT</pubDate><guid>http://www.cppblog.com/qcylxfy/archive/2010/01/29/106694.html</guid><wfw:comment>http://www.cppblog.com/qcylxfy/comments/106694.html</wfw:comment><comments>http://www.cppblog.com/qcylxfy/archive/2010/01/29/106694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qcylxfy/comments/commentRss/106694.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qcylxfy/services/trackbacks/106694.html</trackback:ping><description><![CDATA[<div class=tit></div>
<table style="WIDTH: 100%; TABLE-LAYOUT: fixed" class=FCK__ShowTableBorders>
    <tbody>
        <tr>
            <td>
            <div class=cnt>
            <p style="TEXT-INDENT: 2em"><a href="http://hi.baidu.com/michael_lyx/blog/item/a75d594acbef00fa83025c42.html" target=_blank><u><font color=#810081>Linux 操作系统下GTK+界面编程——第一个程序</font></u></a></p>
            <p style="TEXT-INDENT: 2em">今天，开始在工作之余，抽出时间来学习linux界面编程。我计划在未来的半年内，学会 linux下的GTK+界面编程。这个文档作为我学习linux编程的第一个文档，同时它也将上传到我163邮箱所附带的博客中去。所以，我会尽量做的详 细一点。以后还会有关于linux界面编程之类的学习笔记会被记录并上传到博客中。</p>
            <p style="TEXT-INDENT: 2em">我所用的linux版本是Red Hat 9.0</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">第一个程序——Hello,World</p>
            <p style="TEXT-INDENT: 2em">在开始写第一个程序之前，需要做一点基本操作。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">我登陆linux使用的是root用户（根用户，也叫超级用户）。所以，所有笔记中产生的截图，均是root用户下的。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">一、在linux桌面点击右键，在快捷菜单中选择&#8220;新建终端&#8221;选项，打开类似DOS的窗口。</p>
            <p style="TEXT-INDENT: 2em">二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用mkdir命令创建一个文件夹，文件夹命名为gtkgui,命令输入为：mkdir gtkgui&nbsp;&nbsp; 如图1.2所示</p>
            <p style="TEXT-INDENT: 2em">输入完毕后敲回车键即可创建目录gtkgui,需要注意的是该目录的路径是：/root/gtktui</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">三、使用cd命令进入目录gtkgui&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命令输入：cd gtkgui</p>
            <p style="TEXT-INDENT: 2em">输入命令后敲回车键即可进入目录gtkgui&nbsp;&nbsp;</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">四、创建第一个程序存放的目录，和第一步一样，这次在gtkgui目录下创建一个子目录1gui 然后进入1gui目录。创建目录命令：mkdir 1gui&nbsp;&nbsp; 进入目录命令：cd lgui 命令界面输入。</p>
            <p style="TEXT-INDENT: 2em">(注意1gui第一个字符是&#8220;一&#8221;，不是小写的L)。</p>
            <p style="TEXT-INDENT: 2em">小提示：若你想查看当前目录的绝对路径。可以在终端敲入命令：pwd </p>
            <p style="TEXT-INDENT: 2em">现在可以清楚的看到当前工作目录是&#8220;/root/gtkgui/1gui&#8221;。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">五、编写代码，在开始写第一个程序之前，说说VI编辑器。假设要写的程序是firstgui.c</p>
            <p style="TEXT-INDENT: 2em">，则在终端中敲入 vi firstgui.c&nbsp;&nbsp; 然后回车，就进入编辑文件firstgui.c状态了，VI命令后面的文件若存在，则直接打开，若不存在，则新建一个。进入文件编辑状态后，必须按a键， 才可向文件输入东西，当编辑完后，按esc键退出编辑模式，再按shift+;键，最后输入wq（write and quit）退出VI。好了，在写程序中，再说一遍就记住了。</p>
            <p style="TEXT-INDENT: 2em">1、 创建 firstgui.c并编辑它</p>
            <p style="TEXT-INDENT: 2em">命令：vi first.c&nbsp;&nbsp; 然后敲回车进入编辑模式</p>
            <p style="TEXT-INDENT: 2em">必须先按下 a 键（还有其他的键也可（如i键），不过我觉得按下a键比较方便）才可输入字符，现在按一下a键，终端变成图1.8所示的效果。</p>
            <p style="TEXT-INDENT: 2em">按一下a键后（注意左下方有个--插入--），进入编辑模式</p>
            <p style="TEXT-INDENT: 2em">现在开始输入第一个程序的代码，代码原型如下：</p>
            <p style="TEXT-INDENT: 2em">#include &lt;gtk/gtk.h&gt;</p>
            <p style="TEXT-INDENT: 2em">int main(int argc,char*argv[])</p>
            <p style="TEXT-INDENT: 2em">{</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GtkWidget *window;</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gtk_init(&amp;argc,&amp;argv);</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window=gtk_window_new(GKT_WINDOW_TOPLEVEL);</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gtk_window_set_title(GTK_WINDOW(window),&#8221;Hello,World&#8221;);</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gtk_widget_show(window);</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gtk_main();</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</p>
            <p style="TEXT-INDENT: 2em">}</p>
            <p style="TEXT-INDENT: 2em">现在代码输入完毕，需要保存文件并推出编辑器，先按一下esc键退出编辑模式，然后按组合键：shift+;键 最后输入wq并敲回车键就保存了文件并退出编辑模式了。退出VI后的界面如图1.20所示。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">使用ll命令（小写的LL）查看刚才编写的firstgui.c是否存在。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">若想看文件内容，使用cat firstgui.c 命令就可看到文件firstgui.c的内容了。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">六、编译代码</p>
            <p style="TEXT-INDENT: 2em">在终端敲入下列命令及参数，编译连接程序</p>
            <p style="TEXT-INDENT: 2em">命令及参数：gcc firstgui.c -o firstgui `pkg-config --cflags --libs gtk+-2.0`</p>
            <p style="TEXT-INDENT: 2em">命令说明：&nbsp;&nbsp;&nbsp; gcc 编译命令</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; firstgui.c 源程序文件名</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -o 编译参数，（不是0（零），是opq的o）</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; firstgui 编译连接后的可执行文件名，可以为任意合法的文件名</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; `&nbsp;&nbsp; 这个符号是和~呆在一起的那个键上，不要误认为是单引号&#8216;</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pkg后面与-config之间没有空格</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cflags 前面是两个短线 --</p>
            <p style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; libs前面也是两个短线 --</p>
            <p style="TEXT-INDENT: 2em">七、运行程序</p>
            <p style="TEXT-INDENT: 2em">键入 ./firstgui 后回车便可看到效果了。</p>
            <p style="TEXT-INDENT: 2em">需要注意的是，该程序当你点击窗口右上角上的小X关闭窗口时，窗口倒是关闭了。但是程序还在运行，你必须在终端下按组合键：Ctrl+c来关闭进程。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">八、程序分析</p>
            <p style="TEXT-INDENT: 2em">GtkWidget *window; 相当于Windows下的</p>
            <p style="TEXT-INDENT: 2em">WNDCLASS</p>
            <p style="TEXT-INDENT: 2em">结构体，不过window在此只是一个窗口指针，用于指向函数gtk_window_new()函数返回的窗口地址而已。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">gtk_init(&amp;argc,&amp;argv); </p>
            <p style="TEXT-INDENT: 2em">初始化界面库等一系列操作的函数，当其调用失败时，其将终止我们的程序，目前只要记住在编写任何窗口函数之前，都保证该函数是第一个被调用的就行了。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">window=gtk_window_new(GTK_WINDOW_TOPLEVEL);</p>
            <p style="TEXT-INDENT: 2em">该函数创建一个新的GtkWidget对象（目前我认为其就是创建了一个还没有显示的窗 口），并返回该对象的指针。该函数参数仅有两个，其中一个是上面的GTK_WINDOW_TOPLEVEL,表示创建一个&#8220;主窗口&#8221;，另一个则是 GTK_WINDOW_POPUP，表示创建一个弹出窗口。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">gtk_window_set_title(GTK_WINDOW(window),&#8221;Hello,World&#8221;);该函数设置窗口的标题。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">gtk_widget_show(window); 该函数将窗口显示出来。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">gtk_main();该函数捕获一些消息吧。在没有调用函数gtk_main_quit()函数之前，即使你关闭窗口，进程也不关闭的原因就在此。</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">八、总结</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">创建窗口主要步骤：</p>
            <p style="TEXT-INDENT: 2em">1、GtkWidget *window;</p>
            <p style="TEXT-INDENT: 2em">2、gtk_init(&amp;argc,&amp;argv);</p>
            <p style="TEXT-INDENT: 2em">3、windows=gtk_window_new(GTK_WINDOW_TOPLEVEL);</p>
            <p style="TEXT-INDENT: 2em">4、gtk_widget_show(window);</p>
            <p style="TEXT-INDENT: 2em">5、gtk_main();</p>
            <p style="TEXT-INDENT: 2em"></p>
            <p style="TEXT-INDENT: 2em">最后，注意编译命令。后面的那些参数。</p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/qcylxfy/aggbug/106694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qcylxfy/" target="_blank">丁念念</a> 2010-01-29 09:35 <a href="http://www.cppblog.com/qcylxfy/archive/2010/01/29/106694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT中文教程-----QT教程网络指南</title><link>http://www.cppblog.com/qcylxfy/archive/2010/01/29/106693.html</link><dc:creator>丁念念</dc:creator><author>丁念念</author><pubDate>Fri, 29 Jan 2010 01:28:00 GMT</pubDate><guid>http://www.cppblog.com/qcylxfy/archive/2010/01/29/106693.html</guid><wfw:comment>http://www.cppblog.com/qcylxfy/comments/106693.html</wfw:comment><comments>http://www.cppblog.com/qcylxfy/archive/2010/01/29/106693.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qcylxfy/comments/commentRss/106693.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qcylxfy/services/trackbacks/106693.html</trackback:ping><description><![CDATA[<div class=cnt><strong>转载自</strong><a href="http://www.qteverywhere.com/" target=_blank><font color=#0000ff><u>qteverywhere</u></font></a><br>网上有很多关于Qt的学习资料，今天在这里总结一下，希望各位想学习Qt的同学，各取所需，早日从入门到精通！<br><br><font color=#66b036><strong>Part 1: 新手上路</strong></font><br><font color=#001dc8><strong>Qt 官方学习教程</strong></font><br><br><strong>Qt 官方学习教程包含了3部分，包括如何学习Qt，如何逐步创建一个地址簿应用以及如何编写Qt Widget。教程由浅入深，Qt初学者必读</strong><br><br><a href="http://www.qteverywhere.com/qt/Tutorials/Qt%204_5%20How%20to%20Learn%20Qt_files/Qt%204_5%20How%20to%20Learn%20Qt.htm" target=_blank><font color=#0000ff><u>如何学习 Qt</u></font></a><br><br><strong>我们假定您已了解 C++， 并将用于 Qt 开发。有关将 Qt 与其他编程语言一起使用的更多信息，请参见 </strong><a href="http://www.qtsoftware.com/products/qt" target=_blank><font color=#0000ff><u>Qt 网站</u></font></a><strong>。。。。。</strong><br><br><a href="http://www.qteverywhere.com/qt/Tutorials/Qt%204_5%20Address%20Book/Qt%204_5%20Address%20Book%20Tutorial.htm" target=_blank><font color=#0000ff><u>地址簿教程</u></font></a><br><br><strong>本教程介绍了使用 Qt 跨平台框架的 GUI 编程。在学习过程中，我们将了解部分 Qt 基本技术，如Widget 和布局管理器，容器类，信号和槽，输入和输出设备等。。</strong><br><br><a href="http://www.qteverywhere.com/qt/Tutorials/Qt%204_5%20Widgets%20Tutorial_files/Qt%204_5%20Widgets%20Tutorial.htm" target=_blank><font color=#0000ff><u>Widgets 教程</u></font></a><br><br><strong>Widget 是使用 Qt 编写的图形用户界面 (GUI) 应用程序的基本生成块。每个 GUI 组件，如按钮、标签或文本编辑器，都是一个 widget ，并可以放置在现有的用户界面中或作为单独的窗口显示。每种类型的组件都是由 </strong><a href="http://doc.trolltech.com/4.5/qwidget.html" target=_blank><font color=#0000ff><u>QWidget</u></font></a><strong> 的特殊子类提供的，而 QWidget 自身又是 </strong><a href="http://doc.trolltech.com/4.5/qobject.html" target=_blank><font color=#0000ff><u>QObject</u></font></a><strong> 的子类。</strong><br><br><br><font color=#001dc8><strong>Qt 学习之路:</strong></font><br><br><strong>来自于FinderCheng的Qt 学习之路。简介：在本系列文章中，FinderCheng使用Qt4进行C++ GUI的开发。我是参照着《C++ GUI Programming with Qt4》一书进行学习的。其实，我也只是初学Qt4，在这里将这个学习笔记记下来，希望能够方便更多的朋友学习Qt4。我是一个Java程序员，感觉 Qt4的一些命名规范以及约束同Java有异曲同工之妙，因而从Java迁移到Qt4似乎困难不大。不过，这也主要是因为Qt4良好的设计等等。</strong><br><br><a href="http://www.qteverywhere.com/archives/466" target=_blank><font color=#0000ff><u>Qt学习之路(1)：前言</u></font></a><br><br><strong>Qt是一个著名的C++库——或许并不能说这只是一个GUI库，因为Qt十分庞大，并不仅仅是GUI。使用Qt，在一定程序上你获得的是一个&#8220;一站式&#8221;的服务：不再需要研究STL，不再需要C++的 ，因为Qt有它自己的QString等等。或许这样说很偏激，但Qt确实是一个 &#8220;伟大的C++库&#8221;。</strong><br><br><a href="http://www.qteverywhere.com/archives/468" target=_blank><font color=#0000ff><u>Qt学习之路(2)：Hello, world!</u></font></a><br><br><strong>任何编程技术的学习第一课基本上都会是Hello, world!，我也不想故意打破这个惯例——照理说，应该首先回顾一下Qt的历史，不过即使不说这些也并无大碍。</strong><br><br><a href="http://www.qteverywhere.com/archives/480" target=_blank><font color=#0000ff><u>Qt学习之路(3)：Hello, world!(续)</u></font></a><br><br><strong>下面来逐行解释一下前面的那个Hello, world!程序，尽管很简单，但却可以对Qt程序的结构有一个清楚的认识。现在再把代码贴过来：</strong><br><br><a href="http://www.qteverywhere.com/archives/485" target=_blank><font color=#0000ff><u>Qt学习之路(4)：初探信号槽</u></font></a><br><br><strong>所谓信号槽，简单来说，就像是插销一样：一个插头和一个插座。怎么说呢？当某种事件发生之后，比如，点击了一下鼠标，或者按了某个按键，这时，这个组件就 会发出一个信号。就像是广播一样，如果有了事件，它就漫天发声。这时，如果有一个槽，正好对应上这个信号，那么，这个槽的函数就会执行，也就是回调。就像 广播发出了，如果你感兴趣，那么你就会对这个广播有反应。干巴巴的解释很无力，还是看代码：</strong><br><br><a href="http://www.qteverywhere.com/archives/488" target=_blank><font color=#0000ff><u>Qt学习之路(5)：组件布局</u></font></a><br><br><strong>顾名思义，绝对定位就是使用最原始的定位方法，给出这个组件的坐标和长宽值。这样，Qt就知道该把组件放在哪里，以及怎么设置组件的大小了。但是这样做的 一个问题是，如果用户改变了窗口大小，比如点击了最大化或者拖动窗口边缘，这时，你就要自己编写相应的函数来响应这些变化，以避免那些组件还只是静静地呆 在一个角落。或者，更简单的方法是直接禁止用户改变大小。</strong><br><br><a href="http://www.qteverywhere.com/archives/493" target=_blank><font color=#0000ff><u>Qt学习之路(6): API文档的使用</u></font></a><br><br><strong>今天来说一下有关Qt API文档的使用。因为Qt有一个商业版本，因此它的文档十分健全，而且编写良好。对于开发者来说，查看文档时开发必修课之一——没有人能够记住那么多API的使用！</strong><br><br><a href="http://www.qteverywhere.com/archives/496" target=_blank><font color=#0000ff><u>Qt学习之路(7): 创建一个对话框(上)</u></font></a><br><br><strong>首先说明一点，在C++ GUI Programming with Qt4, 2nd中，这一章连同以后的若干章一起，完成了一个比较完整的程序——一个模仿Excel的电子表格。不过这个程序挺大的，而且书中也没有给出完整的源代 码，只是分段分段的——我不喜欢这个样子，我想要看到我写出来的是什么东西，这是最主要的，而不是慢慢的过上几章的内容才能看到自己的作品。</strong><br><br><a href="http://www.qteverywhere.com/archives/500" target=_blank><font color=#0000ff><u>Qt学习之路(8): 创建一个对话框(下)</u></font></a><br><br><strong>Qt是分模块的，记得我们建工程的时候就会问你，使用哪些模块？QtCore？QtGui？QtXml？等等。这里，我们引入QtGui，它包括了 QtCore和QtGui模块。不过，这并不是最好的做法，因为QtGui文件很大，包括了GUI的所有组件，但是很多组件我们根本是用不到的——就像 Swing的import，</strong><br><br><a href="http://www.qteverywhere.com/archives/503" target=_blank><font color=#0000ff><u>Qt学习之路(9)：深入了解信号槽</u></font></a><br><br><strong>槽函数和 普通的C++成员函数没有很大的区别。它们也可以使virtual的；可以被重写；可以使public、protected或者private 的；可以由其它的C++函数调用；参数可以是任何类型的。如果要说区别，就是，槽函数可以和一个信号相连接，当这个信号发生时，它可以被自动调用。</strong><br><br><a href="http://www.qteverywhere.com/archives/505" target=_blank><font color=#0000ff><u>Qt学习之路(10): Meta-Object系统</u></font></a><br><br><strong>前面说过，Qt使用的是自己的预编译器，它提供了对C++的一种扩展。利用Qt的信号槽机制，就可以把彼此独立的模块相互连接起来，不需要实现知道模块的任何细节。为了达到这个目的，Qt提出了一个Meta-Object系统。它提供了两个关键的作用：信号槽和内省。</strong><br><br><br><font color=#66b036><strong>Part 2： 进阶学习</strong></font><br><br><font color=#001dc8><strong>Qt4 学习笔记</strong></font><br><br><a href="http://www.qteverywhere.com/qt/qt4gossip/Qt4Gossip.html" target=_blank><font color=#0000ff><u>Qt4 学习笔记(繁体中文)</u></font></a><a href="http://translate.google.cn/translate?hl=zh-CN&amp;sl=auto&amp;tl=zh-CN&amp;u=http%3A%2F%2Fwww.qteverywhere.com%2Fqt%2Fqt4gossip%2FQt4Gossip.html" target=_blank><font color=#0000ff><u>简体中文(Google 翻译)</u></font></a><br><strong>来自台湾的caterpillar，Qt4 学习笔记由浅入深，分门别类的介绍了Qt4 中的许多特性，如事件處理，常用圖型元件，常用 API，檔案處理，拖放（Drag &amp; Drop）與剪貼，多執行緒（Multithreading）很多内容，是进一步学习Qt的极好教程</strong><br><br><strong><font color=#001dc8>关于Qt编程的书籍</font></strong><br><br><strong>接下来当你学习了上面的相关内容后，就可以开始阅读Qt编程的书籍进行系统的学习了。当然，书也不一定要从头到尾阅读一遍，用时拿出来学习和参考也很不错</strong><br><br><a href="http://www.qteverywhere.com/qt/book/c-gui-programming-with-qt-4-2ndedition.pdf" target=_blank><font color=#800080><u><font color=#0000ff>C++ GUI Programming with Qt 4 (2nd Edition) (英文版)</font> </u></font></a><br><br><a href="http://www.china-pub.com/42122" target=_blank><font color=#0000ff><u>C++ GUI Qt4 编程中文版China-pub购买地址</u></font></a><br><strong>本书详细讲述了用最新的Qt版本进行图形用户界面应用程序开发的各个方面。前5章主要涉及Qt基础知识，后两个部分主要讲解Qt的中高级编程，包括布局管 理、事件处理、二维/三维图形、拖放、项视图类、容器类、输入/输出、数据库、多线程、网络、XML、国际化、嵌入式编程等内容。对于本书讲授的大量 Qt4编程原理和实践，都可以轻易将其应用于Qt4．4、Qt4．5以及后续版本的Qt程序开发过程中。</strong><br><br><a href="http://www.qteverywhere.com/qt/book/c-gui-programming-with-qt-4.pdf" target=_blank><font color=#0000ff><u>C++ GUI Programming with Qt 4 (英文第一版）</u></font></a><br><br><a href="http://www.qteverywhere.com/qt/book/the_art_of_building_qt_applications.pdf" target=_blank><font color=#0000ff><u>The Book of Qt 4 － The Art of Building Qt Applications</u></font></a><br><br><br><font color=#66b036><strong>Part3：深入理解</strong></font><br><br><font color=#001dc8><strong>Inside Qt 系列</strong></font><br><br><strong>QKevin所著，通过剖析Qt源代码，深入浅出的解释了Qt中的许多机制，了解Qt内部是如何 work 的。着实为想深入了解Qt的开发者提供了很好的学习机会。如果你已经学习了上面的内容并且熟练掌握Qt编程，那么大力推荐这一系列文章！</strong><br><br><a href="http://www.qteverywhere.com/archives/393" target=_blank><font color=#0000ff><u>Inside Qt Series： 序</u></font></a><br><br><strong>写了这么多年的程序，除了留下很多 code (其中有很多是garbage)之外，再没有其它东西，或许我该写点儿什么了，写一些关于我的工作的东西，自己所了解的技术，也把自己在工作过程中新学习的一些东西放在这儿，就算是为了以后做一个参考。</strong><br><br><a href="http://www.qteverywhere.com/archives/400" target=_blank><font color=#0000ff><u>Inside Qt Series (一)：Let&#8217;s go, Starting From the QObject</u></font></a><br><br><strong>QObject 这个 class 是 QT 对象模型的核心，绝大部分的 QT 类都是从这个类继承而来。这个模型的中心特征就是一个叫做信号和槽（signal and slot）的机制来实现对象间的通讯，</strong><br><br><a href="http://www.qteverywhere.com/archives/401" target=_blank><font color=#0000ff><u>Inside Qt Series (二)：对象数据存储(A)</u></font></a><br><br><strong>我们知道，在C++中，几乎每一个类(class)中都需要有一些类的成员变量(class member variable)，在通常情况下的做法如下：</strong><br><br><a href="http://www.qteverywhere.com/archives/403" target=_blank><font color=#0000ff><u>Inside Qt Series (三)：对象数据存储(B)</u></font></a><br><br><strong>在 QT 4.4 中，类成员变量定义方法的出发点没有变化，只是在具体的实现手段上发生了非常大的变化，下面具体来看。</strong><br><br><a href="http://www.qteverywhere.com/archives/405" target=_blank><font color=#0000ff><u>Inside Qt Series (四)：对象数据存储(C)</u></font></a><br><br><strong>接上节，让我们来看看这个 QObjectPrivate 和 QObject 是如何关联在一起的。</strong><br><br><a href="http://www.qteverywhere.com/archives/412" target=_blank><font color=#0000ff><u>Inside Qt Series (五)：元对象系统(Meta-Object System) </u></font></a><br><br><strong>从本节开始，我们讲解 QT Meta-Object System 的功能，以及实现。在使用 Qt 开发的过程中，大量的使用了 signal 和 slot. 比如，响应一个 button 的 click 事件，我们一般都写如下的代码：</strong><br><br><a href="http://www.qteverywhere.com/archives/418" target=_blank><font color=#0000ff><u>Inside Qt Series (六)：元对象编译器 &#8211; Meta Object Compiler (moc) </u></font></a><br><br><strong>元对象编译器用来处理QT 的C++扩展，moc 分析C＋＋源文件，如果它发现在一个头文件(header file)中包含Q_OBJECT 宏定义，然后动态的生成另外一个C++源文件</strong><br><br><a href="http://www.qteverywhere.com/archives/420" target=_blank><font color=#0000ff><u>Inside Qt Series (七)：Signal &amp; Slot</u></font></a><br><br><strong>信号和 槽是用来在对象间通讯的方法，当一个特定事件发生的时候，signal会被 emit 出来，slot 调用是用来响应相应的 signal 的。</strong><br><br><a href="http://www.qteverywhere.com/archives/424" target=_blank><font color=#0000ff><u>Inside Qt Series (八)：Meta Object Class overview</u></font></a><br><br><strong>前面我们介绍了 Meta Object 的基本功能，和它支持的最重要的特性之一：Signal &amp; Slot的基本功能。现在让我们来进入 Meta Object 的内部，看看它是如何支持这些能力的。</strong><br><br><a href="http://www.qteverywhere.com/archives/428" target=_blank><font color=#0000ff><u>Inside Qt Series (九)：QMetaObject class data members</u></font></a><br><br><strong>我们来看一下QMetaObject的定义，我们先看一下QMetaObject对象中包含的成员数据。</strong><br><br><a href="http://www.qteverywhere.com/archives/433" target=_blank><font color=#0000ff><u>Inside Qt Series (十)：connect，幕后的故事</u></font></a><br><br><strong>我们都知道，把一个signal和slot连接起来，需要使用QObject类的connect方法，它的作用就是把一个object的signal和另外一个object的slot连接起来，以达到对象间通讯的目的。</strong><br><br><a href="http://www.qteverywhere.com/archives/435" target=_blank><font color=#0000ff><u>Inside Qt Series (十一)：emit，幕后的故事</u></font></a><br><br><strong>当我们写下一下emit signal代码的时候，与这个signal相连接的slot就会被调用，那么这个调用是如何发生的呢？让我们来逐一解开其中的谜团。</strong><br><br><a href="http://www.qteverywhere.com/archives/437" target=_blank><font color=#0000ff><u>Inside Qt Series (十二)：Qt对象之间的父子关系</u></font></a><br><br><strong>很多C/C++初学者常犯的一个错误就是，使用malloc、new分配了一块内存却忘记释放，导致内存泄漏。Qt的对象模型提供了一种Qt对象之间的父 子关系..</strong><br><br><a href="http://www.qteverywhere.com/archives/440" target=_blank><font color=#0000ff><u>Inside Qt Series (十三)：Qt/e体系结构概述</u></font></a><br><br><strong>首先，让我们来看看Qt/e的系统结构介绍：Qt for destop Linux 和 Qt for Embedded Linux 最大的区别就在于他们所依赖的底层显示基础的不同，这也就导致了他们在体系结构上的差异。</strong><br><br><a href="http://www.qteverywhere.com/archives/449" target=_blank><font color=#0000ff><u>Inside Qt Series (十四)：Qt/e输入法程序设计指南</u></font></a><br><br><strong>本输入法设计指南针对Qt for Embedded Linux 4.5.1，并且以中文输入法为例做说明，并且本文只是侧重于说明Qt/Embedded对输入法的支持接口，</strong><br><br><a href="http://www.qteverywhere.com/archives/452" target=_blank><font color=#0000ff><u>Inside Qt Series (十五)：Qt/e 输入法，How it works?</u></font></a><br><br><strong>前面我们介绍了Qte输入法的基本设计思路，以及一个最简单的例子，那么，Qte的输入法是如何工作的呢？本节我们就来看一下Qte的源代码，一起来解开这个谜团。</strong><br><br><br><font color=#66b036><strong>Happy Qt coding&#8230;.</strong></font><br><br><strong>&#169; 特别感谢Q-Kevin，FinderCheng，caterpillar的原创文章，所有文章都已注明出处。</strong></div>
<br>
<img src ="http://www.cppblog.com/qcylxfy/aggbug/106693.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qcylxfy/" target="_blank">丁念念</a> 2010-01-29 09:28 <a href="http://www.cppblog.com/qcylxfy/archive/2010/01/29/106693.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>