gcc
索引:
1.gcc特性
gcc能在生成调试信息的同时对代码进行优化。
gcc有30多个警告和3个一般警告级。
gcc对C和C++进行了大量扩展。
2.gcc编译过程
gcc首先运行预处理程序cpp来展开源文件中的宏并在其中插入#include文件所包含的内容;然后把预处理后的源代码编译成为目标代码;最后,连接程序ld创建可执行二进制文件。
使用-E选项进行预处理。如:
gcc -E hello.c -o hello.cpp
将预处理代码编译成目标代码,使用-x和-c选项。如:
gcc -x cpp-output -c hello.cpp -o hello.o
选项-x告诉gcc从指定的步骤开始编译。
链接目标文件,生成二进制代码:
gcc hello.o -o hello
3.gcc对文件扩展名的解释
扩展名 |
类型 |
.c |
C语言源代码 |
.C, .cc |
C++语言源代码 |
.i |
预处理后的C源代码 |
.ii |
预处理后的C++源代码 |
.S, .s |
汇编语言代码 |
.o |
编译后的目标代码 |
.a, .so |
编译后的库代码 |
4.常用命令行选项
(1).选项列表
选项 |
说明 |
-o File |
指定输出文件名 |
-c |
只编译不连接 |
-DFOO=BAR |
在命令行定义预处理宏FOO,其值为BAR |
-Idirname |
将dirname加入到头文件的搜索目录列表中 |
-Ldirname |
将dirname加入到库文件的搜索目录列表中 |
-static |
连接静态库,默认情况下gcc只连接动态库 |
-lFOO |
连接名为libFOO的函数库 |
-g |
在可执行程序中包含标准调试信息 |
-ggdb |
在可执行程序中包含只有GNU debugger(gdb)才能识别的大量调试信息 |
-O |
优化编译过的代码 |
-On |
指定代码优化的级别为n(0<=n<=3),如果未指定n,则默认级别为1 |
-ansi |
支持ANSI/ISO C的标准语法,取消gnu的语法扩展中与该标准有冲突部分(但这一选项并不能保证生成ANSI兼容的代码) |
-pedantic |
允许发出ANSI/IOS C标准所列出的所有警告 |
-pedantic-errors |
允许发出ANSI/IOS C标准所列出的所有错误 |
-traditional |
支持Kernighan $ Ritchie C语法(用旧式语法定义函数) |
-w |
关闭所有警告,建议不要使用此项 |
-Wall |
允许发出gcc能提供的所有有用的警告。也可以用-W{warning}来标记指定的警告 |
-werror |
把所有警告转换为错误,以在警告发生时中止编译过程 |
-MM |
输出一个make兼容的相关列表 |
-v |
显示在编译过程中的每一步中用到的命令 |
(2).gcc警告选项
-W{warning}作用是打开warning所指出的用户感兴趣的特殊警告信息。详细情况可参见帮助。
其中-Wuninitialized选项要求使用-O选项连用时才有效。
(3).优化选项
-O1级别:能执行的优化类型取决于目标处理器,但一定包括线程直接跳转(thread jump)和延迟退栈(deferred stack pops)这两种优化。
-O2级别包括所有-O1的优化和额外一些调整,其中包含对处理器指令调度的调整。
-O3包括所有-O2级优化,还包括循环展开和其他与处理器特性有关的优化。
可以使用-f{flag}选项执行特定的优化。详情参见帮助。
(4).调试选项
能够用1、2或3来限定-g选项来指定产生多少调试信息。默认的级别是2(-g2),此时产生的调试信息包括扩展的符号表、行号以及局部或外部变量的信息。3级调试信息包括所有2级信息和源代码中定义的所有宏。1级产生的信息只够创建回溯(backtrace)和堆栈转储(stack dump)之用。
-ggdb能接受的调试级别规范和-g一样。
-p选项在代码中加入prof程序能够读取的剖析符号信息,-pg在代码中加入gprof能够解释的符号信息。-a选项在代码中加入代码块(比如函数)累计使用的次数。
-save-temps选项可以保存在编译过程中生成的中间文件,其中包括目标文件和汇编代码文件。
-Q选项让gcc显示编译过程中碰到的每个函数,并提供编译器编译每个函数所花时间的剖析信息。
(5).特定体系结构的选项
gcc可以生成专门针对每种类型的cpu的代码,使用-m{value}选项。列表参见帮助。
5.GNU C扩展
使用long long类型提供64位的存储空间。
内联函数inline。
函数和变量属性attribute。
注释符//。
case区间。
构造函数名称__FUNCTION__。
6.建立静态库
生成目标代码:
gcc -c liberr.c -o liberr.o
使用ar命令生成静态库:
ar rcs liberr.a liberr.o
7.建立动态库
编译目标文件时使用gcc的-fPIC选项,产生与位置无关的代码并能被加载到任何地址:
gcc -fPIC -g -c liberr.c -o liberr.o
使用gcc的-shared和-soname选项;
使用gcc的-Wl选项把参数传递给连接器ld;
使用gcc的-l选项显示的连接C库,以保证可以得到所需的启动(startup)代码,从而避免程序在使用不同的,可能不兼容版本的C库的系统上不能启动执行。
gcc -g -shared -Wl,-soname,liberr.so -o liberr.so.1.0.0 \
liberr.o -lc
建立相应的符号连接:
ln -s liberr.so.1.0.0 liberr.so.1;
ln -s liberr.so.1.0.0 liberr.so;
gmake
索引:
由于make的共性,详细情况可参见“Unix编程工具”中make的介绍,下面仅仅列出不同的地方。
1.伪目标
伪目标就是没有依赖体的目标,如clean。因为它没有依赖体,所以它的命令不会自动执行,因为make总认为目标体是最新的而不会执行任何操作。要执行,必须输入make clean。
但是,如果确实存在clean这样一个文件,则make clean也不会执行操作,解决方法是使用.PHONY。
.PHONY的依赖体文件的含义和通常一样,但是make不检查是否存在有文件名和依赖体中的一个名字相匹配的文件,而是直接执行与之相关的命令。
如:
.PHONY: clean
clean:
rm *.o
2.变量
(1).递归展开变量
如:
TOPDIR=/home/myproject
SRCDIR=$(TOPDIR)/src
但是,
CC=gcc
CC=$(CC) -o
会出现一个无限循环。解决方法是使用简单展开变量。
(2).简单展开变量
CC := gcc -o
CC += -O2
(3).自动变量
变量 |
说明 |
$@ |
规则的目标所对应的文件名 |
$< |
规则中的第一个相关文件名 |
$^ |
规则中所有相关文件的列表,以空格为分隔符 |
$? |
规则中日期新于目标的所有相关文件的列表 |
$(@D) |
目标文件的目录部分(如果目标在子目录中) |
$(@F) |
目标文件的文件名部分(如果目标在子目录中) |
3.模式规则
使用%。如:
%.c: %c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
gdb
索引:
1.命令行
gdb progname [ corefile | pid ];
2.常用选项
-d dirname:指定源代码的目录,缺省在当前目录下。
-q(--quiet):不显示许可信息。
3.运行程序
(1).命令
run [ arg1 arg2 … ];
(2).参数
除了在run时指定参数外,也可使用set命令:
set args arg1 arg2 …;
(3).设置环境变量
set environment env1 env2 …;
4.查看代码
(1).backtrace
命令backtrace(back)查看导致错误的函数树。
(2).list
命令list[m,n]显示代码的上下文,m和n是显示代码段的起始行和结束行。不带参数的list显示当前行附近的10行代码。
5.检查数据
(1).显示变量值
命令print。
举例:
print num;
打印变量num的值。
print $1 - 1;
$1和$2是被检查数值的历史纪录项。
print ary@10;
打印从ary开始的头10个内存区域。
print ary[0]@10
打印数组ary的头10个值,注意与上例的区别。
(2).变量类型
命令whatis。
(3).变量类型的定义
命令ptype。
(4).更改变量的值
set variable varname = value;
如:
set variable I = 10;
(5).变量的作用域和上下文
如果某个函数(称为控制函数)正在执行或者该函数将控制流程传给一个由控制函数调用的函数,那么该函数里的局部变量处于活动状态。
全局变量不管程序是否运行总是活动的。
非全局变量是非活动的,除非程序运行。
静态变量是局部于文件的,标示的方法如下:
‘file'::varname;
funcname::varname;
如:
print ‘foo.c’::baz;
print &blat::idx;
6.设置断点
(1).根据行号设置断点
break linenum;
(2).根据函数名设置
break funcname;
(3).在指定文件内部设置
break filename: linenum;
break filename: funcname;
(4).条件断点
break linenum(funcname) if expr;
如:
break 24 if I == 15;
(5).在断点后继续执行
命令continue。
(6).显示断点信息
info breakpoints。
(7).删除断点
delete break-no;
(8).使断点无效/有效
disable/enable break-no;
7.单步执行
(1).step
step命令一次执行一条语句,遇到函数调用将进入函数;
(2).next
next命令一次执行一行,不进入函数。
8.函数调用
(1).call
call name(args),调用并执行名为name,参数为args的函数。
(2).finish
如果可以,则中止当前函数并打印它的返回值。
(3).return
return value,停止执行当前函数,并将value返回给调用者。
(4).where
显示逆序的函数调用链。
(5).up
将调用栈上移一个函数调用。
(6).down
将up调用上移的栈移回。
9.查找
(1).search
search <字符串>,查找一个特定字符串在当前文件中的下一次出现。
(2).reverse-search
反向查找。
10.shell
shell command;
执行shell命令。
11.调试正在运行的程序
(1).附加到进程
gdb progname pid;
或
使用attach和file命令。
附加到一个正在运行的进程将自动将其停止以便能使用常规的gdb命令检查它的状态。
(2).与进程分离
detach或quit命令。从进程分离并允许它继续执行。
如果已经在gdb中运行了一个程序,而又要附加到另外一个运行的进程上,那么必须杀死目前运行的这个程序。
cvs
索引:
1.权限设定
(1).设定规则
cvs用户必须拥有对$CVSROOT/CVSROOT目录及其中所有文件的读权限。
cvs用户必须拥有对$CVSROOT/CVSROOT目录下history文件的写权限。
cvs用户如果希望拥有修改某个项目(模板)代码等资料的权利,必须拥有对该目录的写权限。
cvs系统的权限控制依赖于操作系统,可利用操作系统本身的权限设置来控制cvs的权限。
(2).口令文件
pserver认证方式以明文在网络上传输cvs密码。使用口令文件允许cvs用户使用与系统帐号密码不同的密码。
口令文件在服务器的$CVSROOT/CVSROOT/passwd文件。格式为:
cvsuser:[passwd][:sysuser]
口令passwd从/etc/passwd或/etc/shadow获得。
口令文件的安全性很重要,应该将该文件的读写权限仅限于root。
如:
anonymous:
ken:aWTrltv4Ae:pubcvs
(3).设定只读用户
在$CVSROOT/CVSROOT/readers文件里,每行记录一个cvs用户名。
(4).设定具有写权限的用户
在$CVSROOT/CVSROOT/writers文件里,每行记录一个cvs用户名。
同时在readers和writers里的用户只拥有读权限。
2.配置cvs口令服务器
(1).inet服务器
文件/etc/services:
cvspserver 2401/tcp
文件/etc/inet.conf:
cvspserver stream tcp nowait root /usr/local/bin/cvs cvs -f \
--allow-root=$CVSROOT pserver
(2).xinet服务器
编辑cvspserver文件:
service cvspserver
{
port = 2401
socket_type = stream
wait = no
user = root
server = /usr/bin/cvs
server_args = -f --allow-root=$CVSROOT pserver
}
(3).客户端配置
设置环境变量CVSROOT:
CVSROOT=:pserver:username@hostname(ip):[port]path
如:
:pserver:cvsadm@10.10.16.177:2402/home/cvsroot
:pserver:cvsadm@10.10.16.177:/home/cvsroot
(4).客户登录/注销
cvs login
cvs logout
3.初始化服务器
如果设置了环境变量CVSROOT,则执行:
cvs init
否则,执行:
cvs -d path init
其中path等于$CVSROOT。
4.使用基础
(1).创建新项目(模板)
进入项目所在目录:
cvs [ -d $CVSROOT] import [-m log] name VENDOR START
VENDOR表示开发者的标识,START表示起始版本标签。
如:
cd eSWITCH
cvs import eSWITCH v s
(2).捡出工作拷贝
cvs checkout [ -d dir ] module
局部选项-d表示将拷贝放到目录dir下,而不是在一个与module名一样的目录下。
cvs使用文件的时间戳,所以保持服务器和客户端的时钟同步是很重要的。
(3).比较仓库和拷贝的区别
cvs diff filename
cvs diff -c filename(使用对照方式)
(4).提交工作拷贝
cvs commit [-m log] [filename]
当一次提交多个文件时,这些文件共享同一个日志信息。
(5).更新工作拷贝
cvs update [ filename ]
(6).查看日志信息
cvs log filename
(7).版本回退
方法一:取出旧版本,重新提交。如:
cvs update
cvs up -p -r1.2 test.c >test.c
cvs ci test.c
方法二:使用join(合并)选项。如:
cvs up -j 1.3 -j 1.2 test.c
cvs ci test.c
把1.3版本与1.2b版本之间的差异补到当前1.3版本上,相当于从1.3版本上将1.2到1.3之间的变化又减去了。
(8).添加目录或文件
创建一个目录或文件后,执行:
cvs add newfile
对于文件,还要做提交:
cvs ci newfile
(9).删除文件
rm newfile
cvs remove newfile
或:
cvs remove -f newfile
最后,进行提交:
cvs ci newfile
(10).删除目录
首先删除该目录下所有文件,然后使用update的-P选项删除目录:
cd newdir
cvs remove -f new.c
cd ...
cvs update -P
执行cvs update时,cvs并不会自动取出在工作拷贝创建之后新添加到仓库的目录。解决方法是使用update的-d选项:
cvs update -d
(11).重命名文件
方法一,先从cvs中删除旧文件,再添加新文件:
mv old new
cvs remove -f old
cvs ci old
cvs add new
cvs ci new
方法二,直接修改服务器上的文件,要确保没有人访问这个文件,否则将引起不可预知的后果:
cd $CVSROOT/module
mv old,v new,v
(12).重命名目录
方法一,创建新目录,将旧目录下的文件移到新目录下,删除旧文件,添加新目录,添加新文件:
mkdir newdir
mv olddir/* newdir
cvs remove olddir/*
cvs ci
cvs add newdir
cvs ci newdir
方法二,直接再cvs服务器仓库中移动目录:
cd $CVSROOT/module
mv olddir newdir
5.常用命令缩写
cvs checkout:cvs co;
cvs commit:cvs ci;
cvs update:cvs up;
cvs status:cvs st;
6.标签的管理
(1).创建标签
cvs tag tagname
(2).标签命名
以字母开头,中间可以含字母、数字、下划线、连字符。
(3).删除标签
cvs tag -d tagname
(4).重命名标签
先贴上新标签,再删除旧标签:
cvs tag -r tag1 tag2
cvs tag -d tag1
(5).修改某个文件的标签指到别的版本
cvs tag -r new-version -F tag1 filename
如:
cvs tag -r 1.6 -F tag1 test.c
(6).查看标签
cvs status -v filename
(7).特定约束标签
按照日期贴标签:
cvs rtag -D date tagname module
按照已经版本/标签贴标签:
cvs rtag -r revision/tag newtag module
(8).获取某个特定版本
cvs update -r revison/tag module
cvs update -D date module
(9).恢复到最新版本
cvs update -A
7.版本分支
(1).分支版本号
在x.y版本上的分支编号依次是x.y.2、x.y.4、x.y.6等等。
(2).在工作拷贝中创建分支
取出某一版本的代码:
cvs checkout -r tag module
创建:
cvs tag -b branch-tag module
(3).直接在仓库中创建分支
cvs rtag -b -r tag branch-tag module
(4).访问版本分支
方法一、捡出:
cvs checkout -r branch-tag module
方法二、版本切换:
cvs update -r branch-tag
(5).将分支合并到主干
在主干目录下,执行:
cvs update -j branch-tag [ filename ]
每次合并都会把从分支基部到分支最新版本之间的全部修改都合并到主干中。
可以指定合并的版本范围。如:
cvs up -j 1.1.1.1.6.1 -j rel-20021010-brach test.c
把分支rel-20021010-brach从1.1.1.1.6.1到最新版本之间的修改合并到主干上。
进行多次反复合并的一个技巧是在每次合并之后,将分支再贴上标签,这样,每次合并时的分支版本都有标签可以标识。
(6).将主干合并到分支
在分支目录下,执行:
cvs update -j HEAD
其中HEAD是关键字,表示主干代码树的头部,也就是全部最新的主干代码版本。
8.cvs输出export
取出一份没有cvs痕迹的源代码:
cvs exprot -r tag [ -d dir ] module
9.清除工作拷贝
cvs release -d module
10.日志管理
(1).查看详细修改记录
cvs annotate [ -r revision/tag | -D date ] [ filename ]
(2).查看历史记录
cvs history
(3).修改日志信息
cvs admin -m revsion: “messages” filename
对于共享日志,需要对每个文件单独执行上述操作。
11.关键字扩展
cvs中的关键字用两个“$”符号,中间是一个rcs的特定关键字。常用列表如下:
$Revision$
自动扩展为版本号。
$Log$
累计日志信息。
每次更新都进行累加,如果太长,可以手工删除旧的注释。
$Author$
扩展为提交版本的用户的用户名。
$Date$
上一次提交的日期、时间。
$Id$
扩展为文件名、版本号、日期、作者、状态,如果被锁定,还有锁定者的用户名。
$Source$
扩展为带有完整路径的源代码文件名。
12.模块配置
(1).定义模块步骤
修改模块文件需要先checkout:
cvs checkout CVSROOT/modules
修改完毕提交:
cvs ci CVSROOT/modules
(2).语法
module-name [ options ] dir [ files …]
(3).使用举例
由project/acctmgmt组成的模块:
acctmgmt project/acctmgmt
有目录下的三个文件组成的模块:
acctmgmt prject/acctmgmt readme install license
不包含指定目录下的子目录doc:
acctmgmt !project/acctmgmt/doc project/acctmgmt
定义别名(有三个模块组成):
acctmgmt -a init mm file
引用:
lk & linux_kernle
(4).模块选项
-d name:让工作拷贝的名字为参数值而不是模块名;
-e prog:文件被输出(exprot)时执行的程序;
-i prog:提交模块时执行的程序;
-o prog:捡出模块时执行的程序;
-s status:给模块定义一个状态;
13.二进制文件配置
在cvs中保存二进制文件,要使用“-kb”选项来禁止cvs对文件进行加工。该选项只需要在cvs add时使用。“-kb”是一个Sticky Option。
(1).cvswrappers
通过配置$CVSROOT/CVSROOT/cvswrappers文件,使cvs根据文件扩展名来区别二进制文件。
(2).修改方法
同modules的方式。
(3).语法
wildcard [ option val ] [ option val ] …
(4).选项
-m MERGE|COPY:更新方式,MERGE表示更新时进行版本间差异的合并,COPY表示直接拷贝,不进行合并处理。
-k ‘b’|’o’|’kkv’:关键字扩展,’b’表示二进制;’o’表示“off”,不进行关键字扩展,但它仍进行不同平台之间的回车、换行转换;’kkv’表示扩展关键字的值。
(5).使用举例
*.gif -k ‘b’
*.jpg -k ‘b’
*.doc -k ‘b’
*.bmp -k ‘b’
*.mpp -k ‘b’
*.xls -k ‘b’
*.ppt -k ‘b’
14.触发器文件
(1).commitinfo
定义每次提交发生时执行的程序。被提交的文件名作为程序的参数。
(2).loginfo
定义在提交操作完成之前被触发的程序,用户提交时写的日志信息传送到程序的标准输入。
(3).verifymsg
提交时,日志信息送到定义的程序的标准输入,程序返回0则进行提交,返回非0则提交被终止。
(4).rcsinfo
定义日志文件的模板文件。
(5).taginfo
定义贴标签时执行的操作,标签字符串、标签操作、仓库、文件版本作为参数传递给程序。
15.其他配置文件
(1).checkoutlist
指定自定义的配置文件,使其置于cvs的版本管理之下。
(2).cvsignore
指定被cvs忽略的文件类别。
缺省忽略的文件类型如下:
RCS SCCS CVS CVS.adm
RCSLOG cvslog.*
Tags TAGS
.make.state .nse_depinfo
*~ #* .#* ,* _$* *.$
*.old *.bak *.BAK *.orig *.rej *.del-*
*.a *.olb *.o *.obj *.so *.exe
*.Z *.elc *.ln
core