跟着iMX28x开发套件学linux-03

二、linux应用编程之一编译基础知识

VS这类集成IDE的编译过程已经被简化成ctrl+f5,底层一点的编译过程已经被淡化。而linux应用开发或者驱动开发又要对编译过程有一定的了解,所以学习编译基础知识还是很有必要的。

gcc编译流程

gcc编译流程分为四步,分别是:预处理,编译,汇编,链接。

1) gcc -E test.c -o test.i : 预处理,各种预处理命令进行处理,包括头文件包含、宏定义的扩展、条件编译的选择等。

2) gcc -S test.i -o test.s : 编译,将预处理得到的源代码文件,进行“翻译转换”,产生出机器语言的目标程序,得到机器语言的汇编文件。

3) gcc -c test.s -o test.o : 汇编,将汇编代码翻译成了机器码,但是还不可以运行。

4) gcc    test.o -o test   : 链接,处理可重定位文件,把各种符号引用和符号定义转换成为可执行文件中的合适信息,通常是虚拟地址。

常用的gcc选项

1) -g : 添加调试内容,用于GDB调试,是在汇编过程就要加上了。

2) -O  优化编译,可选优化等级,01,02,03O3优化等级最高。

3) -w/-W : 关闭/开启编译警告。

4) -v : 显示编译详细信息。

5) -I  编译时包含头文件的目录,后面要跟上头文件目录的路径。

6) -static : 编译采用静态链接,即将库文件包含到程序中,程序会变得非常大,gcc默认是动态编译。

库文件是一些数据类型,函数和变量等的集合。库的详细内容是不可见的,只可以在头文件中看到函数原型。例如标准输入输出库,只要包含了stdio.h就可以自动地链接到标准输入输出库。库分为静态库(.a)以及动态库(.so)。

静态库(.a)是.o文件的集合,在编译的链接阶段使用,编译器将程序用到的函数从静态库里面提取出来,整合到程序中去。因为程序中用到的库函数都被整合到了程序中,所以编译出来的程序会比较大。创建用户静态库的步骤如下:

1) 编写库的.c文件 : 按照要求,可以编写多个.c文件,注意.c文件内要include一个.h文件。

2) 编写库的.h文件 : 在.h文件中声明所有库函数的函数原型。

3) 将所有的.c文件进行编译不链接(-c) : 正确进行编译后产生若干个.o文件。

4) ar -r 库名.a *.o(所有的.o文件,空格间隔) : 将.o文件链接成库。

5) 使用库 编写.c文件时include库的.h文件,编译的时候引用生成的库.a以及头文件.h。

在编译时引用库的方式一般有以下几种方式:

1) gcc test.c test.a -o test : 直接在编译列表中加入库文件(.c文件后),可以包含路径。

2) gcc test.c -L ./libtest -lFOO: 用-L引入库文件所在的目录,再用-lFOO引用名字为libFOO的库(所以库的文件名就要写成lib**了),这样可以避免每个库都要写带路径的全名。

动态库以.so(share object)结尾,在Windows中以.dll结尾。动态库创建与使用都与静态库类似,但是用动态库编译的文件在运行时,要在系统中能找到动态库文件才能正确运行。创建动态库的步骤如下:

1) 前三步与静态库一样,都是生成.o文件和.h文件。

2) gcc -shared -fPIC -o 库名.so *.o(所有的.o文件,空格间隔)  : 将.o文件链接成库。

引用动态库的方法跟静态库差不多,但是生成的可执行文件在执行之前要把动态库放到系统库文件目录下,比如/usr/lib 。

其实静态或者动态库平时接触也很多,就是没有留意到。例如在keil中添加一个.c文件,再添加一个.h文件,编译完成之后就可以在其他文件中引用这个.c文件中的函数了,这里用到的应该是用户创建库,只是创建及引用过程被keil封装成了一个编译按钮。

Makefile

每次编译都要写一大串gcc指令,太繁琐了,用Makefile可以简化这个过程。Makefile可以看成是一个编译脚本,运行这个Makefile脚本就可以完成想要完成的编译动作。有些版本的Ubuntu没有安装make工具,要先安装make工具。

Makefile的格式比较简单,暂时用到的初级通用Makefile代码如下:

   

.PHONY:clean 表示伪目标,意思是clean不是目标,但是可以make clean调用这个“目标”下的指令,主要用来删除编译产生的文件。

EXE, OBJ, SRC, CC, CFLAGS, TEMP 这些都是变量,用$(变量名)就可以引用这些变量。其中EXE代表生成可执行程序名,OBJ表示生成过程文件名(.o文件), SRC表示.c程序名, CC表示编译器类型,可以用gcc编译生成可执行文件在Ubuntu上运行,也可以用arm-linux-交叉编译器生成可执行文件在开发板上面运行。CFLAGS表示编译选项,可以加上类似-g-v-O这类的选项。TEMP表示临时文件,如果程序中用了creat()之类的函数创建了新的文件,可以把生成的文件名添加到这里,运行make clean可以删除掉。

注意一点:“目标:依赖文件”的下一行是指令行,这里有一个缩进,这个缩进必须要用一个tab实现,不管文本编辑器的tab是几个空格都行,但是不能用几个空格代替。

GDB

GDB是一个代码调试工具,功能很强大,可是没有图形界面用起来不是很习惯,所以安装了GDB的图形界面DDD。用命令 ddd 可执行文件可以打开ddd界面,前提是在汇编的时候一定要加上-g选项,不然打开的ddd界面没有显示代码,也调试不了。ddd中可以输入GDB的指令,常用的指令如下:

1) break 行号 : 在第几行设置断点。

2) clear 行号 : 取消在第几行设置的断点。

3) watch 变量名 : 观察一个变量的值。

其他指令暂时还没用过,在ddd的可视化界面上的按钮可以快速实现这些命令。

个人选择

个人比较喜欢可视化编程,所以在Ubuntu上我是用notepad+ddd来完成编程的,vi只是用来修改一些系统配置文件或者写一些简单一点的测试程序。本来还想折腾eclipse,装了cdt插件后发现编译出错,而且偶尔打开报错,一直都搞不定。想了想,Makefile也要自己写,不如用notepad算了,省事一点。暂时先用着吧,后面有别的需求再考虑换。

猜你喜欢

转载自www.cnblogs.com/liangda/p/9905044.html
今日推荐