(转)Linux下C++开发初探

1.开发工具java

    Windows下,开发工具多以集成开发环境IDE的形式展示给最终用户。例如,VS2008集成了编辑器,宏汇编ml,C /C++编译器cl,资源编译器rc,调试器,文档生成工具, nmake。它们以集成方式提供给最终用户,对于初学者而言十分方便。可是,这种商业模式,直接致使用户可定制性差,不利于自动化,集成第三方工具的能力弱。例如,没法定制一些宏来处理一些重复操做;体会不到自动化makefile一步到位快感;没法远程登陆到服务器上进行开发;没法使用某种”粘合剂”来把第三方工具(例如,文本工具,字符串工具)有效地调用起来。能够说,良好的商业支持和傻瓜式开发,是它们主要的优势。
    在linux下,开发工具被切割成一个个独立的小工具。各自处理不一样的问题。例如,编辑器(emacs, vim)用来进行编辑程序的,调试器(gdb)用来调试程序,编译器(GCC)用来编译和连接程序的,性能分析工具(gcov, gprof)用来优化程序的,文档生成器(doxygen)用来生成文档的。同时,还有一些系统工具和系统知识,咱们是颇有必要了解的:程序自动化机制 makefile,系统粘合剂shell,系统查找工具grep, locate, find。其它的工具(例如ctags, OCI公司的MPC等等),一旦熟练掌握,它们将成为你手中的利器。
linux

   主要是一些针对LINUX下开发工具使用的经验之谈。因为,工具品种繁多,咱们没有能力也没有必要一一介绍。对于LINUX下IDE工具,例如 eclipse, anjuta等,它们虽然也很实用,可是使用起来比较简单,并且目前还算不上主流。因此,它们将不被着重介绍。同时,本文也不打算写成各个工具的操做手册,只着眼于介绍各个工具的想要解决的问题、运行机理和主要特性。c++

1.1编辑器程序员

    要进行开发,第一件事情就是选择一个合适的编辑器。编辑器选择有几个要素:
    1)减小没必要要的编辑动做,减小编辑的时间。
    一切可以无二义性描述出来的编辑任务,均可以并且应该能被自动化。例如,每个C++程序都会有一个main函数;咱们在定义.h文件时,都但愿加入一些预处理指令#define来帮咱们解决重复引用同一个头文件而带来的麻烦。鼠标操做老是比键盘操做要慢的。这方面EMACS作得可算是到了极致。因此, EMACS用户常常会吹嘘:他们编辑的速度等同于他们思考的速度。
    2)可扩展性高。
    程序员预期的编辑器应该能提供一些编程的帮助,例如,语法高亮,自动补齐,自动排版,语法检查等等。留心观察一下gedit, vim, emacs, ultraEdit,就会发现它们提供的远不是windows 记事本,写字板提供的那么简陋的功能。对于一种新的语言,新的语法,它们应该能很方便地提供支持,而不停留在一种或几种固定的语言上。
    3)用户可定制性高。
    若是想长期从事研发, 特别是linux/unix下研发的话,那么你颇有必要学好一个功能足够的编辑器。有这么一句话:Linux下程序员分为三种,使用emacs的,使用vi的,还有其它。EMACS是Stallman用lisp语言写的一个GPL的编辑器。咱们这里所说的emacs指的是GNU emacs,而非Xemacs。因为它的开放性,咱们能够把它打形成一个功能强大的IDE。咱们在安装好CGYwin以后,也能够在Windows系统下使用 EMACS。CGYwin和MINGW是第三方写的一个在Windows系统上模拟POSIX系统的工具。
    EMACS与其说的是一个编辑器,倒不如说它是一个操做系统。咱们能够用它来写编程,写wiki,收发邮件等等。EMACS主要是经过两种方式来进行扩展:el脚本(elisp是lisp的一种方言)和第三方扩展包。EMACS的入门成本很高。因为是纯键盘操做,因此须要记忆大量的快捷键;功能强大是经过用户添加一些扩展包,lisp脚原本实现的。如何正确配置和修改是很须要耐心和技巧的。shell

1.2编译器编程

    编译器首选GCC(GNU COMPILER COLLECTION)。缘由有两个,它是GNU开源的,同时它对标准C++的支持度高达96.15%。而VC++6.0的支持度只有83.43%。 GCC不只是一般意义上的C或C++的编译器,它还能够编译java等其它语言。gcc是gnu c的编译器,g++是gnu c++的编译器, 而EGCS(Enhanced GNU Compiler Suite)能够认为是gcc的改进版。
    编译语言从源程序到目标代码会通过以下几个阶段:源程序->汇编程序->编译成obj程序->连接成最终可执行程序。咱们能够经过一条编译指令来完成全部步骤。也能够分步执行。gcc有三个重要选项-E(只进行预处理), -S(生成汇编代码), -g(生成带原代码调试符号的可执行文件,若是想用gdb调试的话,就应该在编译时打开这个选项)。
    GCC能够看做一个软件包,除了编译工具,它还集成了调试器gdb,性能分析工具gcov, gprof。只要咱们装好了GCC,这些强大工具就能够直接使用了。
    经过gcov,咱们能够查看一个程序,源代码中每行代码的运行次数。咱们优化运行次数最多的代码,那么就能够大大优化程序。使用gcov时,须要打开 GCC的fprofile-arcs和ftest-coverage两个选项。gcov中经常使用的选项有-b分支统计信息。
    经过gprof工具,咱们能够查看函数之间的调用顺序,及各个函数运行的时间。咱们能够将gprof理解为linux/unix自带工具time的增强版。使用gprof时,须要打开GCC的pg选项。
    gcov和 gprof的共同点是在编译程序时,加入本身的一些辅助信息,由此来进行程序诊断。除了,这些优化手段,咱们还可使用一些内存泄漏工具,来减小野指针,未释放的内存空间。 
调试器
    GDB即GNU的调试器,它是GCC附带的一个性能优质的调试器。经过GDB和脚本结合,咱们能够很好的实现回归测试。
    GDB能够运行于CLI和GUI两种模式。默认GDB是CLI模式的,咱们能够去下载和安装GUI模式的GDB,例如xxgdb, ddd等。一个更好的方式是在 EMACS中使用GDB。GDB包括visual studio工具的全部调试功能,还包括它没有的功能。它除了支持,咱们通常的设置断点,单步跟踪,step in, step out, step over等,还有一些强大的功能。在gdb中,咱们能够有如下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程中止(Thread Stops)。
下面列举几个让我印象深入的功能。1)经过 watch指令,可让程序在某个变量的值发生变化时,暂停下来。2)经过print指令,在程序运行时,设置变量的值,运行一个程序自身支持的一个方法。3)经过until指令,咱们可让程序在运行到某个程序时暂停下来。4)经过break.. if指令,使得程序在知足某个bool表达式时,暂停下来。vim

1.3粘合剂windows

    我想经过“粘合剂”这个词来表达将多个工具粘合起来的“胶水”。例如,经过shell脚本,咱们能够把OS命令,sed指令,awk指令,其它脚本文件等串联起来,发挥它们的协力。在linux C++编程中,咱们不可避免地会使用makefile文件。经过,它咱们能够把编译指令,生成文档操做,清除操做等等串联起来。从某种意义上来看,它也至关于一个粘合剂。
makefile的出发点是,维护好一个项目中众多文件的依赖关系,由此获得一个源程序的拓扑图。当咱们只修改图中某个结点时,从新编译时就只须要将拓扑图中关联的链路进行编译就行了。由此,大大缩短了编译的时间。make有两大概念:dependencies和rules。规则rule即针对每个依赖关系 dependency定义一个操做规则。这个细粒度的分离,就可使咱们能够定制软件构建的行为。例如,修改使用的编译器,修改includepath, 修改libpath, 修改编译选项等等。咱们常见的VC中的nmake,功能和make是相似的。
    make使用的重点和难点是编写Makefile文件。Makefile的语法相对其它语言来讲是很不同的,咱们要特别注意TAB键和空格键的区别。有不少工具能够用来帮助咱们生成Makefile。最出名的就是GNU的autoconf了。一个GNU程序的编写,须要autoscan, aclocal, autoconf, automake这四个工具。
咱们知道GNU软件安装的三步曲是:./configure, make, make install。其中./configure就是根据autoconf, alocal等工具生成一个makefile文件。make指令就是调用make指令来根据makefile文件的规则来编译源程序。而make install就是执行makefile中的install规则指出的操做(通常是copy操做)。而make clean就是执行makefile中的clean规则指出的操做(通常是rm操做)。咱们用Eclispe+CDT开发Managed C++ Project时,它就是经过objects.mk,subdir.mk,sources.mk三个文件来生成Makefile。咱们注意观察编译时的输出信息,就能够看到显示的Makefile文件的内容。
能够说,若是想编译出跨平台的C++程序,那么makefile是一种最方便的机制。OCI公司为Douglas C.Schmidt的ACE,TAO开源社区编写了一段伟大的perl脚本--MPC。它由平台信息,一个规则文件,源代码,生成用户想要的工程文件,例如Make, Nmake, Visual C++ 6, Visual C++ 7等等。Google Web Tookit, Celtix作的事情与之相似,不过它们是针对JAVA的,而MPC是针对C++的。
服务器

2. 基本开发流程

2.1 代码的编写

对于移植工程来说,基本代码都在Windows下完成,只须要吧代码传到Linux下,而后在Linux下面组织源码目录便可。对于传到Linux编辑,可使用Linux下的vi工具来完成,也能够经过UltraEdit以Ftp方式打开Linux下的文件进行编辑。vi是Linux下面最经常使用的一个文本编辑器,后面将会介绍vi的一些基本用法。eclipse

有一点值得注意,Windows下文本里面的回车符包含两个字符‘\n’和‘\r’,而Linux下的文本里面的回车符只包含一个字符‘\n’。这样,若是上传文件的时候没有选择正确的方式,应该使用文本方式上传的使用了二进制方式,或者应该使用二进制方式上传的使用了文本方式,那么在Linux下都会出现问题,打开的文本当中每一行的行尾就会出现一个‘^M’字符。能够经过vi的匹配替换功能(稍后会作介绍)或者从新按照正确的方式上传来解决。

2.1.1 vi简介

vi是Linux下最经常使用的一个文本编辑器,小巧并且功能强大,一次咱们把它单独拿出来作一下介绍。若是想了解更详细的信息,请执行man vi查看其联机帮助文档。

2.1.2 命令模式和编辑模式

vi的工做模式包括命令模式和编辑模式两种。命令模式下能够执行vi中定义的一些命令,这些命令跟一些特定的键相对应,命令模式下全部的键盘相应将会做为命令来解释。编辑模式就是编辑文档的模式,在编辑模式下全部键盘的相应都为做为文档输入的内容。经过ESC键能够从编辑模式切换到命令模式。经过一些编辑命名能够从命令模式进入编辑模式。

2.1.3 基本命令

基本命令指的是在命令模式下,经过敲键执行的命令,这里咱们介绍几个经常使用的命令:

i             在当前开始插入,进入编辑模式

I             在行首开始插入,进入编辑模式

a             在当前字符后追加,进入编辑模式

A            在行尾追加,进入编辑模式

x            删除当前光标处的字符

X            删除当前光标前面的字符

D            删除从光标位置到行尾的全部字符

dd           删除当前行

dw          删除当前的单词

u            取消刚才的操做

G            跳到文件末尾

此外,在命令模式下,经过输入‘/’能够进行查询,经过输入‘:’能够输入一些其余命令。输入‘:’能够输入的命令包括:

q            退出

w           保存

wq          保存退出

q!         强制退出,不保存

w!        对受保护的文件强制写,包括只读文件

set number     显示行号  (set nu  也能够)

数字       跳到某一行

2.1.4 查找和匹配

vi的查找功能也很是强大,命令模式下经过输入‘/’就能够进入查找模式,能够输入要查找的关键字。而后能够经过‘n’来查找下一处。

在输入‘:’后,还能够输入一些匹配替换的命令——“%s”。命令的格式为“:%s /str1/str2,执行以后将把当前文件中全部str1替换成str2。举一个典型的例子,前面咱们说过,Windows下的文本文件若是以二进制的方式传到了Linux下,那么vi打开的时候每行的行尾就会出现一个“^M”,咱们能够用vi打开这个文件,而后经过vi的匹配替换功能去掉这些“^M”。命令格式以下:

       :%s /^M//

其中“^M”经过CTRL+V 和 CTRL+M来输入。  

2.2 编译

2.2.1  简单编译

       对于简单的程序,如只有几个源文件,能够直接使用编译器进行编译,或者把几条编译命令写在一个脚本文件里面,经过执行脚本文件实现工程的编译和链接。好比只有一个hello.cpp文件的工程,能够经过以下命令编译:

CC –o hello hello.cpp

其中CC是编译器,不一样的系统下面可能有不一样的编译器。通常来讲,大多数Linux系统下的C编译器都叫cc,而C++编译器叫CC。Linux下面带的C编译器为gcc,C++编译器为g++。-o参数用来指定输出的目标的名称,也就是编译后执行程序的名称。这种状况下编译和链接一步完成。

对于稍微负责一些的程序,包含多个源文件的,能够编写一个编译脚本,至关于windows下的批处理。以下:

工程中包含hello.cpp、func.cpp、other.cpp,咱们能够用以下脚原本实现工程的编译。

        CC –c hello.cpp

        CC –c func.cpp

        CC –c other.cpp

        CC –o hello hello.o func.o other.o

多个文件状况下,把编译和链接分开执行,先逐个编译源文件,而后再进行连接,造成最终的可执行程序。参数-c就是声明只进行编译操做。

2.2.2  使用Makefile

当工程达到必定的规模的时候,2.2.1中的作法显然是不能知足要求的,若是非要那样作,将会带来很大的工做量,并且还很是容易出错。这是咱们就要使用Makefile来帮助咱们完成工程的编译工做。

Makefile文件至关于一个工程文件,文件中描述了工程中的源代码、额外须要的库文件及其路径、额外须要的头文件路径已经编译器类型、编译参数等。经过make命令来调入Makefile进行工程的编译。当执行make命令是,会在当前目录下搜索名称为“Makefile”或者“makefile”的文件,做为当前编译的工程文件,也可一指定其余的工程文件,如make –f MyMakefile。