导图社区 linux环境搭建
linux下四大组件: vi编辑器 gcc编译器 gdb调试器 make管理工具
编辑于2019-10-12 13:08:04C语言开发环境搭建
编译工具:把一个源程序编译为一个可执行程序 调试工具:能对执行程序进行源码或汇编级调试 软件工程工具:用于协助多人开发或大型软件项目的管理,如make、CVS、Subvision 其他工具:用于把多个目标文件链接成可执行文件的链接器,或者用作格式转换的工具。 补充: linux下四大组件: vi gcc gdb make
GCC编译器
全称为GNU CC ,GNU项目中符合ANSI C标准的编译系统 一个交叉平台编译器 ,适合在嵌入式领域的开发编译 gcc 1.c gcc 1.c -o 1 查看更详细的信息: $ gcc –v –o test test.c readelf 1.o -a 当程序运行时才分配4G的虚拟内存的.. .text .data .rodata .bss位于内存中 多个编译单位: gcc main.c fun.c fun2.c -o main gcc main.c -o main.o -c gcc fun.c -o fun.o -c gcc fun2.c -o fun2.o -c gcc main.o fun.o fun2.o -o main 补: gcc所支持后缀名解释 .c C原始程序 .i 已经过预处理的C原始程序 .s/.S 汇编语言原始程序 .o 目标文件 .C/.cc/.cxx C++原始程序 .m Objective-C原始程序 .ii 已经过预处理的C++原始程序 .h 预处理文件(头文件) .a/.so 编译后的库文件 ranlib:产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。 readelf:显示elf格式可执行文件的信息。 size:列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。 strings:打印某个文件的可打印字符串。默认情况下,只打印目标文件初始化和可加载段中的可打印字符;对于其它类型的文件它打印整个文件的可打印字符,这个程序对于了解非文本文件的内容很有帮助。 strip:丢弃目标文件中的全部或者特定符号,减小文件体积。
预处理(Pre-Processing)
gcc 1.c -o 1.i -E 编译预处理:解释以#开头的行:文件包含 宏定义 条件编译 不属于C语句,所以不用;结尾 去掉注释 用wc命令,查看这两个阶段代码大小: $ wc 1.c 1.cpp 9 16 127 1.c 842 1934 16498 1.cpp 851 1950 16625 总用量 test.i比test.c增加了很多内容,主要是放在系统提供的include文件中的。
编译(Compiling)
gcc 1.i -o 1.s -S 编译:把C语言翻译为汇编语言
汇编(Assembling)
gcc 1.s -o 1.o -c 汇编:把汇编语言翻译为二进制
链接(Linking)
gcc 1.o -o 1 链接:链接相关的可重定位文件与动态库文件,生成可执行程序
GDB调试工具
调试器-Gdb调试流程
首先使用gcc对test.c进行编译,注意一定要加上选项‘-g’ # gcc -g test.c -o test # gdb test 查看文件 (gdb) l 设置断点 (gdb) b 6 查看断点情况 (gdb) info b 运行代码 (gdb) r 查看变量值 (gdb) p n 单步运行 (gdb) n (gdb) s 恢复程序运行,运行到下一个断点处 (gdb) c del n n不是行,是断点的序号 删除序号为n的断点 q 退出gdb 帮助 (gdb) help [command]
段错误解决方案
段错误解决方案: 1 肉眼看 2 printf 3 gdb调试
gdb的图形界面:ddd
gdb的图形界面:ddd sudo apt-get install ddd ddd a.out
Make工程管理器
1.管理较多的文件。 2.自动编译管理器: 这里的“自动”是指它能构根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件文件的内容来执行大量的编译工作 Make将只编译改动的代码文件,而不用完全编译。 3。Makefile是Make读入的唯一配置文件。
Makefile基本结构
1.Makefile格式: 目标:依赖 //目标名与编译命令生成的可执行程序名字相同 //依赖:就是你编译命令所要依赖的文件,如果多个文件用空格隔开 <tab>编译命令 //tab键如果是4个格,按两个tab键 不能用空格凑够8个字节 main:test.c gcc test.c -o test 2.输入make + 目标名 //make项目管理工具会识别当前目录下一个叫Makefile的文件 会执行对应目标下的命令 //可以只make 后面不加目标名,表示默认执行第一个目标 3.main:main.o fun1.o fun2.o //多个目标的时候.make会自动理清依赖关系 gcc main.o fun1.o fun2.o -o main main.o:main.c gcc main.c -o main.o -c //根据文件时间戳自动发现更新过的文件,只编译更新过的文件,而减少编译的工作量 fun1.o:fun1.c gcc fun1.c -o fun1.o -c fun2.o:fun2.c gcc fun2.c -o fun2.o -c
Makefile变量
一个复杂一些的例子 sunq:kang.o yul.o gcc kang.o yul.o -o sunq kang.o : kang.c kang.h gcc –Wall –O -g –c kang.c -o kang.o yul.o : yul.c gcc - Wall –O -g –c yul.c -o yul.o 注释: -Wall:表示允许发出gcc所有有用的报警信息. -c:只是编译不链接,生成目标文件”.o” -o file:表示把输出文件输出到file里 刚才的例子 OBJS = kang.o yul.o CC = gcc CFLAGS = -Wall -O -g sunq : $(OBJS) $(CC) $(OBJS) -o sunq kang.o : kang.c kang.h $(CC) $(CFLAGS) -c kang.c -o kang.o yul.o : yul.c yul.h $(CC) $(CFLAGS) -c yul.c -o yul.o
自定义变量
1.简单方式 VAR:=var 变量使用$(VAR) 用”$”则用”$$”来表示 类似于编程语言中的宏 2.自定义变量: OBJS=main.o fun1.o fun2.o $(OBJS)
预定义变量
变量已经预先定义过,可以直接使用,如果直接使用,表示的就是它预定义的意思.. 也可以重新赋值,自己给它一个意思.. CC RM CFLAGS 预定义变量(常见编译器 汇编器的名称 编译选项) AR 库文件维护程序的名称,默认值为ar。 AS 汇编程序的名称,默认值为as。 CC C编译器的名称,默认值为cc。 CPP C预编译器的名称,默认值为$(CC) –E。 CXX C++编译器的名称,默认值为g++。 FC FORTRAN编译器的名称,默认值为f77 RM 文件删除程序的名称,默认值为rm -f CFLAGS C编译器的选项 CFLAGS = -Wall -O -g 补充1: .PHONY:clean //Make 并不将其当作一个文件来处理,而只是当作一个概念上的目标。 clean: <tab> $(RM) hello 补充2: @(RM)并不是我们自己定义的变量,那它是从哪里来的呢? 通常在清除文件的伪目标所定义的命令中“rm”使用选项“–f”(--force)来防止在缺少删除文件时出错并退出,使“make clean”过程失败。这种方式时 make 会提示错误信息但不会退出。为了不看到这些讨厌的信息,需要使用上述的第一种方式。 另外 make存在一个内嵌隐含变量“RM”,它被定义为:“RM = rm –f” 。因此在书写“clean”规则的命令行时可以使用变量“$(RM)”来代替“rm”,这样可以免出现一些不必要的麻烦!这是我们推荐的用法。
自动变量
自动变量: $@ 目标文件 $^ 所有依赖文件 以空格分开 $< 第一个依赖文件的名称 选项: -C dir 读入指定目录下的Makefile make -C myself -f file 读入当前目录下的file文件作为Makefile make -f test
Make使用
直接运行make 选项 -C dir读入指定目录下的Makefile -f file读入当前目录下的file文件作为Makefile -i忽略所有的命令执行错误 -I dir指定被包含的Makefile所在目录 -n只打印要执行的命令,但不执行这些命令 -p显示make变量数据库和隐含规则 -s在执行命令时不显示命令 -w如果make在执行过程中改变目录,打印当前目录名 补充: 1.make -C $@ 这是一句嵌套makefile的语法,在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的Makefile,这有利于让我们的Makefile变得更加地简洁,而不至于把所有的东西全部写在一个Makefile中,这样会很难维护我们的Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。 2.export CC OBJS BIN OBJS_DIR BIN_DIR 我们把这个Makefile叫做“总控Makefile”,总控Makefile的变量可以传递到下级的Makefile中,但是不会覆盖下层的Makefile中所定义的变量。 如果你要传递变量到下级Makefile中,那么你可以使用这样的声明: export <variable ...>
GCC错误类型及对策
第一类∶C语法错误 错误信息∶文件source.c中第n行有语法错误(syntex errror)。有些情况下,一个很简单的语法错误,gcc会给出一大堆错误,我们最主要的是要保持清醒的头脑,不要被其吓倒,必要的时候再参考一下C语言的基本教材。 第二类∶头文件错误 错误信息∶找不到头文件head.h(Can not find include file head.h)。这类错误是源代码文件中的包含头文件有问题,可能的原因有头文件名错误、指定的头文件所在目录名错误等,也可能是错误地使用了双引号和尖括号。 第三类∶档案库错误 错误信息∶链接程序找不到所需的函数库(ld: -lm: No such file or directory )。这类错误是与目标文件相连接的函数库有错误,可能的原因是函数库名错误、指定的函数库所在目录名称错误等,检查的方法是使用find命令在可能的目录中寻找相应的函数库名,确定档案库及目录的名称并修改程序中及编译选项中的名称。 第四类∶未定义符号 错误信息∶有未定义的符号(Undefined symbol)。这类错误是在连接过程中出现的,可能有两种原因∶一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题,这时需要使用档案库维护命令ar检查我们需要的库函数到底位于哪一个函数库中,确定之后,修改gcc连接选项中的-l和-L项。
其他选项
-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。 -Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。 -Ldirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数。
优化选项
-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。 -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
警告和出错选项
-WALL:打开所有类型语法警告,建议使用 -w 禁止警告信息
编译选项
GCC的执行过程
GCC是Linux平台下常用的编译链接器。编译链接的过程分为: 源代码-->预处理文件(.i)-->编译后的汇编代码(.s)-->汇编后的二进制文件(.o)-->链接后的二进制文件(无后缀)。 处理程序分别是 :cpp、ccl、as、ld。 1.调用cpp进行预处理,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析; 2.调用cc1进行编译,生成.s为后缀的目标文件; 3.调用as进行汇编,汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件; 4.调用ld进行链接,所有的目标文件被安排在可执行程序中的恰当的位置。同时,该程序所调用到的库函数也从各自所在的档案库中链接到合适的地方。