Linux环境下的软件开发工具
简化版
BWS刘少锋
2012年6月4日
目 录
身边的同事们有不少为Linux环境下的开发工具而纠结,特写作此文,希望可以抛砖引玉,与大家互勉。
本文档从6月4日一直写到6月18日,每天晚上下班写2小时,完成初稿。后经过修改和整理,最终完成本文档(简化版),本文档略去了不是必要228页。
本文假定读者熟悉linux系统和常用命令,如有实际的编程经验将有助于理解本文的内容。
其实vim也很酷,先给个图看看。
1 Vim
Vim(Vi IMproved)是一个从vi发展出来的文本编辑器,在程序员中被广泛使用,和Emacs并列成为类Unix系统用户最喜欢的编辑器。
1、Vim的历史:
Vim的第一个版本由布莱姆·米勒1991年发布,简称Vi IMitation,仅仅是vi的克隆。
1991年Vim 1.14版被"Fred Fish Disk #591"这个Amiga用的免费软体集所收录了。
1992年Vim 1.22版本被移植到了UNIX和MS-DOS上,正式名称改成Vi IMproved(改良)。
1994年Vim 3.0版本加入了多视窗编辑模式(分割视窗),同一萤幕可以显示多个Vim编辑的文件。
1996年Vim 4.0是第一个利用GUI(图形用户界面)的版本。
1998年Vim 5.0版本的Vim加入了highlight(语法高亮)功能。
2001年Vim 6.0版本加入了代码折叠、插件、多国语言支持、垂直分割视窗等功能。
2006年5月发布的Vim 7.0版本,加入了拼字检查、上下文相关补全,标签页编辑等新功能。
2008年8月发布的Vim 7.2版本,合并了Vim 7.1以来的所有修正补丁,并且加入了脚本的浮点数支持。
2010年8月发布的Vim 7.3版本,这个版本除了包含最新修正的补丁之外,还加入了“永久撤销”、“Blowfish算法加密”、“文本隐藏”和“Lua以及Python3的接口”等新功能。
2、Vim的基本概念
Vim编辑器基本上可以分为三种模式:命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode)。
命令模式:控制屏幕光标的移动,进行文本的删除、复制等文字编辑工作(不使用[Del]键和[Backspace]键)以及进入插入模式,或者回到底行模式。
插入模式:只有在插入模式下,才可以输入文字。按[Esc]键可回到命令行模式。很多Vim编辑器使用者希望一打开Vim就可以输入内容,但这是不能成功的,因为刚打开Vim编辑器时处于命令模式。
底行模式:保存文件或退出Vim,同时也可以设置编辑环境和一些编译工作,如列出行号、寻找字符串等。
下图为Vim模式相互转换的关系图。
Vim模式相互转换的关系图(摘自Vim手册)
也有人将底行模式算作命令行模式,将把Vim编辑器简化成两个模式。
按「i」进入插入模式,从光标当前位置开始输入文件;
按「a」进入插入模式,从目前光标所在位置的下一个位置开始输入文字;
按「o」进入插入模式,插入新的一行,从行首开始输入文字。
从插入模式切换为命令行模式,按「ESC」键。
3、Vim的基本操作
在系统提示符号输入vim,就进入vi全屏幕编辑画面,
例如:
$ vim或者$ vim c_file.c
此时处于命令模式,可以进行的操作如下:
1) 移动光标
Ø Vim使用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格,也可以用方向键上下左右移动。
「ctrl」+「b」 | 屏幕往“后”移动一页 |
「ctrl」+「f」: | 屏幕往“前”移动一页 |
「ctrl」+「u」 | 屏幕往“后”移动半页 |
「ctrl」+「d」 | 屏幕往“前”移动半页 |
「0」 | 移到文章的开头 |
「G」 | 移动到文章的最后 |
「$」 | 移动到光标所在行的“行尾” |
「^」 | 移动到光标所在行的“行首” |
「w」 | 光标跳到下个字的开头 |
「e」 | 光标跳到下个字的字尾 |
「b」 | 光标回到上个字的开头 |
2) 复制
Ø 按「yw」:将光标所在之处到字尾的字符复制到缓冲区中。
Ø 按「#yw」:复制#个字到缓冲区
Ø 按「yy」:复制光标所在行到缓冲区。
Ø 按「#yy」:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。
Ø 按「p」:将缓冲区内的字符贴到光标所在位置。
注意:所有与“y”有关的复制命令都必须与“p”配合才能完成复制与粘贴功能。
3) 删除文字
Ø 按「x」:每按一次,删除光标所在位置的“后面”一个字符。
Ø 按「#x」:例如,「6x」表示删除光标所在位置的“后面”6个字符。
Ø 按「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符。
Ø 按「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符。
Ø 按「dd」:删除光标所在行。
Ø 按「#dd」:从光标所在行开始删除#行
4) 替换
Ø 按「r」:替换光标所在处的字符。
Ø 按「R」:替换光标所到之处的字符,直到按下「ESC」键为止。
5) 恢复上一次操作
Ø 按「u」:回到上一个操作,按多次“u”可以执行多次恢复。
6) 更改
Ø 「cw」:更改光标所在处的字到字尾处。
Ø 「c#w」:例如,「c3w」表示更改3个字。
7) 跳至指定的行
Ø 「ctrl」+「g」列出光标所在行的行号。
Ø 「#G」:例如,「15G」,表示移动光标至文章的第15行行首。
8) 跳到文件中的某一行
在冒号后输入一个数字,再按回车键就会跳到该行。例如:输入数字15,再回车,就会跳到文章的第15行。
详细见vim手册,在终端中输入man vim,英文阅读困难的可以安装中文手册。
Vim快捷键如下图所示:
Vim快捷键示意图-1
Vim快捷键示意图-2
4、修改代码
作为较早的代码编写工具,vim当然具备变量联想功能。编写程序时,按“Ctrl+N”或“Ctrl+P”进行联想,如下图所示。
但是,如果你觉得这样比较麻烦,也可以设置自动补全。
5、显示函数栏
按“F4”终端将被分为左右两栏,右侧栏显示当前文件的定义的变量和函数,再次按“F4”终端恢复原先界面。如下图所示:
2 Ctags
1、Ctags简介:
Ctags(Generate tag files for source code)是一个用于从程序源代码树产生索引tag文件,从而便于文本编辑器来实现快速定位的实用工具。在产生的tag文件中,每一个tag的入口指向了一个编程语言的对象。这个对象可以是变量定义,函数,类或其他的物件。
Ctags是开放源代码的程序。支持下列的编程语言:汇编,AWK, ASP, BETA, Bourne/Korn/Zsh Shell, C, C++, COBOL, Eiffel, Fortran, Java, Lisp, Lua, Make, Pascal, Perl, PHP, Python, REXX, Ruby, S-Lang, Scheme, Tcl, Vim, and YACC。
支持Ctags产生的tag文件的编辑器以及编辑器插件包括有:Vim,Vile,Lemmy等。
2、Ctags的使用:
在源代码的根目录下创建“tags”文件:
$ ctags –R ↙
“-R”表示递归创建,也就包括源代码根目录下的所有子目录下的源程序。“tags”文件中包括这些对象的列表:
Ø 用#define定义的宏
Ø 枚举型变量的值
Ø 函数的定义、原型和声明
Ø 名字空间(namespace)
Ø 类型定义(typedefs)
Ø 变量(包括定义和声明)
Ø 类(class)、结构(struct)、枚举类型(enum)和联合(union)
Ø 类、结构和联合中成员变量或函数
VIM用这个“tags”文件来定位上面这些做了标记的对象。
下面以阅读Linux内核代码为例,讲解如何简单快捷的阅读代码。
打开终端,在工程文件顶层目录中输入:
$ ctags –R↙
在终端中键入“vim –t函数名”,例如:
# vim –t dm6446x_init↙
直接进入函数dm6446x_init的定义处,如下图所示。
将光标移动到函数名称上,按“Ctrl+】”进入函数定义处,如下图所示:
按“Ctrl+O”或“Ctrl+T”返回函数调用处。
把光标移动到某个元素上,CTRL+],就会跳转到对应的定义啦。CTRL+o可以回退到原来的地方。如果当前光标下是个局部变量,在VIM里输入gd的话,就会跳到这个局部变量的定义处。
3 Cscope
利用tag文件,跳转到标签定义的地方。但如果想查找函数在哪里被调用,或者标签在哪些地方出现过,就需要使用更为强大的Cscope。
1、Cscope简介:
Cscope(Code scope)是一个控制台模式或基于字符界面的源代码浏览工具。Cscope具有纯正的Unix血统,它最早是由贝尔实验室为PDP-11计算机开发的,后来成为商用的AT&T Unix发行版的组成部分。直到2000年4月,这个工具才由SCO公司以BSD license开源发行,常被使用在非常大的工程。在Windows上也可以使用cscope(cscope for windows),cygwin工具包中包含了cscope。
Cscope缺省解析C文件(.c和.h)、lex文件(.l)和yacc文件(.y),也可以用于对C++和Java代码的搜索(注1)。
如下图所示:用cscope你可以轻易地搜索到你的标识符是在哪里被定义和使用的,它可以轻而易举地解决:
1、变量和函数在哪里被使用,如何定义?
2、预处理符号的值是什么?
3、源文件在在目录结构中的位置?
4、哪些源文件包含了这个头文件?
启动选择查找哪些函数被main函数调用了,可以看到搜索结果,如下图所示:
2、Cscope使用:
建立cscope使用的索引文件
首先需要为你的代码生成一个cscope数据库,在你需要浏览源码的根目录下使用下面命令:
#cscope –Rbkq ↙
这个命令会生成三个文件:cscope.out, cscope.in.out, cscope.po.out。
其中cscope.out是基本的符号索引,后两个文件是使用"-q"选项生成的,可以加快cscope的索引速度。上面所用到的命令参数,含义如下:
-R:在生成索引文件时,搜索子目录树中的代码
-b:只生成索引文件,不进入cscope的查询界面
-k:在生成索引文件时,不搜索/usr/include目录
-q:生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度
其他参数
-i:如果保存文件列表的文件名不是cscope.files时,需要加此选项告诉cscope到哪儿去找源文件列表。可以使用”-“,表示由标准输入获得文件列表。
-I dir:在-I选项指出的目录中查找头文件
-u:扫描所有文件,重新生成交叉索引文件
-C:在搜索时忽略大小写
-Ppath:在以相对路径表示的文件前加上的path,就无需切换到你数据库文件所在的目录。
Cscope只在第一次解析时扫描全部文件,以后再调用cscope,它只扫描那些改动过的文件,这大大提高了cscope生成索引的速度。
在vim中查找代码
在源码根目录下打开任意.c文件,使用如下命令:
Ctrl+]将跳到光标所在变量或函数的定义处
Ctrl+T返回
cs find s ----查找C语言符号,即查找函数名、宏、枚举值等出现的地方
cs find g ----查找函数、宏、枚举等定义的位置,类似ctags所提供的功能
cs find d ----查找本函数调用的函数
cs find c ----查找调用本函数的函数
cs find t: ----查找指定的字符串
cs find e ----查找egrep模式,相当于egrep功能,但查找速度快多了
cs find f ----查找并打开文件,类似vim的find功能
cs find i ----查找包含本文件的文件
4、扩展:
min-cscope:cscope的强化版,它起源于贝尔实验室(Bell Labs),包含了cscope的所有功能,对cscope做络一些精简(编译系统)和扩展(排序)。
Kscope:cscope的图形界面(KDE)版,需要Qt开发库的支持。
4 Gcc
GCC(GNU Compiler Collection)是一套GNU系统的官方编译器(包括GNU/Linux家族),也是编译与建立其他操作系统的主要编译器,包括BSD家族、Mac OS X、NeXTSTEP与BeOS。
GCC原名为GNU C语言编译器(GNU C Compiler),只处理C语言。后来扩展为可以处理C++,Fortran、Pascal、Objective-C、Java、Ada,以及Go与其他语言,后更名为GNU编译器套装(GNU Compiler Collection)。
GCC目前由世界各地不同的数个程式设计师小组维护。它是移植到中央处理器架构以及操作系统最多的编译器。GCC支持ARM, Atmel AVR,Alpha,IA-32,IA-64,Motorola 68000,MIPS,PA-RISC,PowerPC,SuperH,SPARC等众多处理器架构。
#gcc main.c
在默认情况下,C编译器将生成一个名为 a.out 的可执行文件。键入如下命令运行它:
#./a.out
我们可以通过使用 -o编译选项,指定可执行文件的名字,没有的命名限制。
#gcc main.c -o main
其实以上命令编译一个程序,其实也可以分三步做,第一步生成汇编代码,第二步生成目标文件,第三步生成可执行文件:
$ gcc -S main.c
$ gcc -c main.s
$ gcc main.o
1、Gcc选项选项列表
总体选项(Overall Option) | -c -S -E -ofile -pipe -v -xlanguage |
语言选项 (Language Option) | -ansi -fall-virtual -fcond-mismatch -fdollars-in-identifiers -fenum-int-equiv -fexternal-templates -fno-asm -fno-builtin -fhosted -fno-hosted -ffreestanding -fno-freestanding -fno-strict-prototype -fsigned-bitfields -fsigned-char -fthis-is-variable -funsigned-bitfields -funsigned-char -fwritable-strings -traditional -traditional-cpp -trigraphs |
警告选项 (Warning Option) | -fsyntax-only -pedantic -pedantic-errors -w -W -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscript -Wcomment -Wconversion -Wenum-clash -Werror -Wformat -Wid-clash-len -Wimplicit -Wimplicit-int -Wimplicit-function-declaration -Winline -Wlong-long -Wmain -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wno-import -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wshadow -Wstrict-prototypes -Wswitch -Wtemplate-debugging -Wtraditional -Wtrigraphs -Wuninitialized -Wunused -Wwrite-strings |
调试选项 (Debugging Option) | -a -dletters -fpretend-float -g -glevel -gcoff -gxcoff -gxcoff+ -gdwarf -gdwarf+ -gstabs -gstabs+ -ggdb -p -pg -save-temps -print-file-name=library -print-libgcc-file-name -print-prog-name=program |
优化选项 (Optimization Option) | -fcaller-saves -fcse-follow-jumps -fcse-skip-blocks -fdelayed-branch -felide-constructors -fexpensive-optimizations -ffast-math -ffloat-store -fforce-addr -fforce-mem -finline-functions -fkeep-inline-functions -fmemoize-lookups -fno-default-inline -fno-defer-pop -fno-function-cse -fno-inline -fno-peephole -fomit-frame-pointer -frerun-cse-after-loop -fschedule-insns -fschedule-insns2 -fstrength-reduce -fthread-jumps -funroll-all-loops -funroll-loops -O -O2 -O3 |
预处理器选项 (Preprocessor Option) | -Aassertion -C -dD -dM -dN -Dmacro[=defn] -E -H -idirafterdir -includefile -imacros file -iprefix file -iwithprefixdir -M -MD -MM -MMD -nostdinc -P -Umacro -undef |
汇编器选项 (Assembler Option) | -Wa,option |
连接器选项 (Linker Option) | -llibrary -nostartfiles -nostdlib -static -shared -symbolic -Xlinker option -Wl,option -usymbol |
目录选项(Directory Option) | -Bprefix -Idir -I- -Ldir |
目标机选项(Target Option) | -bmachine -Vversion |
配置相关选项 (Configuration Dependent Option) | M680x0 选项,VAX选项,SPARC选项,Convex选项,AMD29K选项,M88K选项,RS6000选项,RT选项,MIPS选项,i386选项,HPPA选项,i960选项,DEC Alpha选项,System V选项 |
代码生成选项 (Code Generation Option) | -fcall-saved-reg -fcall-used-reg -ffixed-reg -finhibit-size-directive -fnonnull-objects -fno-common -fno-ident -fno-gnu-linker -fpcc-struct-return -fpic -fPIC -freg-struct-return -fshared-data -fshort-enums -fshort-double -fvolatile -fvolatile-global -fverbose-asm |
2、Gcc基本选项:
-xlanguage
明确指出后面输入文件的语言为language (而不是从文件名后缀得到的默认选择).这个选项应用于后面所有的输入文件,直到遇着下一个`-x'选项. language的可选值有`c', `objective-c', `c-header', `c++', `cpp-output', `assembler'和`assembler-with-cpp'.
-x none
关闭任何对语种的明确说明,因此依据文件名后缀处理后面的文件(就象是从未使用过`-x'选项)。
-c
编译或汇编源文件,但是不作连接.编译器输出对应于源文件的目标文件。
缺省情况下, GCC通过用`.o'替换源文件名后缀`.c', `.i', `.s',等等,产生目标文件名.可以使用-o选项选择其他名字。GCC忽略-c选项后面任何无法识别的输入文件(他们不需要编译或汇编)。
-S
编译后即停止,不进行汇编.对于每个输入的非汇编语言文件,输出文件是汇编语言文件。
缺省情况下, GCC通过用`.o'替换源文件名后缀`.c', `.i',等等,产生目标文件名.可以使用-o选项选择其他名字。GCC忽略任何不需要编译的输入文件。
-E
预处理后即停止,不进行编译.预处理后的代码送往标准输出.
GCC忽略任何不需要预处理的输入文件.
-ofile
指定输出文件为file.该选项不在乎GCC产生什么输出,无论是可执行文件,目标文件,汇编文件还是预处理后的C代码。由于只能指定一个输出文件,因此编译多个输入文件时,使用`-o'选项没有意义,除非输出一个可执行文件。如果没有使用`-o'选项,默认的输出结果是:可执行文件为`a.out', `source.suffix '的目标文件是`source.o',汇编文件是 `source.s',而预处理后的C源代码送往标准输出。
-v
显示执行编译阶段的命令.同时显示编译器驱动程序,预处理器,编译器的版本号。
-pipe
在编译过程的不同阶段间使用管道而非临时文件进行通信.这个选项在某些系统上无法工作,因为那些系统的汇编器不能从管道读取数据. GNU的汇编器没有这个问题。
(此处略去36页)
5 Makefile
在GUN make是Linux环境下一个“自动化编译、生成目标程序”的命令工具。执行make命令,make程序根据makefile文件的描述完全自动编译整个软件工程,极大的提高了软件开发的效率。makefile文件按照某种语法进行编写,文件中说明如何编译各个源文件并连接生成可执行文件,并描述了源程序之间的依赖关系。
在许多集成开发环境中,用户通过友好的界面修改makefile文件。大多数的集成开发环境都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。
1、如何写Makefile:
(此处略去192页)