- 浏览: 20727 次
- 性别:
- 来自: 北京
最新评论
Linux下的基本操作速查
涉及的内容:
1) 连接服务器;
2) Shell常用命令与常用参数;
3) VIM 的使用;
4) Linux更新软件;
5) GCC的常见参数;
6) GDB调试程序;
7) Makfefile的编写;
8) 代码注释,文档管理:开源Doxygen;
9) 版本控制:SVN常用命令;
连接到Linux服务器
用SecureCRT 连接Linux服务器。安装完成后从File菜单选择Quick Connect即可。使用SSH1协议,在连接时注意。
为了方便起见,建议在安装完成后作如下设置:
Options -> Global Options -> Default Session -> Edit Default Settings
Connection -> Protocol SSH1
Terminal -> Emulation-> Terminal Xterm
Terminal -> Emulation-> ANSI Color On
Terminal -> Appearance-> Current Color Schema Traditional
建议在Windows上安装虚拟机学习;
如何使用Shell
刚登录到Linux时,会显示Bash Shell提示符如下。现在你可以使用Shell命令来指挥Linux。
l ===常识===
linux用"/"而非"\"来分隔目录,/dir/.表示/dir这个目录,而/dir1/dir2/..表示/dir1这个目录。
shell总是有一个当前目录,文件的相对路径(不以"/"开头的路径)从当前目录开始计算
cat sort等处理文件内容的命令,在没有文件名时处理标准输入(键盘输入)
*和?是文件名通配符,*代表示任意数量字符,?代表单个字符。通配符由shell而非命令自身解释,因此ren *.bak *.sav这样的dos操作是不可能的。
l ===目录相关===
pwd 显示当前目录,
cd /dir1/dir2 修改当前目录为/dir1/dir2
mkdir newdir 在当前目录下建立新目录newdir
rmdir olddir 在当前目录下删除旧目录olddir
ls -l 列出当前目录下所有文件
ls -la 列出包括以"."开头的隐含文件
l ===解决乱码或者其他中文字符集问题===
export LC_ALL=
export LC_CTYPE=zh_CN.gbk
l ===文件操作===
rm foo bar etc 删除文件foo bar etc
mv foo bar 文件改名foo1改成bar
mv src1 src2 … dst 把文件移动到dst目录
cp src dst 把文件src拷贝为dst
cp src1 src2 … dst 把文件拷贝到dst目录
scp … root@host:path 把文件拷贝到主机host的目录path下
scp root@host:path dst . 把文件从主机host的目录path下拷贝到当前目录
ln -s old new 为文件old建一个符号连接new
l ===文件内容操作===
cat foo 显示文件foo的内容
head -n100 foo 查看文件foo的前100行
tail -n100 foo 查看文件foo的尾100行
diff -u foo bar 对比文件foo和bar
sort foo 按字母排序文件foo
sort -n foo 按数字排序文件foo
sort foo | uniq -c 统计文件foo中每行出现了多少次
fgrep xxx files 在文件中检索字符串xxx
l ===查看帮助===
man bash 查看bash shell的内部命令,按q退出
info coreutils 查看最常用的那些命令,按q退出
man ls 查看命令ls的帮助
man -a printf 查看printf的所有帮助,按q切换到下一个帮助。像printf这样同时出现在shell/c/perl等多个环境中的命令会有多个帮助。
man -K printf 在所有的帮助文件中搜索printf
l ===简单管理===
ps aux 列出当前所有的进程,注意PID和COMMAND两列
top 实时显示当前系统负载和最活跃的进程。
按1显示多cpu详情,按shift-m显示内存最多的进程
kill 1234 杀死PID为1234的进程
kill -9 1234 强行杀死PID为1234的进程(如果kill不行的话)
netstat --anp 列出当前所有的tcp/udp连接以及相关的进程
l ===打包===
一般用tar打包,包有.tar.gz(.tgz)以及.tar.bz2两种格式
tar cvzf a.tar.gz foo 把foo下的所有文件打包成a.tar.gz
tar xvzf a.tar.gz 把a.tar.gz解包到当前目录
tar xvjf a.tar.bz2 把a.tar.bz2解包到当前目录
如何使用VIM编辑文件
首先,正确的设置vim环境会使用更加舒服,执行以下命令设置环境:
echo -e "set nocp\nsyntax on\nset ts=4\nset sw=4\nset si\n" >> ~/.vimrc
vim foo 启动vim,并编辑文件foo
vim和Windwos的编辑器不一样,它有2种模式:命令模式和编辑模式。刚启动vim时处于命令模式,此时可以移动光标和发布命令。常用命令:
i r <insert> 进入编辑模式
<esc> 离开编辑模式
:q :q! 退出/强制退出
:w :w! 存盘/强制存盘
:wq :wq! 存盘退出/强制存盘退出
? / 向前/向后查找文本
gg G 移动到文件头/文件尾
dd 删除当前行
v V 开始选择文本/开始按行选择文本
y 将v/V选中的文本放入剪贴板
p 粘贴剪贴版的内容
J 将下一行拼到当前行尾
:%s/old/new/g 全文替换old为new
<ctrl-]> 如果有make tags的话,查找当前标识符的定义
:make 在当前目录执行make,并移动到第一个编译错误
Shell进阶
===egrep 正则表达式检索===
egrep pattern files 在文件中检索pattern,显示匹配的行
pattern 由若干atom组成,atom定义如下
. 匹配任意字符
[abc] 匹配abc三个字母任何一个
[^abc] 匹配除abc三个字母以外的任何字符
[a-h] 匹配abcdefgh中的任何一个
<atom>? ?前一个atom匹配0~1次
<atom>+ +前一个atom匹配至少1次
<atom>* *前一个atom匹配任意次
<atom1>|<atom2> 匹配两个atom中的任何一个
(<atom1><atom2>…) 用"("和")"把多个atom编成一组
\ 转义符,例如"\."精确匹配".","\t"匹配tab字符
^ 表示一行的开始
$ 表示一行的结束
其他普通字符都是atom
例子:
([a-z]\.)[a-z]+ 匹配任何纯由小写字母组成的域名
egrep常用参数
-o 显示匹配上pattern的串
-v 显示没有匹配pattern的那些行
-n 显示行号 ===输入输出重定向和管道===
一般情况下程序从键盘读取用户输入,输出到显示器。我们可以通过"<" ">" "|"操作符来改变这种行为。
ls > file 把ls的结果存到文件file,file原有的内容被销毁i
ls >> file 把ls的结果存到文件file原有内容的尾部
ls -xxx &> file 把ls的错误信息和正常输出都存到文件file
foo < file 用文件file作为命令foo的输入
ls | sort 把ls的结果做为sort的输入
ls 2>&1 | sort 把ls的结果和出错信息一起做为sort的输入
ls | tee file 利用tee命令把ls的结果存到文件file并同时显示在荧幕上。 ===后台任务===
在程序运行的过程中,按ctrl-z可以把程序切换到后台挂起,此时程序暂停执行。
启动程序的时候,在命令行的最后加"&",可以让程序直接在后台执行
grep xxx file > yyy & 在后台执行grep命令
jobs 显示当前后台有哪些程序
fg 9 把第9号后台程序切换到前台
bg 9 让第9号后台程序恢复执行(用于ctrl-z挂起的程序)
Windows和Linux互传文件
如果你使用SecureCRT,那么可以用rz命令传送文件到linux,用sz命令传送文件到Windows,但是这两个命令在处理大文件时往往有问题。
你可以安装winscp来传送文件
用yum或者apt-get补充安装rpm软件包
rpm是linux下常用的软件包封装格式。
rpm -ivh xxx.rpm 安装xxx.rpm
rpm -qa 显示系统上已经安装了哪些rpm
rpm -ql xxx 显示xxx包括哪些文件,xxx需要已经安装
rpm -e xxx 删除xxx
rpm -qf /bin/ls 查找/bin/ls属于哪个rpm包
rpm比自己下载源码要方便,但是去哪里下载rpm仍然是个问题。Linux发行版一般都附带了大量的rpm,但是并没有默认全部安装。Redhat提供了yum工具用于安装和管理系统附带的rpm软件包。使用软件和编译程序时如果发现缺少对应的工具或者库文件可以用yum补充安装。
yum search xxx 搜索名字和描述中带有xxx的软件包。
yum install xxx 安装xxx以及xxx依赖的rpm到最新版本。
例如,我们编译时发现找不到zlib相关的头文件。首先用”yum search zlib”发现有一个包叫做zlib-devel.i386,然后用”yum install zlib-devel”安装它即可。
某些系统用的是apt-get来管理rpm
apt-cache search xxx 搜索xxx
apt-get install xxx 安装xxx
参考
Bash新手指南
http://xiaowang.net/bgb-cn/
Shell设计入门
http://www.newsmth.net/bbscon.php?bid=392&id=320837
C/C++的开发 GCC/GDB/Make
在Linux下,我们用gcc来编译C/C++程序,用GDB调试程序,并用make工具来把多个源文件组织成project。如果缺乏耐心的话,请直接跳到本章的最后快速指南[Makefile模板[14页]]学习如何快速开始一个项目。
gcc
gcc – the GNU Compiler Collection。 能编译C,C++和一些其它语言编写的程序。
gcc特性
和其它编译器一样,gcc的编译过程可分为4个阶段:预处理,汇编,编译和链接。gcc的使用者可以在任何阶段停止整个编译过程,并得到该阶段的输出信息。
gcc也有优化代码和生成调试信息的功能,一般我们编译代码的时候,都会加入调试信息,这样代码出现问题的时候容易追查。但编译器优化过的代码往往不方便调试,因此,代码优化只有在正式上线的时候才会被使用。
此外gcc支持30多个警告和3个警告级别,支持交叉编译(生成非本机体系结构的二进制代码),还对标准C和C++进行了大量扩展,以提高执行效率和编程的方便性。但我们不建议使用这些扩展,因为这会影响代码的可移植性。
gcc使用
编译文件hello.c的基本方式是:
gcc hello.c --o hello
其中hello.c是输入文件,-o选项的内容为输出文件。该命令编译并链接hello.c,生成文件为hello可执行文件。如果不加-o参数,则为gcc最简单的用法:
gcc hello.c
此时gcc生成文件名为a.out的可执行文件。
编译多个源文件(如hello.c和world.c):
gcc hello.c world.c --o helloworld
实际使用中,建议先把多个源文件编译成为目标文件,再进行链接生成可执行文件:
gcc --c hello.c
gcc world.c -c
gcc hello.o world.o --o helloworld
上例中的-c选项表示只对源文件做编译处理,生成目标文件,没有加-o参数,此时编译器生成与源文件同名的.o目标文件(为别为hello.o和world.o),第三个命令把各个.o文件链接成可执行文件。
注意各参数和输入文件在命令中顺序可任意。例如第三句可以写成(不推荐)
gcc hello.o --o helloworld world.o
只对源文件进行预处理(包括头文件展开,宏展开等),可用-E参数。例如:
gcc --E --o hello.cpp hello.c
先成的文件名为hello.cpp。在unix系统下,.cpp文件表示预处理过的C/C+文件。而对于C+源文件,一般使用.cc或.cxx的扩展名。
很多时候我们还需要观察gcc产生的汇编代码,可用-S参数:
gcc --S hello.c
此时gcc生成文件名为hello.s的汇编语言文件。
调试与优化
优化的目的是改进程序的执行效率,代价是延长编译时间,也可能会增加产生的二进制文件的大小,增大调试难度。
优化参数包括-O0,-O1(等同于-O),-O2和-O3,优化程度递增。如果不加优化参数,则相当于--O0,不优化。在O0下内联函数不会被展开。一般在编译Linux内核的时候使用参数-O2,因为O3参数会展开一些非内联函数,增加二进制代码量,这对Linux内核是不能接受的。对于一般的应用,使用O3优化也是安全的。
优化参数只需在编译的时候指定,链接时不需要,例如:
gcc hello.c --c --O2
gcc --o hello hello
编译优化在理论上不会影响程序的逻辑,如果出现优化后代码运行异常,则很可能是源程序本身有bug。
gcc可通过-g参数在生成的代码里加入调试信息,以方便调试时的会话过程。和优化参数一样,-g也只需在编译的时候指定:
gcc --g --c hello.c
gcc --o hello hello.o
Unix下常用的调试工具gdb(GNU Debugger)将在下一部分介绍。用户还可通过-ggdb参数来加入更多的只能被gdb识别的调试信息。
注意,尽量避免-g和-Ox一起使用。编译优化会改变代码执行顺序被打乱以加快运行速度,但调试会变得很困难。
其它常用参数
-I::指定一个头文件路径。可用多个-I参数指定多个头文件路径。只在编译时有效。
-L::指定一个库文件路径。和-I一样可指定多个。只在链接时有效,经常和-l一起使用。
-l:指定一个库文件名。Linux下库文件的文件都是libXXX.so或libXXX.a的形式,分别是动态链接库和静态链接库。例如数学函数库文件为libm.so和libm.a,SSL的函文件为libssl.so和libssl.a。gcc在链接时-l参数只需指定库文件名的中缀部分。例如hello.c中调用了数学库的cos()函数,则:
gcc --g --c hello.c
gcc --o hello hello.o --lm
-Wall:实际上是-W参数加”all”。可让gcc打开所有的警告。在调试代码时建议使用。
-static:所有引用的库都静态链接。将会增加可执行文件的大小。
gdb
gdb介绍
gdb – the GNU Debugger。Linux下用得最多的命令行调试器。使用gdb对程序进行调试的前提是可执行文件有调试符号,在编译时需使用-g或-ggdb参数(见上一节),同时不打开编译优化。
gdb基础
启动gdb有三种常用的方法(直接启动,调试core文件和调试运行中的进程)。直接启动gdb的方法如下。
gdb test
此时会启动对程序test的调试,进入gdb交互界面。
在gdb中输入run(或r)命令表示运行程序,如果程序需要参数(main的参数),在run之后加入参数即可,例如:
(gdb) run arg1 arg2
run命令将运行到程序正常退出,或遇到断点,或被用户Ctrl-C,或出现异常,例如段错误(内存访问超出进程的地址空间),除0,总线错误,以及其它一些使程序无法运行下错误。当程序中断时(断点或Ctrl-C或异常),gdb会显示中断的代码位置。可用list(或l)命令来查看中断位置前后(共10行)代码。list命令每运行一次,查看10行代码,同时查看点也向后推进10行。list命令也可指定要查看的源文件名和位置,例如:
(gdb) list test.c:100
或当前文件就是test.c的话,等价于:
(gdb) list 100
此时gdb显示test.c的第95行到104行的代码。如果再敲入一次list,则显示从105行到114行。
程序中断是可用print(或p)命令来查看各变量的值。print命令支持所有C语言的语法。例如查看结构体指针a的域x:
(gdb) print a->x
通过where(或bt)命令可查看程序的中断位置,此会gdb会显示当前的函数调用层次。通过up命令可退回到上一级函数,以查看上一级函数中的变量情况。与up相对应的命令是down。
断点的使用
调试出问题的代码的时候,在某一点停止执行往往很管用。gdb支持几种不同的设置断点的方式,包括行号和函数名。还允许设置条件断点,即只有满足一定条件,代码才会在断点处停止执行。设置断点的命令为break(或b),例如:
(gdb) break test.c:100
(gdb) break 100
(gdb) break func1
(gdb) break 100 if (a->x==5)
其中,条件断点语句的条件部分支持C语言的所有语法。当程序在某个断点中断时,则可用上面说到的print命令来查看各变量的值,up,down命令来查看程序各级函数中的状态。注意up,down命令只会影响查看点,并不会改变程序当前执行到的位置。
让程序在断点中断之后继续运行,包括几个常用的命令。
continue(或c)命令让程序继续运行,直到遇到下一个断点;
next(或n)命令让程序执行下一条语句,如果下一条语句是函数,不进入函数内部;s
tep(或s)命令执行一下条语句,遇到函数则进入函数内部。
finish(或fin,maybe)可让程序继续运行,直到当前函数返回;
return(或ret?)命令让函数立即返回,返回后程序仍处于中断状态。return命令可加返回值,例如:
(gdb) return 20
即让当前函数立即返回,返回值为20。注意的时让函数从一个非正常的点返回,后果可能很严重,但在调试中有时也很有用。在程序中断时还可以通过call命令来调用函数,例如:
(gdb) call a=func(20)
此时gdb调用了func函数并把返回值赋予变量a。如果func函数中也有断点,程序也会在断点处被中断。
如果要删除某个断点,首先找到要删除断点的id号,方法是:
(gdb) info break
此时gdb会显示当然的所有断点位置和对应的id。用delete(或del?)命令加id号删除对应的断点;delete不加参数则删除所有的断点。另外,用disable和enable命令可让断点临时关闭和重新打开。
调试core和调试进程
对于运行中的进程,如果出现一些异常无法继续运行,会在程序的运行目录下留下一个core文件,就是我们常说的“程序core了”。core的原因是程序/进程收到了某些会让程序core的信号(准确的说是让程序流产的信号),常见的有SIGSEGV(程序出现段错误,越界访问,最常见),SIGABRT(如程序调用了abort()函数,abort本身就是流产的意思),SIGFPE(浮点异常)。当程序core了之后,会在运行目录留下一个core文件,文件名为core.XXXX,XXXX为进程号pid。如果发现怎么程序异常退出却没有core文件,系统设置的问题。用以下命令允许产生无限大的core文件:
ulimit --c unlimited
假设我们的程序名为test,产生了文件名为core.1234的core文件,通过以下命令启动gdb来调试core:
gdb test core.1234
进入gdb之后,会显示出程序异常的位置。再通过上面介绍的gdb命令查看异常时程序的状态,就可以比较方便的找到程序bug所在。注意程序core了之后已经不在运行状态,因此和运行相关的命令,如run,continue,next, step,finish,return,call,在调度core的时候无法使用。break也是没有意义的。
gdb还可以调试一个正在运行中的进程,方法是:
gdb --p <进程号>
进入gdb之后进程被gdb中断,gdb显示中断位置。此时调试的方法与普通启动gdb方式几乎无异,也可以使用运行相关命令来控制进程的推进。唯一的区别是,使用exit(或Ctrl-D)命令退出后,被调试的进程会继续运行,而不是结束。
其它常用命令
kill – 杀死当前的调试进程,对于core调试无效,因为core已经是死掉的进程。
info thread – 显示所有线程和id号。
thread <id> – 切换到某个线程。
set variable <variable name>=<expression> – 改变变量的值,对core调试无效,支持C语法。例如:
(gdb) set variable i=x+5
ptype <variable> – 显示变量的数据类型。
shell [cmd] – 执行一个shell命令。如果[cmd]为空,则进入shell。在shell中exit或Ctrl-D返回gdb。
help – 当你需要其它帮助。
Makefile
Makefile的原始形式
Make是linux最基本的工程描述工具。编写Makefile以后,简单的键入make all就能方便的编译整个项目而不用一次次手工调用gcc。先来看一下一个最基本的Makefile,它描述了如何从s1.cpp s2.cpp编译产生程序test:
objects=s1.o s2.o ##变量定义
all: test ##一般用all表示生成所有目标
test: $(objects) ##普通依赖关系
g++ $+ -o $@ ##从s1.o s2.o如何生成test
%.o:%.cpp ##从.cpp文件编译.o的依赖模板
g++ -g -O2 -c $< ##具体如何编译
clean: ##一般用clean表示清除所有目标和中间文件
rm -f test *.o ##
[kirbyzhou@sohu]$ make ##编译test
g++ -g -O2 -c s1.cpp
g++ -g -O2 -c s2.cpp
g++ s1.o s2.o -o test
[kirbyzhou@sohu]$ make ##再次编译,因为文件没有变化,所以什么都没发生
make: Nothing to be done for `all'.
[kirbyzhou@sohu]$ make clean ##清理
rm -f test *.o
Makefile的文件名必须是严格的”Makefile”,make会在当前目录下查找Makefile文件。Makefile主要由3部分组成:1.变量定义;2普通依赖关系(explicit rule);3.模板依赖关系(implicit rule)。格式分别如下:
TARGET : PREREQUISITES ##TARGETS直接依赖于PREREQUISITES
<TAB>COMMAND ##从PREREQUISITES如何产生TARGET
%.DST : %.SRC ##.dst文件依赖于.src文件,例如.o和.cpp的关系
<TAB>COMMAND ##从PREREQUISITES如何产生TARGET
在COMMAND中可以用$+表示PREREQUISITES,用$@表示TARGET,用$<表示第一个PREREQUISIT。例子参见上文。
用Automake/Autoconf自动生成makefile
涉及的文件增多以后,Makefile变得很难维护。首先是依赖关系的复杂性:s1.o不仅仅是依赖于s1.cpp,它可能还依赖于s1.h s2.h s3.h等等;其次如何生成库、动态库等等都比较复杂;各人的Makefile风格迥异很难修改;最后是缺乏统一的子目录管理机制。总之靠人工来维护Makefile是非常辛苦的。为此人们发明了一系列工具用于简化Makefile的编写,并统一Makefile的风格。
automake/autoconf是一套比较成熟的工具,它主要涉及到1个configure.ac和若干个Makefile.am
l Makefile.am一般每个子目录一个,一个最简单的Makefile.am如下,已经可以满足绝大部分的需求:
bin_PROGRAMS=demo1 demo2 ##我要编译demo1 demo2这两个程序
lib_LTLIBRARIES=libdemo3.la ##我要编译libdemo3.la这个库
demo1_SOURCES=demo1.cpp func.cpp f.h ##demo1的源码
demo2_SOURCES=demo2.cpp func.cpp f.h ##demo2的源码
libdemo3_la_SOURCES=demo3.cpp demo3.h ##libdemo3.la的源码
SUBDIRS=sub1 sub2 ##如果有子目录要build的话,列在这里
Makefile.am首先定义需要build哪些target,语法如下:
[bin|lib|libexec|…|noinst]_[SCRIPTS/PROGRAMS|LIBRARIES|LTLIBRARIES]=target1 target2 …
其中””前说明target会被安装到$(prefix)下的哪个目录,noinst表示不安装;””后是target的类型------脚本/可执行程序/静态库/动态库。注意静态库和动态库分别要满足lib*.a lib*.la的命名。
然后是每个target相关的源码,automake会自己处理源码间的关系:
<target>_SOURCES=src1.c src2.cpp header1.h header2.hpp
这里如果target是X.Y这样的形式,要写成X_Y_SOURCES=…的形式
l 在项目的topdir里还需要一个configure.ac,描述一些全项目的信息
AC_PREREQ(2.57) ##样板戏,不用管它,下同
AC_INIT(demopkg, 0.5.1) ##整套程序的名字、版本号
AM_INIT_AUTOMAKE([foreign]) ##样板戏,让autoconf按最糙的要求审核我们的程序
AC_PROG_CC ##样板戏,检查C编译器
AC_PROG_CXX ##样板戏,检查C++编译器
AC_PROG_LIBTOOL ##样板戏,检查用于生成动态库的libtool工具
AC_CONFIG_FILES([
Makefile demo/Makefile ##在[]里列出需要自动生成的Makefile
])
AC_OUTPUT ##最后一行样板戏
l 最后执行autoreconf --is && ./configure就可以开始make了。
l 常用的make目标有all(缺省target,build项目),clean(清理),install(安装),uninstall(反安装),check(测试),dist(源码打包),distcheck(检查打包后的源码能否正常工作)。
快速指南:
=== 编写Makefile ===
编写Makefile 参见[Makefile模板[14页]]
make 用makefile编译整个工程
make clean 清除make的结果和中间文件
=== GCC ===
gcc a.c 编译纯C程序a.c为可执行程序a.out
g++ -g s1.cc s2.cpp -o dest 把源文件s1.cc s2.cpp编译成可执行程序dest
g++ -g -O0 src.cpp -o dest 禁止优化的编译,这样方便调试
g++ -I/opt/include … 附加的include目录
g++ -L/opt/lib -lACE … 附加的lib目录,并链接库libACE.so
==== GDB ===
gdb test 调试程序test
gdb test 12345 调试进程PID为12345的程序test
gdb test core.123 调试程序test崩溃后留下的现场core.123
ulimit --c unlimited 使程序崩溃后有机会留下现场
==== GDB 命令===
r arg1 arg2 … 运行程序,arg1 arg2 …是传给程序的参数
l 列出代码
l a.cpp:100 列出a.cpp第一百行附近的代码
b 100 在第100行设置断点
<ctrl-c> 中断程序
p x 打印变量x的值
set variable x = y +2 改变变量的值
n / s / c 单步/深入单步/继续
bt 察看函数调用层次
up / down 转到上一级/下一级函数
kill 杀死当前的调试进程
info thread 显示所有线程和id号
thread 3 切换到线程3
参考
GCC常见编译选项
http://dev.csdn.net/author/ganxingming/d4fabf69cc48471fbcbc7b9be2a908dc.html
GDB手册 http://www.newsmth.net/bbs0an.php?path=%2Fgroups%2Fcomp.faq%2FLinuxDev%2Fdevelop%2Fgdb_linuxdev
GNU make指南
http://www.newsmth.net/bbs0an.php?path=%2Fgroups%2Fcomp.faq%2FLinuxDev%2Fdevelop%2Fmakefile
使用automake和autoconf管理项目的上手指南
http://blog.donews.com/idlecat511/archive/2006/01/17/698470.aspx
http://cvs.so.sohu.com:2080/svn/arch/trunk/Projects/MakefileDemo/
文档工具
Doxygen
Doxygen是开源(GPL)的文档工具,可以自动根据类之间的调用关系生成UML图,也支持类似javadoc的从注释中提取文档的功能。
Doxygen可以直接生成html, LaTeX, rtf等格式的文档。
Doxygen的项目主页在http://www.doxygen.org/。生成图片需要Graphviz(http://www.graphviz.org/)程序的支持。
程序中的注释块
Doxygen支持的注释格式如下:
l /*或者/!开头:
/**
* @brief put result back to output module
*
* @param seq the seq of the request
* @param result the result
*
* @return 0 on successful, otherwise an error number
*/
virtual int put_result(const seq_t& seq, const result_t& result) = 0;
l ///或者//!开头:
/// the superclass for output module
class Base_Output {
l 还可以用增加一个<来为注释前面的代码写文档(默认为注释后面的),这种情况在定义enum的时候很有用:
/**
* @brief enumerate for supported products
*/
关于更多的程序中的注释块的说明可以参考官方文档
常用命令
命令以@或者\开头,用来指定后面文字的形势,比如@brief, \return等。
常用命令如下:
l brief: 简短说明
l details: 详细说明
l param: 参数说明,后面跟的第一个单词为参数名
l return: 返回值说明
l class: 类名,可以省略
l file: 文件名,可以省略
l author: 作者
完整的命令列表请见官方文档(http://www.stack.nl/~dimitri/doxygen/commands.html)
配置文件
与make类似,doxygen的默认配置文件为当前目录下的Doxyfile文件,http://www.sohu-rd.com/images/f/fe/Doxyfile.doc是一个example,注意要去掉.doc扩展名
在这个例子里面,一般来说你需要更改的东西有:
l PROJECT_NAME: 项目的名字
l PROJECT_NUMBER: 项目的版本号
l TAB_SIZE: 制表符的宽度
l INPUT: 源代码的路径
l HTML_OUTPUT: 输出的html文档的路径
l LATEX_OUTPUT: 输出的LaTeX文档的路径
l RTF_OUTPUT: 输出的rtf文档的路径
准备好配置文件后,在配置文件(Doxyfile)所在目录执行doxygen就可以生成文档。按照这个例子,doxygen会对Code子目录下面的所有代码生成文档,其中html文档生成到html子目录下,LaTeX文档生成到latex子目录下,rtf文档生成到rtf子目录下。
其它
l 如果使用vim作为编辑器,可以安装DoxygenToolkit这个插件,这个可以对你已经写好的函数头、类头等自动生成doxygen注释框架。
l 一个doxygen注释的源代码的例子在http://www.sohu-rd.com/images/7/7e/Core_Manager.h.doc,注意要去掉.doc扩展名
版本管理工具
SVN
SVN是CVS的进化版本,最主要的区别是SVN为整个Repository维护一个统一的版本号以避免混乱。建议在Windows下用TortotiseSVN。
svn中的trunk目录对应CVS的HEAD/MAIN分支,SVN中没有传统CVS的branch/tag,而是通过在branches/tags目录下建立原始文件的拷贝来模拟:
cvs tag branch_name : svn copy . branch_path
cvs up -r tag_name : svn switch tag_path
WorkCopy的概念和CVS类似,注意,一般不checkout整个respository,而是check out trunk或某个分支
svn命令行简明参考手册
l Prestart
l 创建仓库(Repository)
svnadmin create /path/to/repository
svnadmin是有用的subversion系统管理命令,使用svnadmin help查看在线帮助
信息。subversion的手册推荐在项目在repository下分别建立branches/ tags/trunk/三个目录,分别存放分支/标签/主分支
l 检出(checkout)项目
svn checkout file:///.../trunk/ project
svn checkout http://host/.../trunk/ project
l 列出仓库中的项目(list)
svn list -verbose file:///.../tags/
svn list -verbose http://.../trunk/
l 状态查询(status)
svn status
给出新文件,已经改变的文件和被删除的文件列表
l 添加文件或目录(add)
svn add
l 删除文件或目录(delete)
svn delete
svn delete http://host/svn_dir/repository/project_dir 这条命令可以用来删除错误的import的某些项目!!
l 回滚workcopy的修改
svn revert file1 file2
svn revert -R .
l 提交(commit)
svn commit http://host/svn_dir/repository/project_dir
l 更新(update)
svn update
更新仓库中的文件到本地。
l 删除重命名和移动(update)
svn delete (del, remove, rm)
svn move (mv, rename, ren)
l 使用COPY命令管理Tag和 Branch
svn copy http://host/repos/project/trunk http://host/repos/project/tags/1.0.0
用于创建某个特定版本的快照(snapshot);
svn list http://host/repos/project/tags/1.0.0
查看某个版本的内容
svn switch branch_url
把workcopy切换到某个分支
l 版本合并
svn merge -r N:M branch .
把branch上版本N和M之间的修改合并到当前目录
branch可以是url或者本地目录
svn merge tag branch .
把tag和branch之间的修改合并到当前目录
svn log -qv --stop-on-copy http://svnhost/svn/repo/branches/br1
查看某个branch的修改日志从而决定从哪个版本开始merge
l 快速查看当前workcopy的版本号(svnversion)
svnversion
给出新文件,已经改变的文件和被删除的文件列表;
参考
CVS中文手册
http://man.chinaunix.net/develop/cvsdoc_zh/
使用Subversion进行版本控制
http://svnbook.red-bean.com/index.zh.html
涉及的内容:
1) 连接服务器;
2) Shell常用命令与常用参数;
3) VIM 的使用;
4) Linux更新软件;
5) GCC的常见参数;
6) GDB调试程序;
7) Makfefile的编写;
8) 代码注释,文档管理:开源Doxygen;
9) 版本控制:SVN常用命令;
连接到Linux服务器
用SecureCRT 连接Linux服务器。安装完成后从File菜单选择Quick Connect即可。使用SSH1协议,在连接时注意。
为了方便起见,建议在安装完成后作如下设置:
Options -> Global Options -> Default Session -> Edit Default Settings
Connection -> Protocol SSH1
Terminal -> Emulation-> Terminal Xterm
Terminal -> Emulation-> ANSI Color On
Terminal -> Appearance-> Current Color Schema Traditional
建议在Windows上安装虚拟机学习;
如何使用Shell
刚登录到Linux时,会显示Bash Shell提示符如下。现在你可以使用Shell命令来指挥Linux。
l ===常识===
linux用"/"而非"\"来分隔目录,/dir/.表示/dir这个目录,而/dir1/dir2/..表示/dir1这个目录。
shell总是有一个当前目录,文件的相对路径(不以"/"开头的路径)从当前目录开始计算
cat sort等处理文件内容的命令,在没有文件名时处理标准输入(键盘输入)
*和?是文件名通配符,*代表示任意数量字符,?代表单个字符。通配符由shell而非命令自身解释,因此ren *.bak *.sav这样的dos操作是不可能的。
l ===目录相关===
pwd 显示当前目录,
cd /dir1/dir2 修改当前目录为/dir1/dir2
mkdir newdir 在当前目录下建立新目录newdir
rmdir olddir 在当前目录下删除旧目录olddir
ls -l 列出当前目录下所有文件
ls -la 列出包括以"."开头的隐含文件
l ===解决乱码或者其他中文字符集问题===
export LC_ALL=
export LC_CTYPE=zh_CN.gbk
l ===文件操作===
rm foo bar etc 删除文件foo bar etc
mv foo bar 文件改名foo1改成bar
mv src1 src2 … dst 把文件移动到dst目录
cp src dst 把文件src拷贝为dst
cp src1 src2 … dst 把文件拷贝到dst目录
scp … root@host:path 把文件拷贝到主机host的目录path下
scp root@host:path dst . 把文件从主机host的目录path下拷贝到当前目录
ln -s old new 为文件old建一个符号连接new
l ===文件内容操作===
cat foo 显示文件foo的内容
head -n100 foo 查看文件foo的前100行
tail -n100 foo 查看文件foo的尾100行
diff -u foo bar 对比文件foo和bar
sort foo 按字母排序文件foo
sort -n foo 按数字排序文件foo
sort foo | uniq -c 统计文件foo中每行出现了多少次
fgrep xxx files 在文件中检索字符串xxx
l ===查看帮助===
man bash 查看bash shell的内部命令,按q退出
info coreutils 查看最常用的那些命令,按q退出
man ls 查看命令ls的帮助
man -a printf 查看printf的所有帮助,按q切换到下一个帮助。像printf这样同时出现在shell/c/perl等多个环境中的命令会有多个帮助。
man -K printf 在所有的帮助文件中搜索printf
l ===简单管理===
ps aux 列出当前所有的进程,注意PID和COMMAND两列
top 实时显示当前系统负载和最活跃的进程。
按1显示多cpu详情,按shift-m显示内存最多的进程
kill 1234 杀死PID为1234的进程
kill -9 1234 强行杀死PID为1234的进程(如果kill不行的话)
netstat --anp 列出当前所有的tcp/udp连接以及相关的进程
l ===打包===
一般用tar打包,包有.tar.gz(.tgz)以及.tar.bz2两种格式
tar cvzf a.tar.gz foo 把foo下的所有文件打包成a.tar.gz
tar xvzf a.tar.gz 把a.tar.gz解包到当前目录
tar xvjf a.tar.bz2 把a.tar.bz2解包到当前目录
如何使用VIM编辑文件
首先,正确的设置vim环境会使用更加舒服,执行以下命令设置环境:
echo -e "set nocp\nsyntax on\nset ts=4\nset sw=4\nset si\n" >> ~/.vimrc
vim foo 启动vim,并编辑文件foo
vim和Windwos的编辑器不一样,它有2种模式:命令模式和编辑模式。刚启动vim时处于命令模式,此时可以移动光标和发布命令。常用命令:
i r <insert> 进入编辑模式
<esc> 离开编辑模式
:q :q! 退出/强制退出
:w :w! 存盘/强制存盘
:wq :wq! 存盘退出/强制存盘退出
? / 向前/向后查找文本
gg G 移动到文件头/文件尾
dd 删除当前行
v V 开始选择文本/开始按行选择文本
y 将v/V选中的文本放入剪贴板
p 粘贴剪贴版的内容
J 将下一行拼到当前行尾
:%s/old/new/g 全文替换old为new
<ctrl-]> 如果有make tags的话,查找当前标识符的定义
:make 在当前目录执行make,并移动到第一个编译错误
Shell进阶
===egrep 正则表达式检索===
egrep pattern files 在文件中检索pattern,显示匹配的行
pattern 由若干atom组成,atom定义如下
. 匹配任意字符
[abc] 匹配abc三个字母任何一个
[^abc] 匹配除abc三个字母以外的任何字符
[a-h] 匹配abcdefgh中的任何一个
<atom>? ?前一个atom匹配0~1次
<atom>+ +前一个atom匹配至少1次
<atom>* *前一个atom匹配任意次
<atom1>|<atom2> 匹配两个atom中的任何一个
(<atom1><atom2>…) 用"("和")"把多个atom编成一组
\ 转义符,例如"\."精确匹配".","\t"匹配tab字符
^ 表示一行的开始
$ 表示一行的结束
其他普通字符都是atom
例子:
([a-z]\.)[a-z]+ 匹配任何纯由小写字母组成的域名
egrep常用参数
-o 显示匹配上pattern的串
-v 显示没有匹配pattern的那些行
-n 显示行号 ===输入输出重定向和管道===
一般情况下程序从键盘读取用户输入,输出到显示器。我们可以通过"<" ">" "|"操作符来改变这种行为。
ls > file 把ls的结果存到文件file,file原有的内容被销毁i
ls >> file 把ls的结果存到文件file原有内容的尾部
ls -xxx &> file 把ls的错误信息和正常输出都存到文件file
foo < file 用文件file作为命令foo的输入
ls | sort 把ls的结果做为sort的输入
ls 2>&1 | sort 把ls的结果和出错信息一起做为sort的输入
ls | tee file 利用tee命令把ls的结果存到文件file并同时显示在荧幕上。 ===后台任务===
在程序运行的过程中,按ctrl-z可以把程序切换到后台挂起,此时程序暂停执行。
启动程序的时候,在命令行的最后加"&",可以让程序直接在后台执行
grep xxx file > yyy & 在后台执行grep命令
jobs 显示当前后台有哪些程序
fg 9 把第9号后台程序切换到前台
bg 9 让第9号后台程序恢复执行(用于ctrl-z挂起的程序)
Windows和Linux互传文件
如果你使用SecureCRT,那么可以用rz命令传送文件到linux,用sz命令传送文件到Windows,但是这两个命令在处理大文件时往往有问题。
你可以安装winscp来传送文件
用yum或者apt-get补充安装rpm软件包
rpm是linux下常用的软件包封装格式。
rpm -ivh xxx.rpm 安装xxx.rpm
rpm -qa 显示系统上已经安装了哪些rpm
rpm -ql xxx 显示xxx包括哪些文件,xxx需要已经安装
rpm -e xxx 删除xxx
rpm -qf /bin/ls 查找/bin/ls属于哪个rpm包
rpm比自己下载源码要方便,但是去哪里下载rpm仍然是个问题。Linux发行版一般都附带了大量的rpm,但是并没有默认全部安装。Redhat提供了yum工具用于安装和管理系统附带的rpm软件包。使用软件和编译程序时如果发现缺少对应的工具或者库文件可以用yum补充安装。
yum search xxx 搜索名字和描述中带有xxx的软件包。
yum install xxx 安装xxx以及xxx依赖的rpm到最新版本。
例如,我们编译时发现找不到zlib相关的头文件。首先用”yum search zlib”发现有一个包叫做zlib-devel.i386,然后用”yum install zlib-devel”安装它即可。
某些系统用的是apt-get来管理rpm
apt-cache search xxx 搜索xxx
apt-get install xxx 安装xxx
参考
Bash新手指南
http://xiaowang.net/bgb-cn/
Shell设计入门
http://www.newsmth.net/bbscon.php?bid=392&id=320837
C/C++的开发 GCC/GDB/Make
在Linux下,我们用gcc来编译C/C++程序,用GDB调试程序,并用make工具来把多个源文件组织成project。如果缺乏耐心的话,请直接跳到本章的最后快速指南[Makefile模板[14页]]学习如何快速开始一个项目。
gcc
gcc – the GNU Compiler Collection。 能编译C,C++和一些其它语言编写的程序。
gcc特性
和其它编译器一样,gcc的编译过程可分为4个阶段:预处理,汇编,编译和链接。gcc的使用者可以在任何阶段停止整个编译过程,并得到该阶段的输出信息。
gcc也有优化代码和生成调试信息的功能,一般我们编译代码的时候,都会加入调试信息,这样代码出现问题的时候容易追查。但编译器优化过的代码往往不方便调试,因此,代码优化只有在正式上线的时候才会被使用。
此外gcc支持30多个警告和3个警告级别,支持交叉编译(生成非本机体系结构的二进制代码),还对标准C和C++进行了大量扩展,以提高执行效率和编程的方便性。但我们不建议使用这些扩展,因为这会影响代码的可移植性。
gcc使用
编译文件hello.c的基本方式是:
gcc hello.c --o hello
其中hello.c是输入文件,-o选项的内容为输出文件。该命令编译并链接hello.c,生成文件为hello可执行文件。如果不加-o参数,则为gcc最简单的用法:
gcc hello.c
此时gcc生成文件名为a.out的可执行文件。
编译多个源文件(如hello.c和world.c):
gcc hello.c world.c --o helloworld
实际使用中,建议先把多个源文件编译成为目标文件,再进行链接生成可执行文件:
gcc --c hello.c
gcc world.c -c
gcc hello.o world.o --o helloworld
上例中的-c选项表示只对源文件做编译处理,生成目标文件,没有加-o参数,此时编译器生成与源文件同名的.o目标文件(为别为hello.o和world.o),第三个命令把各个.o文件链接成可执行文件。
注意各参数和输入文件在命令中顺序可任意。例如第三句可以写成(不推荐)
gcc hello.o --o helloworld world.o
只对源文件进行预处理(包括头文件展开,宏展开等),可用-E参数。例如:
gcc --E --o hello.cpp hello.c
先成的文件名为hello.cpp。在unix系统下,.cpp文件表示预处理过的C/C+文件。而对于C+源文件,一般使用.cc或.cxx的扩展名。
很多时候我们还需要观察gcc产生的汇编代码,可用-S参数:
gcc --S hello.c
此时gcc生成文件名为hello.s的汇编语言文件。
调试与优化
优化的目的是改进程序的执行效率,代价是延长编译时间,也可能会增加产生的二进制文件的大小,增大调试难度。
优化参数包括-O0,-O1(等同于-O),-O2和-O3,优化程度递增。如果不加优化参数,则相当于--O0,不优化。在O0下内联函数不会被展开。一般在编译Linux内核的时候使用参数-O2,因为O3参数会展开一些非内联函数,增加二进制代码量,这对Linux内核是不能接受的。对于一般的应用,使用O3优化也是安全的。
优化参数只需在编译的时候指定,链接时不需要,例如:
gcc hello.c --c --O2
gcc --o hello hello
编译优化在理论上不会影响程序的逻辑,如果出现优化后代码运行异常,则很可能是源程序本身有bug。
gcc可通过-g参数在生成的代码里加入调试信息,以方便调试时的会话过程。和优化参数一样,-g也只需在编译的时候指定:
gcc --g --c hello.c
gcc --o hello hello.o
Unix下常用的调试工具gdb(GNU Debugger)将在下一部分介绍。用户还可通过-ggdb参数来加入更多的只能被gdb识别的调试信息。
注意,尽量避免-g和-Ox一起使用。编译优化会改变代码执行顺序被打乱以加快运行速度,但调试会变得很困难。
其它常用参数
-I::指定一个头文件路径。可用多个-I参数指定多个头文件路径。只在编译时有效。
-L::指定一个库文件路径。和-I一样可指定多个。只在链接时有效,经常和-l一起使用。
-l:指定一个库文件名。Linux下库文件的文件都是libXXX.so或libXXX.a的形式,分别是动态链接库和静态链接库。例如数学函数库文件为libm.so和libm.a,SSL的函文件为libssl.so和libssl.a。gcc在链接时-l参数只需指定库文件名的中缀部分。例如hello.c中调用了数学库的cos()函数,则:
gcc --g --c hello.c
gcc --o hello hello.o --lm
-Wall:实际上是-W参数加”all”。可让gcc打开所有的警告。在调试代码时建议使用。
-static:所有引用的库都静态链接。将会增加可执行文件的大小。
gdb
gdb介绍
gdb – the GNU Debugger。Linux下用得最多的命令行调试器。使用gdb对程序进行调试的前提是可执行文件有调试符号,在编译时需使用-g或-ggdb参数(见上一节),同时不打开编译优化。
gdb基础
启动gdb有三种常用的方法(直接启动,调试core文件和调试运行中的进程)。直接启动gdb的方法如下。
gdb test
此时会启动对程序test的调试,进入gdb交互界面。
在gdb中输入run(或r)命令表示运行程序,如果程序需要参数(main的参数),在run之后加入参数即可,例如:
(gdb) run arg1 arg2
run命令将运行到程序正常退出,或遇到断点,或被用户Ctrl-C,或出现异常,例如段错误(内存访问超出进程的地址空间),除0,总线错误,以及其它一些使程序无法运行下错误。当程序中断时(断点或Ctrl-C或异常),gdb会显示中断的代码位置。可用list(或l)命令来查看中断位置前后(共10行)代码。list命令每运行一次,查看10行代码,同时查看点也向后推进10行。list命令也可指定要查看的源文件名和位置,例如:
(gdb) list test.c:100
或当前文件就是test.c的话,等价于:
(gdb) list 100
此时gdb显示test.c的第95行到104行的代码。如果再敲入一次list,则显示从105行到114行。
程序中断是可用print(或p)命令来查看各变量的值。print命令支持所有C语言的语法。例如查看结构体指针a的域x:
(gdb) print a->x
通过where(或bt)命令可查看程序的中断位置,此会gdb会显示当前的函数调用层次。通过up命令可退回到上一级函数,以查看上一级函数中的变量情况。与up相对应的命令是down。
断点的使用
调试出问题的代码的时候,在某一点停止执行往往很管用。gdb支持几种不同的设置断点的方式,包括行号和函数名。还允许设置条件断点,即只有满足一定条件,代码才会在断点处停止执行。设置断点的命令为break(或b),例如:
(gdb) break test.c:100
(gdb) break 100
(gdb) break func1
(gdb) break 100 if (a->x==5)
其中,条件断点语句的条件部分支持C语言的所有语法。当程序在某个断点中断时,则可用上面说到的print命令来查看各变量的值,up,down命令来查看程序各级函数中的状态。注意up,down命令只会影响查看点,并不会改变程序当前执行到的位置。
让程序在断点中断之后继续运行,包括几个常用的命令。
continue(或c)命令让程序继续运行,直到遇到下一个断点;
next(或n)命令让程序执行下一条语句,如果下一条语句是函数,不进入函数内部;s
tep(或s)命令执行一下条语句,遇到函数则进入函数内部。
finish(或fin,maybe)可让程序继续运行,直到当前函数返回;
return(或ret?)命令让函数立即返回,返回后程序仍处于中断状态。return命令可加返回值,例如:
(gdb) return 20
即让当前函数立即返回,返回值为20。注意的时让函数从一个非正常的点返回,后果可能很严重,但在调试中有时也很有用。在程序中断时还可以通过call命令来调用函数,例如:
(gdb) call a=func(20)
此时gdb调用了func函数并把返回值赋予变量a。如果func函数中也有断点,程序也会在断点处被中断。
如果要删除某个断点,首先找到要删除断点的id号,方法是:
(gdb) info break
此时gdb会显示当然的所有断点位置和对应的id。用delete(或del?)命令加id号删除对应的断点;delete不加参数则删除所有的断点。另外,用disable和enable命令可让断点临时关闭和重新打开。
调试core和调试进程
对于运行中的进程,如果出现一些异常无法继续运行,会在程序的运行目录下留下一个core文件,就是我们常说的“程序core了”。core的原因是程序/进程收到了某些会让程序core的信号(准确的说是让程序流产的信号),常见的有SIGSEGV(程序出现段错误,越界访问,最常见),SIGABRT(如程序调用了abort()函数,abort本身就是流产的意思),SIGFPE(浮点异常)。当程序core了之后,会在运行目录留下一个core文件,文件名为core.XXXX,XXXX为进程号pid。如果发现怎么程序异常退出却没有core文件,系统设置的问题。用以下命令允许产生无限大的core文件:
ulimit --c unlimited
假设我们的程序名为test,产生了文件名为core.1234的core文件,通过以下命令启动gdb来调试core:
gdb test core.1234
进入gdb之后,会显示出程序异常的位置。再通过上面介绍的gdb命令查看异常时程序的状态,就可以比较方便的找到程序bug所在。注意程序core了之后已经不在运行状态,因此和运行相关的命令,如run,continue,next, step,finish,return,call,在调度core的时候无法使用。break也是没有意义的。
gdb还可以调试一个正在运行中的进程,方法是:
gdb --p <进程号>
进入gdb之后进程被gdb中断,gdb显示中断位置。此时调试的方法与普通启动gdb方式几乎无异,也可以使用运行相关命令来控制进程的推进。唯一的区别是,使用exit(或Ctrl-D)命令退出后,被调试的进程会继续运行,而不是结束。
其它常用命令
kill – 杀死当前的调试进程,对于core调试无效,因为core已经是死掉的进程。
info thread – 显示所有线程和id号。
thread <id> – 切换到某个线程。
set variable <variable name>=<expression> – 改变变量的值,对core调试无效,支持C语法。例如:
(gdb) set variable i=x+5
ptype <variable> – 显示变量的数据类型。
shell [cmd] – 执行一个shell命令。如果[cmd]为空,则进入shell。在shell中exit或Ctrl-D返回gdb。
help – 当你需要其它帮助。
Makefile
Makefile的原始形式
Make是linux最基本的工程描述工具。编写Makefile以后,简单的键入make all就能方便的编译整个项目而不用一次次手工调用gcc。先来看一下一个最基本的Makefile,它描述了如何从s1.cpp s2.cpp编译产生程序test:
objects=s1.o s2.o ##变量定义
all: test ##一般用all表示生成所有目标
test: $(objects) ##普通依赖关系
g++ $+ -o $@ ##从s1.o s2.o如何生成test
%.o:%.cpp ##从.cpp文件编译.o的依赖模板
g++ -g -O2 -c $< ##具体如何编译
clean: ##一般用clean表示清除所有目标和中间文件
rm -f test *.o ##
[kirbyzhou@sohu]$ make ##编译test
g++ -g -O2 -c s1.cpp
g++ -g -O2 -c s2.cpp
g++ s1.o s2.o -o test
[kirbyzhou@sohu]$ make ##再次编译,因为文件没有变化,所以什么都没发生
make: Nothing to be done for `all'.
[kirbyzhou@sohu]$ make clean ##清理
rm -f test *.o
Makefile的文件名必须是严格的”Makefile”,make会在当前目录下查找Makefile文件。Makefile主要由3部分组成:1.变量定义;2普通依赖关系(explicit rule);3.模板依赖关系(implicit rule)。格式分别如下:
TARGET : PREREQUISITES ##TARGETS直接依赖于PREREQUISITES
<TAB>COMMAND ##从PREREQUISITES如何产生TARGET
%.DST : %.SRC ##.dst文件依赖于.src文件,例如.o和.cpp的关系
<TAB>COMMAND ##从PREREQUISITES如何产生TARGET
在COMMAND中可以用$+表示PREREQUISITES,用$@表示TARGET,用$<表示第一个PREREQUISIT。例子参见上文。
用Automake/Autoconf自动生成makefile
涉及的文件增多以后,Makefile变得很难维护。首先是依赖关系的复杂性:s1.o不仅仅是依赖于s1.cpp,它可能还依赖于s1.h s2.h s3.h等等;其次如何生成库、动态库等等都比较复杂;各人的Makefile风格迥异很难修改;最后是缺乏统一的子目录管理机制。总之靠人工来维护Makefile是非常辛苦的。为此人们发明了一系列工具用于简化Makefile的编写,并统一Makefile的风格。
automake/autoconf是一套比较成熟的工具,它主要涉及到1个configure.ac和若干个Makefile.am
l Makefile.am一般每个子目录一个,一个最简单的Makefile.am如下,已经可以满足绝大部分的需求:
bin_PROGRAMS=demo1 demo2 ##我要编译demo1 demo2这两个程序
lib_LTLIBRARIES=libdemo3.la ##我要编译libdemo3.la这个库
demo1_SOURCES=demo1.cpp func.cpp f.h ##demo1的源码
demo2_SOURCES=demo2.cpp func.cpp f.h ##demo2的源码
libdemo3_la_SOURCES=demo3.cpp demo3.h ##libdemo3.la的源码
SUBDIRS=sub1 sub2 ##如果有子目录要build的话,列在这里
Makefile.am首先定义需要build哪些target,语法如下:
[bin|lib|libexec|…|noinst]_[SCRIPTS/PROGRAMS|LIBRARIES|LTLIBRARIES]=target1 target2 …
其中””前说明target会被安装到$(prefix)下的哪个目录,noinst表示不安装;””后是target的类型------脚本/可执行程序/静态库/动态库。注意静态库和动态库分别要满足lib*.a lib*.la的命名。
然后是每个target相关的源码,automake会自己处理源码间的关系:
<target>_SOURCES=src1.c src2.cpp header1.h header2.hpp
这里如果target是X.Y这样的形式,要写成X_Y_SOURCES=…的形式
l 在项目的topdir里还需要一个configure.ac,描述一些全项目的信息
AC_PREREQ(2.57) ##样板戏,不用管它,下同
AC_INIT(demopkg, 0.5.1) ##整套程序的名字、版本号
AM_INIT_AUTOMAKE([foreign]) ##样板戏,让autoconf按最糙的要求审核我们的程序
AC_PROG_CC ##样板戏,检查C编译器
AC_PROG_CXX ##样板戏,检查C++编译器
AC_PROG_LIBTOOL ##样板戏,检查用于生成动态库的libtool工具
AC_CONFIG_FILES([
Makefile demo/Makefile ##在[]里列出需要自动生成的Makefile
])
AC_OUTPUT ##最后一行样板戏
l 最后执行autoreconf --is && ./configure就可以开始make了。
l 常用的make目标有all(缺省target,build项目),clean(清理),install(安装),uninstall(反安装),check(测试),dist(源码打包),distcheck(检查打包后的源码能否正常工作)。
快速指南:
=== 编写Makefile ===
编写Makefile 参见[Makefile模板[14页]]
make 用makefile编译整个工程
make clean 清除make的结果和中间文件
=== GCC ===
gcc a.c 编译纯C程序a.c为可执行程序a.out
g++ -g s1.cc s2.cpp -o dest 把源文件s1.cc s2.cpp编译成可执行程序dest
g++ -g -O0 src.cpp -o dest 禁止优化的编译,这样方便调试
g++ -I/opt/include … 附加的include目录
g++ -L/opt/lib -lACE … 附加的lib目录,并链接库libACE.so
==== GDB ===
gdb test 调试程序test
gdb test 12345 调试进程PID为12345的程序test
gdb test core.123 调试程序test崩溃后留下的现场core.123
ulimit --c unlimited 使程序崩溃后有机会留下现场
==== GDB 命令===
r arg1 arg2 … 运行程序,arg1 arg2 …是传给程序的参数
l 列出代码
l a.cpp:100 列出a.cpp第一百行附近的代码
b 100 在第100行设置断点
<ctrl-c> 中断程序
p x 打印变量x的值
set variable x = y +2 改变变量的值
n / s / c 单步/深入单步/继续
bt 察看函数调用层次
up / down 转到上一级/下一级函数
kill 杀死当前的调试进程
info thread 显示所有线程和id号
thread 3 切换到线程3
参考
GCC常见编译选项
http://dev.csdn.net/author/ganxingming/d4fabf69cc48471fbcbc7b9be2a908dc.html
GDB手册 http://www.newsmth.net/bbs0an.php?path=%2Fgroups%2Fcomp.faq%2FLinuxDev%2Fdevelop%2Fgdb_linuxdev
GNU make指南
http://www.newsmth.net/bbs0an.php?path=%2Fgroups%2Fcomp.faq%2FLinuxDev%2Fdevelop%2Fmakefile
使用automake和autoconf管理项目的上手指南
http://blog.donews.com/idlecat511/archive/2006/01/17/698470.aspx
http://cvs.so.sohu.com:2080/svn/arch/trunk/Projects/MakefileDemo/
文档工具
Doxygen
Doxygen是开源(GPL)的文档工具,可以自动根据类之间的调用关系生成UML图,也支持类似javadoc的从注释中提取文档的功能。
Doxygen可以直接生成html, LaTeX, rtf等格式的文档。
Doxygen的项目主页在http://www.doxygen.org/。生成图片需要Graphviz(http://www.graphviz.org/)程序的支持。
程序中的注释块
Doxygen支持的注释格式如下:
l /*或者/!开头:
/**
* @brief put result back to output module
*
* @param seq the seq of the request
* @param result the result
*
* @return 0 on successful, otherwise an error number
*/
virtual int put_result(const seq_t& seq, const result_t& result) = 0;
l ///或者//!开头:
/// the superclass for output module
class Base_Output {
l 还可以用增加一个<来为注释前面的代码写文档(默认为注释后面的),这种情况在定义enum的时候很有用:
/**
* @brief enumerate for supported products
*/
关于更多的程序中的注释块的说明可以参考官方文档
常用命令
命令以@或者\开头,用来指定后面文字的形势,比如@brief, \return等。
常用命令如下:
l brief: 简短说明
l details: 详细说明
l param: 参数说明,后面跟的第一个单词为参数名
l return: 返回值说明
l class: 类名,可以省略
l file: 文件名,可以省略
l author: 作者
完整的命令列表请见官方文档(http://www.stack.nl/~dimitri/doxygen/commands.html)
配置文件
与make类似,doxygen的默认配置文件为当前目录下的Doxyfile文件,http://www.sohu-rd.com/images/f/fe/Doxyfile.doc是一个example,注意要去掉.doc扩展名
在这个例子里面,一般来说你需要更改的东西有:
l PROJECT_NAME: 项目的名字
l PROJECT_NUMBER: 项目的版本号
l TAB_SIZE: 制表符的宽度
l INPUT: 源代码的路径
l HTML_OUTPUT: 输出的html文档的路径
l LATEX_OUTPUT: 输出的LaTeX文档的路径
l RTF_OUTPUT: 输出的rtf文档的路径
准备好配置文件后,在配置文件(Doxyfile)所在目录执行doxygen就可以生成文档。按照这个例子,doxygen会对Code子目录下面的所有代码生成文档,其中html文档生成到html子目录下,LaTeX文档生成到latex子目录下,rtf文档生成到rtf子目录下。
其它
l 如果使用vim作为编辑器,可以安装DoxygenToolkit这个插件,这个可以对你已经写好的函数头、类头等自动生成doxygen注释框架。
l 一个doxygen注释的源代码的例子在http://www.sohu-rd.com/images/7/7e/Core_Manager.h.doc,注意要去掉.doc扩展名
版本管理工具
SVN
SVN是CVS的进化版本,最主要的区别是SVN为整个Repository维护一个统一的版本号以避免混乱。建议在Windows下用TortotiseSVN。
svn中的trunk目录对应CVS的HEAD/MAIN分支,SVN中没有传统CVS的branch/tag,而是通过在branches/tags目录下建立原始文件的拷贝来模拟:
cvs tag branch_name : svn copy . branch_path
cvs up -r tag_name : svn switch tag_path
WorkCopy的概念和CVS类似,注意,一般不checkout整个respository,而是check out trunk或某个分支
svn命令行简明参考手册
l Prestart
l 创建仓库(Repository)
svnadmin create /path/to/repository
svnadmin是有用的subversion系统管理命令,使用svnadmin help查看在线帮助
信息。subversion的手册推荐在项目在repository下分别建立branches/ tags/trunk/三个目录,分别存放分支/标签/主分支
l 检出(checkout)项目
svn checkout file:///.../trunk/ project
svn checkout http://host/.../trunk/ project
l 列出仓库中的项目(list)
svn list -verbose file:///.../tags/
svn list -verbose http://.../trunk/
l 状态查询(status)
svn status
给出新文件,已经改变的文件和被删除的文件列表
l 添加文件或目录(add)
svn add
l 删除文件或目录(delete)
svn delete
svn delete http://host/svn_dir/repository/project_dir 这条命令可以用来删除错误的import的某些项目!!
l 回滚workcopy的修改
svn revert file1 file2
svn revert -R .
l 提交(commit)
svn commit http://host/svn_dir/repository/project_dir
l 更新(update)
svn update
更新仓库中的文件到本地。
l 删除重命名和移动(update)
svn delete (del, remove, rm)
svn move (mv, rename, ren)
l 使用COPY命令管理Tag和 Branch
svn copy http://host/repos/project/trunk http://host/repos/project/tags/1.0.0
用于创建某个特定版本的快照(snapshot);
svn list http://host/repos/project/tags/1.0.0
查看某个版本的内容
svn switch branch_url
把workcopy切换到某个分支
l 版本合并
svn merge -r N:M branch .
把branch上版本N和M之间的修改合并到当前目录
branch可以是url或者本地目录
svn merge tag branch .
把tag和branch之间的修改合并到当前目录
svn log -qv --stop-on-copy http://svnhost/svn/repo/branches/br1
查看某个branch的修改日志从而决定从哪个版本开始merge
l 快速查看当前workcopy的版本号(svnversion)
svnversion
给出新文件,已经改变的文件和被删除的文件列表;
参考
CVS中文手册
http://man.chinaunix.net/develop/cvsdoc_zh/
使用Subversion进行版本控制
http://svnbook.red-bean.com/index.zh.html
相关推荐
内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
深圳建设施工项目安全生产奖惩管理制度
离散数学课后题答案+sdut往年试卷+复习提纲资料
04741计算机网络原理 2018(尚德).pdf 13年试题(2套).pdf 2015年10月自考计算机网络原理04741试题及答案解析.docx 2021年4月自考04741计算机网络原理真题及答案.docx 2021年4月自考04741计算机网络原理试卷.bak.docx 计算机网络原理 课后题答案 全 李全龙版 自考04741.zip.zip 计算机网络原理课件 计算机网络原理课件.rar
C++实现rpc,全程手写
前端拿到的列表数据里id都一样的处理办法.txt
最新仿720云全景制作源码|krpano仿720云全景网站源码(新增微信支付+打赏+场景红包等)是一款基于php+mysql开发制作的全景在线制作网站源码,包含全景图片,全景视频等。数据存储全部存于OSS云端或本地,源码完全开源可自行二次开发。 环境要求:PHP5.5.X+MYSQL5.6.X+伪静态 熟悉linux系统推荐使用LAMP,web服务器最好使用apache,不要使用nginx(发布大全景图需要时间可能需要20多分钟, nginx超时机制不好控制)。 Windows系统推荐使用phpstudy。Liunx推荐宝塔控制面板apache 前端为HTML5开发,自适应手机版! 1、支持VR虚拟现实、全景视频、环物全景、说一说、点赞评论、重力感应、智能视频嵌入、场景切换热点、加载进度条、 地图导航、光晕flash特效、物体全景嵌入、场景自播、场景解说、雷达导航等业内前沿功能。 2、支持windows、Linux、Mac、安卓、IOS等几乎所有的系统观看。支持CDN图片转存,极大的减轻的服务器流量费用。 3、支持用户权限分配。方便会员制收费。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
环境监测系统源代码全套技术资料.zip
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
四轮转向系统横摆角速度控制simulink仿真模型,利用滑模控制算法,基于八自由度车辆模型,控制有比较好的效果,附参考说明。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
02142数据结构导论历年真题及答案(2012-2018共13套).rar 02331数据结构历年真题共267页2009.10-2019.4.rar 24数据结构201704_8.pdf 25数据结构201710_10.pdf 26数据结构201804_11.pdf 27数据结构201810_9.pdf 全国2021年04月高等教育自学考试02331数据结构试题及答案.docx 全国2022年04月高等教育自学考试02331数据结构试题及答案.docx 数据结构-课件.rar 第l六讲.ppt 第一讲.ppt 第七讲.ppt 第三讲.ppt 第九讲.ppt 第二讲.ppt 第五讲.ppt 第八讲.ppt 第四讲.ppt
验收确认单表格.docx
内存搜索工具(易).rar
饮食管理系统项目源代码全套技术资料.zip
【项目简介】 代码主干网络采用Swin-Transformer 家族系列,包括【tiny、small、base】三种模型。pretrained和freeze_layers参数为是否采用官方预训练模型和是否仅训练分类头。为了做对比消融试验,优化器采用了Adam和SGD、AdamW三种。损失函数采用多类别的交叉熵、学习率优化策略采用cos余弦退火算法 【评估网络】 评估的指标采用loss和准确率(accuracy),分别会在训练集和验证集上进行评估、输出、绘制曲线图像。同时会在训练集、验证集进行一系列评估,包含混淆矩阵、recall、precision、F1 score等等曲线图像,以及recall、precision、F1 score、特异度的输出信息等等。 【具体各类别的指标在json文件中查看】 【如果想要更换数据集训练,参考readme文件】 【本项目为8种番茄病害图片(约4k张数据),包含数据集和标签,可以一键运行】
windows电脑下载OpenHarmony鸿蒙命令行工具hdc_std。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
本项目可以作为小程序毕设项目,主要功能为音乐播放器,主要功能是:可以播放歌曲(采用mp3网络连接实现)、专辑封面播放时可以旋转,能够实现开始和暂停播放,可以点击下一首歌曲,主页面实现动态轮播图
考研学习分享功能的描述可以涵盖以下几个主要模块,旨在为考研学生提供一个互动、资源共享、经验交流的平台: 1. 用户注册与个人信息管理 学生可以通过邮箱或手机号注册账户,填写个人信息,如姓名、专业、目标院校等。 用户可设置学习目标和进度,方便记录自己的学习历程。 2. 学习资料共享 用户可以上传、下载考研相关学习资料,如教材、真题、笔记、复习计划等。 提供文件分类功能,按学科、院校、难度等进行整理,方便用户查找。 支持多种文件格式,如PDF、Word、Excel、图片等。 3. 复习经验分享 学生可以发布自己的复习经验文章,分享复习方法、备考心得、时间管理技巧等。 提供文章评论和互动功能,其他学生可以点赞、评论、提问,促进经验交流。 设置专栏或专题,帮助学生快速找到自己感兴趣的复习内容。 4. 考研小组与社交功能 学生可以创建或加入学习小组,组内成员可共享资料、讨论问题、互相鼓励。 提供私信、群聊功能,方便学员在小组内进行实时讨论和交流。 支持设置小组学习目标和定期检查进度,增加学习动力。 5. 在线课程与讲座 提供考研各科目(如英语、数学、政治等)的在线课程资源,用户可以报名参加。