对于需要在Linux上编程的场合,其实完全可以用VS替代,但学习GCC编译和GDB调试还有Makefile可以帮助理解程序结构。
入门期间,会简单用GCC编译指令即可,GDB调试前期是没什么机会的,但Makefile要会看。推荐《跟我一起学Makefile》一书,这里只做简单介绍。因为笔者有这本书,需要时翻这本书比翻笔记更快。
对比华清远见和正点原子的教程,我准备从gcc编译,gdb调试和Makefile语法三方面笔记,至于传统的编辑器vi不做记录,打字没什么好学的
GCC编译
gcc能编译多种代码,其生成可运行文件的过程大致为 预处理、编译、汇编、链接四个流程。
预处理
即对头文件和宏定义的处理过程,.c文件经过预处理后生成的文件为.i文件。
编译
首先是检查代码规范性和语法错误,然后将代码翻译为汇编,否则报错。编译后生成的文件为.s文件
汇编
将汇编代码转换为二进制文件,处理结果是.o文件。
链接
即链接函数库,比如当使用printf函数时,我们并没有实现这个函数,这个函数定义在stdio.h文件中,而实现在libc.so.6库文件中,查找函数实现并调用,就是链接的作用。
类似libc.so.6这种库文件,分为静态库和动态库两种。静态库在编译链接时会将代码全部加入可执行文件,因此生成的文件比较大,但运行效率高。动态库则相反,程序只在执行过程中需要时才加载库,相当来说效率就慢。
该阶段结束后即可生成可执行文件。
参数选项
gcc编译时可以用-c/-S/-E等参数包括但不限于限制编译过程、规定生成类型、设置路径依赖等等,比如只编译不连接、在可执行程序中包含标准调试信息种种功能。具体有哪些参数,这里不做展开,提供一篇参考
菜鸟教程是一个很好的学习网站
GDB调试
VS提供的调试方法其实已经很够用了,但是GDB调试在没有安装VS的系统上或者需要提供输出时最适用,对笔者来说,仅做了解。
使用gdb调试需要在编译时对.c加上 -g 选项,这样才能在可执行代码中包含调试信息。另外注意gdb的执行对象是可执行文件而不是.c文件。
常用功能
查看文件 l(list) 设置断电 b (行号)
查看断电情况 info b 运行代码 r
查看变量值 p (变量名) 单步运行 n/s
恢复运行 c(continue)
更多命令可以通过 help 参数查看,实际上在Linux中很多手册之类的参考都可以尝试使用 help或者 -h查看帮助。
指令类型
工作环境相关命令
断点控制命令
源码相关命令
运行数据/参数命令
Makefile基本语法
什么是Makefile?通过前面的介绍可以知道,在编译过程中往往需要根据实际情况增加或者减少某些参数,当.c文件多起来,一行行的命令敲会很麻烦且还不考虑输入错误的情况,清理也很麻烦。
而Makefile就是解决这种麻烦的东西,可以理解为一种脚本,用于为一个项目制定编译规则,比如什么文件先编译?什么文件需要重新编译?什么文件只需要编译到汇编代码等等,提高编译效率。
常用的VS一类IDE其实内部也有Makefile,只不过被封装成了更高级的图形界面,这一层不用程序员关注,也就是说其实Makefile也能自动生成。这里需要用到一种叫做autotools的工具,但这不在笔者的学习范围内,对于Makefile要么深入学习看书,要么就只要会用即可。
Makefile结构
目标:依赖文件
指令
其中指令一行必须以制表符即tab键开头。假设现在有一个fun.c,要编译出.o文件,那么我们就需要在一个Makefile文件中写如下指令:
fun.o:fun.c fun.h
gcc -c hello.c -o hello.o
随后执行Make指令即可。
可能有疑惑的是,为什么直接从.c到.o了,预处理和编译过程的.i和.s文件呢?是这样的,一般来说一个程序不可能只由一个.o文件就生成,往往需要多个.o文件作为依赖文件才能生成,所以一般.o文件是我们需要的,而.i和.s属于中间文件,并不作为最后必须的依赖文件,在编译过程中就会删掉,所以这里虽然是一条指令,但是完成了一直到汇编的三个过程,只不过多余文件在用完后就删掉了。
Makefile变量
一般来说,Makefile中往往会用许多命令和文件,现在有一批经常用到的依赖文件,如果每次用到的时候都要重新写,未免有些太不方便,所以Makefile允许用一个字符串作为变量名来代替这批依赖文件,同样的也可以代替目标文件或者命令等。
大致有两种使用方式
递归展开式:VAR=var
简单扩展式:VAR:=var
使用时 $(VAR)
变量名区分大小写!一般用小写作为变量名,大写另作他用。
另外Makefile中还支持自动变量,不做细讲
来源为华清远见嵌入式学院第三章
Make规则
隐式规则:让make按照传统的默认规则完成任务,结合变量的一个例子是
obj = fun.o hello.o
CC = gcc
prj:$(obj)
$(CC) $^ -o $@
不清楚对不对,随手写的,大致意思就是对于.o文件我们可以直接使用,不在需要写由.c生成.o的过程,因为默认xx.o由同名xx.c生成。
模式规则
用以定义相同处理规则的多个文件,且能使用变量,可以为多个文件建立相同规则来简化Makefile。
obj = fun.o
CC = gcc
CFLAGS = -Wall -o -g
david:$(obj)
$(CC) $^ -o -$@
%.o:%.c
$(CC) $(CFLAGS ) -c $< -o $@
最后
一般来说有专门写Makefile的程序员,使用是只需要关注make和make clean即可,毕竟Makefile是一种提供编译效率的工具,并不是程序开发的重点