LINUX编译与调试.ppt
第一章 LINUX下编译与调试,学习目标,gcc/g+编译命令,对于.c格式的C文件,可以采用gcc或g+编译对于.cc、.cpp格式的C+文件,应该采用g+进行编译常用的选项两种-c 表示编译源文件-o 表示输出目标文件-g 在目标文件中产生调试信息,用于gdb调试-D 编译时将宏定义传入进去-Wall 选项可以打开所有类型的语法警告,以便帮助我们确定代码是正确的,并且尽可能实现可移植性。,编译和连接的方式,1、g+-c func.cpp将编译func.cpp,并且生成同名的但扩展名为.o的二进制目标文件 func.o同样道理g+-c main.cpp将编译main.cpp,并且生成同名的但扩展名为.o的二进制目标文件 main.o2、g+-c func.cpp-o func.o功能同(1)一样,但是显式地指定了输出文件名为main.o 同样道理g+-c main.cpp o main.o编译main.cpp,并输出目标文件main.o3、(1)、(2)的基础上g+main.o func.og+-o a.out main.o func.og+-o a.out*.o都将连接目标文件main.o和func.o最后形成可执行文件a.out对于第一种,如果没有显式指定可执行文件名,g+默认为a.out,编译和连接的方式,也可以将编译和链接的过程合为一块处理:g+*.cppg+func.cpp main.cppg+-o a.out func.cpp main.cpp都将先编译指定的源文件,如果成功的话,再链接成可执行文件a.out采用第4种方式,在其中第某个源文件中必须有main函数,否则链接通不过。如果希望在编译时传入宏定义,可使用-D参数,例如g+-D _DEBUG*.cpp,什么是makefile,makefile的工作过程为:先将需要编译连接的c/c+源文件组织到文件makefile中,接着运行make程序,make程序读取当前文件夹下面的makefile文件信息,并根据makefile里面的组织信息,调用相应的gcc/g+/shell等程序,完成对源文件的批量编译和连接。要写makefile文件,首页必须清楚目标文件和依赖文件的概念。通常情况下,目标文件和依赖文件都是指实际的文件。例如,有makefile文件,内容如下:main.exe:main.o func.og+-o main.exe main.o func.omain.o:main.cppg+-c main.cppfunc.o:func.cppg+-c func.cpp,Makefile文件的依赖关系,文件第一行中的文件main.exe称为目标文件,冒号后面以空格分隔的两个文件称为main.exe的依赖文件。意思是文件main.exe的产生依赖于文件main.o和func.o同样道理:第3行的main.o为目标文件,main.cpp为main.o的依赖文件。第5行的func.o为目标文件,func.cpp为func.o的依赖文件.第2行(以tab开头)表示要产生第1行的目标文件需要执行的命令。,make程序的处理过程,make程序首先读到第1行的目标文件main.exe和它的两个依赖文件main.o和func.o;然后比较文件main.exe和main.o/func.o的产生时间,如果main.exe比main.o/func.o旧的话,则执行第2条命令,以产生目标文件main.exe。在执行第2行的命令前,它首先会查看makefile中的其他定义,看有没有以第1行main.o和func.o为目标文件的依赖文件,如果有的话,继续按照(1)、(2)的方式匹配下去。根据(2)的匹配过程,make程序发现第3行有目标文件main.o依赖于main.cpp,则比较目main.o与它的依赖文件main.cpp的文件新旧,如果main.o比main.cpp旧,则执行第4行的命令以产生目标文件main.o.在执行第4条命令时,main.cpp在文件makefile不再有依赖文件第定义,make程序不再继续往下匹配,而是执行第4条命令,产生目标文件main.o目标文件func.o按照上面的同样方式判断产生.执行(3)、(4)产生完main.o和func.o以后,则第2行的命令可以顺利地执行了,最终产生了第1行的目标文件main.exe。,特殊处理与伪目标,先看一些makefile的特殊情况:makefile文件内容为a:echo a执行make时,如果文件a存在,echo a将不会被调用,可以理解为文件a没有依赖文件,则认为文件a总是最新的,不需要执行;如果文件a不存在,echo a将会被调用。a:becho a如果文件b不存在,不管a是否存在,make时都将会报错如果文件b存在,文件a不存在,则echo a会被调用如果文件a、b都存在,则按照正常的方式先比较文件新旧,决定是否调用echo,特殊处理的例子,执行make clean将清除掉文件夹中的二进制可执行文件执行make rebuild则先执行清除,再重新编译连接。main.exe:main.o func.o g+-o main.exe main.o func.omain.o:main.cpp g+-c main.cppfunc.o:func.cpp g+-c func.cpp.PHONY:rebuild cleanrebuild:clean main.execlean:rm*.o*.exe,Makefile变量,随着软件项目的变大、变复杂,源文件也越来越多,如果采用前面的方式写makefile文件,将会使makefile也变得复杂而难于维护。通过make支持的变量定义、使用、内置函数和规则,可以写出通用性较强的makefile文件,使得同一个makefile文件能够适应不能的项目。变量:为一文本串定义一个名字,名字即为变量的名称,文本串即为变量的值。定义变量的一般方法:变量名=变量值 递规变量展开(几个变量共享一个值)或者变量名:=变量值 简单变量展开(类似于C+的赋值)使用变量的一般方法:$(变量名)=?赋值?=$(变量名)引用,使用makefile变量,OBJS=main.o func.omain.exe:$(OBJS)g+-o main.exe main.o func.omain.o:main.cppg+-c main.cppfunc.o:func.cppg+-c func.cpp,自动变量,make内部事先定义好了一些变量,他们分为两种类型,自动变量和预定义变量:自动变量:指在使用的时候,自动用特定的值替换。常用的有:,预定义变量,预定义变量:也是make内部事先定义好的变量,但是它的值是固定的,并且有些的值是为空的。常用的有:,内部变量举例,OBJS:=main.o func.oCC:=g+main.exe:$(OBJS)$(CC)-o$main.o:main.cpp$(CC)-o$-c$func.o:func.cpp$(CC)-o$-c$,makefile模式规则,模式规则是指通用第匹配方式,模式规则必须指定”%”,百分号可以匹配任何字符串,例如下面规则:%.o:%.cpp表示任何目标文件的依赖文件是与目标文件同名的并且扩展名为.cpp的文件根据模式规则,上面的makefile可改写为:,OBJS:=main.o func.oCC:=g+main.exe:$(OBJS)$(CC)-o$%.o:%.cpp$(CC)-o$-c$,makefile函数,makefile 里的函数跟它的变量很相似使用的时候,你用一个$符号跟开括号,函数名,空格后跟一列由逗号分隔的参数(第一个参数前不要逗号),最后用关括号结束。例如,有一个叫wildcard 的函 数,它有一个参数,功能是搜索当前目录下的文件名,展开成一列所有符合由其参数描述的文件名,文件间以空格间隔。你可以像下面所示使用这个命令:SOURCES=$(wildcard*.cpp)这行会产生一个所有以.cpp的文件的列表,然后存入变量 SOURCES 里。当然你不需要一定要把结果存入一个变量。另一个有用的函数是字符串替换函数:$(patsubst,要查找的子串,替换后的目标子串,源字符串)它用于将源字符串(以空格分隔)中的所有要查找的子串替换成目标子串。例如,处理那个经过上面定义后的变量,OBJS=$(patsubst%.cpp,%.o,$(SOURCES)将处理所有在SOURCES 字列中的字(一列文件名),如果它的结尾是.cpp,就用.o 把.cpp 替换。注意这里的%符号将匹配一个或多个字符。,gdb调试器,Linux 包含了一个叫gdb的调试程序。gdb可以用来调试C和C+程序。gdb 提供如下一些常用功能:它使你能监视你程序中变量的值.它使你能设置断点以使程序在指定的代码行上停止执行.它使你能一行行的执行你的代码.为了使gdb正常工作,你必须使你的程序在编译时包含调试信息.调试信息包含你程序里的每个变量的类型和在可执行文件里的地址映射以及源代码的行号。gdb 利用这些信息使源代码和机器码相关联。在程序编译时用-g 选项可打开调试选项.gdb 基本命令 gdb 支持很多的命令使你能实现不同的功能.这些命令从简单的文件装入到允许你检查所调用的堆栈内容的复杂命令,表1列出了你在用 gdb 调试时会用到的一些命令.,gdb 基本命令,gdb 基本命令,Gdb调试过程,Gdb调试过程,Gdb调试过程,练习,编写2个以上的类的工程,分别通过gcc命令和makefile编译成执行文件。,