分类: C/C++
2010-02-27 22:21:21
我心目中,这篇文章的目标读者应该是在 Windows 下完全使用 Visual Studio 或 Borland C++ Builder (现在还有人在用么?)等系列 IDE 开发软件的 C/C++ 程序员。
我并不打算从 GNU Make 这种工具的使用写起,因为如果以上提到的这类同学如果都开始看 gmake 的文档(现在翻译工作已经有人做了),应当已经脱离了纯粹 IDE 开发的人群。本文只是一篇非常初步的入门文章,如果你已经使用过类似 gnu make 的工具构建自己的项目,那么完全不必看下去了。
不可否认,IDE 对于软件开发领域,是一项伟大的发明。它极大的降低了软件开发的门槛。但是另一方面,IDE 也限制了程序员们创造软件的手段。这些限制还包括了平台限制,工具选择,甚至新的编译技术,编程语言的选择。所以 IDE 绝对不是程序员的唯一选择,如果你现在作为一个程序员,完全不能离开 IDE 工作。那么,是时候接触一些新东西了。
如果你大约知道一点相关的知识,但是对用 make 工具去构建项目充满了鄙视和厌恶,云风不期望通过这篇文章改变你的想法。因为我不想花太多笔墨来介绍其好处。我个人认为,那些好处,一旦你认真的采用这种开发方式,是显而易见的。
阅读本文,云风假设你至少已经了解了下面这些知识:
会使用 Visual Studio 的某一个版本创建一个由 C/C++ 程序构建起来的工程,并正确编译运行它。
知道 Windows 里有一个叫做控制台(或终端)的程序,通常用 Win-R 然后输入 cmd 启动它。
知道最基本的 dir cd mkdir del copy 等 Windows 命令行指令,并了解 Windows 文件系统的基本结构。
基本了解 "环境变量" 这个概念,知道 PATH 这种常见环境变量的用途。
如果你对上述概念不甚了解,请运用你使用 google 的技能把它们弄清楚。然后,我们可以开始了。
读到这里还没有离开的同学,机器上应该装有一份 Visual Studio 。我的机器上就装了两个版本,但是差不多三年没怎么用它们做项目了。一份是 Visual Studio 6.0 ,早几年订购 MSDN 宇宙版送的。另一份是从微软网站免费下载的 Visual Studio 2005 Express Edition 。
我自己做项目现在是用 gcc ,并且向同学们推荐这款编译器。主要原因当然不是其免费,如上所述,我们现在也可以从微软免费获得编译器了。使用 gcc 最大的好处就是,一旦你打算切换到别的平台开发软件,可以不用更改你的使用习惯。就算你不离开 Windows ,也需要它来开发你的 psp ,nds ,手机,pda 等等。另外 gcc 一直在更新,它给你带来的好处是更强大的编译功能。如果你有一天像我一样放弃了 IDE ,Visual Studio 不断升级的 IDE 界面以及更华丽的工程管理方案对你也会毫无意义。
不过现在,我们暂时不要切换到 gcc 下。那样变化太大,反而难以接受。常年使用 vs 培养出来的习惯是很顽固的。等你学会了 make 这类工具,就会发现,其实切换编译器是再容易不过的事情了,到时候爱用啥用啥。
现在进入 cmd 控制台模式。输入 cl 回车。如果你的机器上安装了 vs 2005 ,你应该可以看到
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
如果是 vc 6 那么也大同小异,
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
如果没有出来,可能是环境变量没有配置好。进入 vs 的安装目录(C:\Program Files\Microsoft Visual Studio 8\VC 或 C:\Program Files\Microsoft Visual Studio\VC98\Bin),运行 vcvarsall.bat (vs2005) 或 VCVARS32.BAT (vc6) 即可。实在搞不定就重新安装 vs ,默认安装选项会帮你设置好所有的环境变量。
好了,如果你成功运行了 cl 这个程序,下面的一切都会很顺利。cl 是微软出品的 C/C++ 编译器,就是把 .c 或 .cpp 的源文件编译生成为 PE 文件的工具。常年使用 IDE 的同学也应该注意到它的存在,就是在你使用 vs ide 时,按下 build 的按钮,下面 output 窗口里也会蹦出正在运行 cl 的信息。
现在创建并进入一个工作目录,比如 C:\project\foo ,我们将在这个目录下进行今天的演示。
用你喜欢的文本编辑器在这个目录下编辑一个文件名为 foo.c C 程序。写点 hello world 之内的东西即可。
接下来使用 cl foo.c cl 将为你生成两个文件,一个是 foo.obj 一个是 foo.exe 。我们应该明白这些是什么了。
现在可以试着运行 foo.exe 了,看看是不是你预期的结果?
好吧,对于这种一个源文件就可以搞定的简单程序,我个人认为,无论从任何角度讲,直接使用 cl 都比用 ide 要来的方便。至少我不用构建一个新的工程项目不是?有时候需要写一些实验性的代码,可以把一堆这样的小程序放在一个目录下,只要它们的文件名各不相同就可以了。完全不必在硬盘上留下大堆复杂的目录结构。
但这离构建一个项目还远远不够。通常一个 C/C++ 项目都是由很多个 .c .cpp 源文件,以及若干 .h 构成的。
比如,我们再添加一个 bar.c ,希望把 foo.c 和 bar.c 编译链接到一起。
无论是 cl 还是 gcc ,都支持直接在一个命令行写上多个源文件,然后依次编译并链接成最终的 PE 文件。所以最简单的做法是直接
cl foo.c bar.c
我们会看到, cl 生成了三个文件, foo.obj bar.obj 以及 foo.exe
cl 将 foo.obj 与 bar.obj 链接成了 foo.exe ,这个文件名默认是以第一个输入源文件为参考的。
如果我们想换个最终目标文件名怎么办?查一下 cl 的帮助,输入 cl /? 看看。
/? 是微软风格的命令行求助选项,几乎所有的微软编译工具都支持。如果是用 gcc 则是 gcc --help 。
我们在帮助信息里可以找到,能够用 /Fe 来指定最终生成的 PE 文件名。
现在可以用 cl /Fefoobar foo.c bar.c 试试看了,主要 /Fe 和 foobar 间不要留空格。
现在则生成的是 foobar.exe 而不是 foo.exe 了。
调试怎么办?
我猜用惯 IDE 的同学们现在最想问的就是这个了。如果我再来推荐诸如写 log 这类 “原始“ 调试方法,怕是要被人嗤之以鼻了。vs 的用户们肯定习惯了单步跟踪、设置断点、监视变量,等等这种 ”高科技“ 的调试手段。其实我也喜欢,方便的工具为何不用呢?
调试器的选择并不多,尤其在 Windows 下。但也不是别无选择的。使用 cl 自然就要使用 vs 自家的调试器啦。正如你使用 gcc 就必然选择 gdb 一样。(btw, gdb 习惯后其实并不难用,何况还有 insight ddd 这样的图形界面的选择,只不过他们的表现不如在非 windows 平台上那么好罢了。)
要使用调试器,必须先生成调试信息。对于 cl ,这个编译开关是 /Zi 不太好记,但是用的多了就熟了,一旦忘记了,请用 cl /? 查询。如果以后换成 gcc 那么就是 -g 了。
试试
cl /Zi foo.c
除了原来生成的 obj 和 exe 文件外,cl 还生成了 pdb 文件,这里面就存放了调试信息。当然,如果你用 gcc 的话,是不会有额外的文件的,调试信息就放在 exe 文件内部。
现在开启熟悉的 ide 来调试这个程序,当然这次,我们只是把 ide 当成调试器在用。如果不想使用 VS 的 IDE ,也可以使用微软免费提供调试器 WinDBG ,不过使用稍微麻烦一点,需要自己设定源码以及调试符号文件的路径,这里就不介绍了。
如果是在使用 vs2005 express 版, 请输入 vcexpress foo.exe ;如果是 vc6 的话,输入 msdev foo.exe 。效果都是一样的,都是打开 vs 的 ide 并加载 foo.exe 。
如果你讨厌命令行操作(嘿,同学。你都打算学习怎样不使用 ide 开发项目了,怎么能讨厌命令行环境呢?), 可以先打开 vs 的 ide ,然后从菜单里选择 open ,打开 foo.exe 也可以。
接下来,按一下 F11 (vs ide 默认的 step into 的热键)。看到了什么?foo.c 被打开了,程序运行指示光标停在了 main 函数的第一行。:)
接下来,云风将传授一门关于调试的独门秘籍。
知道调试器是如何实现断点这个功能的吗?其实它偷偷的在你的程序要设置断点的位置放置了一条调试中断指令。在 x86 32 位系统上,这是一条单字节指令,汇编代码是 int 3 。cpu 运行程序的时候,碰到 int 3 就会把控制权交给调试器,当你在调试器中选择继续运行的时候,调试器再将被替换的程序机器指令换回去,让程序继续运行。
知道了这个细节,我们就可以自己提前设置调试断点了。我称它为硬断点。只要程序运行到,就一定会停下来。如果你想在运行期屏蔽硬断点,需要在源码上做一些工作了。
现在在你刚才的 foo.c 的程序入口处加一行 __asm int 3 ( 如果你在用 gcc 可以加 asm ("int $3"); ) 重新用 cl /Zi foo.c 编译一次。然后在命令行直接运行 foo.exe 。
马上,你将会看到一个熟悉的关于程序崩溃的对话框。没关系,它是由你插入的硬断点 (int 3) 造成的。如果你正确安装了 vs ,vs 应该已经把自己设置成系统默认的调试器了。点对话框上的按钮,便将启动 vs 的 ide ,我们会发现程序正好停在了 int 3 那行汇编的地方。现在你可以尽情的单步跟踪了。
写了这么多,似乎还没进入正题。我们一直在玩一些玩具代码和迷你工程。貌似离取代 ide 去工作还很远。只是我今天写累了,还是且听下回分解吧。今天这一篇,让一些完全没接触过命令行编译程序的同学们加深一下,一组源代码是如何生成最终的执行文件,这个过程的理解。达到这个目的就足够了。本质上,IDE 也在做这些事情,作为一个 C/C++ 程序员,怎能对一个天天在用的系统怎样在工作一点都不了解呢?
ps. 希望看到这里的同学不要为在命令行下输入了太多的指令而心烦意乱。或者担心那些命令行参数用完就忘。你知道 windows 下有个叫做批处理的好用的工具么?就是那些后缀为 .bat 的文件。可以把经常输入的指令放在里面,简化日常的命令行操作。如果不知道,那么还请 google 之。
虽然 windows 下的批处理比 *nix 的 shell 脚本弱了上万倍,但毕竟还是可以提高我们的生产力的。在没有介绍 make 工具前,同学们可以先用 bat 文件顶一下。比如将你的工程的编译指令一次性写到一个 .bat 文件里,就不需要每次重新编译都敲上长长的一串编译指令了。
事实上,云风最早从 ide 里出来,就是用批处理来管理自己的工程的。在下一回,本系列将隆重推出更加好用的工具来取代它。