嵌入式C语言编译器
1.嵌入式C语言编译器
1.1 GCC与gcc
上述两者的区别:
GCC(GUN Compiler Colletion),是指GUN编译器集合包含众多语言得到编译器如C语言(gcc),C++(g++),Java语言(jdk)、D语言(gdc)、等
gcc 则指的是单纯的C语言编译器
当代的嵌入式开发已经和传统的嵌入式开发不同,硬件性能的提升使其越来越接近桌面开发,使用的开发语言也越来越多样,内核和驱动开发使用C语言,应用开发使用gcc/g++/gdc等。
1.2交叉编译
两种开发模式:
A.非嵌入式开发:A(类)机编写(源代码)、编译得到可执行程序,发布给A(类)机运行。
B.嵌入式开发 :A(类)机编写(源代码)、编译得到可执行程序,发布给B(类)机运行。
为何使用交叉编译
嵌入式产品由于资源受限,不能直接在嵌入式产品上进行编程,所以选择在PC主机上进行源码编写和编译,最终生成在嵌入式设备上运行的程序。
交叉编译可以用高性能机器为低性能机器开发软件(包括裸机软件、系统级和应用级软件)
交叉编译特点:
必须使用专用的交叉编译工具链。由于可执行程序不能本地运行调试,因此必须配合一定手段(专用调试器、JTAG调试器、USB下载、串口下载、SD启动、网络共享等)将可执行程序加载到目标嵌入式设备上运行及调试。
gcc如何进行交叉编译?
配置目标主机的编译工具链(如arm-linux),配置工具链的具体版本。
根据具体的目标代码选择相应的工具链版本
正确使用关于硬件体系结构的特殊编译选项
大型企业嵌入式开发环境:
1.3编译过程
我们通常所将的编译器实际上是指广义的编译器,包含下面四个部分:
整个编译过程如下面所示:
预处理器完成:头文件原地展开、宏定义替换、注释删除工作。
编译器(狭义上的):完成各种语言到目标平台的会变文件的翻译工作。
汇编器:将平台回避那文件编译成最终的二进制文件(.O文件)
链接器:将最终的二进制文件按照连接脚本的内容,链接称为最中的可执行文件Linux中为elf文件。
整个过程:源码.c->(预处理)->预处理过的.i源文件->(编译)->汇编文件.S->(汇编)->目标文件.o->(链接)->elf可执行程序
1.4多语言混合开发
多语言混合开发时当×××发中常见的开发方式,优势在于节省人力成本,提高开发效率。
方式一:目标平台汇编文件的统一
行业案例:
方式二:目标平台二进制文件的统一
行业案例:
方式三:利用进程间通信进行协同
行业案例:
1.5 gcc 编译选项
预处理指令: gcc -E file.c -o file.i
编译指令 : gcc -S file.i -o file.s
汇编指令 : gcc -c file.s -o file.o
生成映射文件: gcc test.c -Wl,-Map=test.map (注意逗号后面没有空格)
宏定义:gcc test.c -D 'TEST="PENGCHAO"' gcc test.c -D TEST=110
获取系统头文件路径; gcc -v file.c
获取目标的完整依赖关系:gcc -M test.c
获取目标的部分依赖关系:gcc -MM test.c
制定库文件及库文件的搜索路径
-L 指令库文件搜索路径
-l 指定库文件名
gcc test.c -L -lfunc
静态库生成命令:ar -rc libfunc.a func.o
动态库生成命令:gcc func.c -o func.o -c -fPIC
gcc -o libfunc.so func.o -shared
nm命令也很有用,它可以用来查看一个.a文件中都有哪些符号
ldd命令:作用是可以在一个使用了共享库的程序执行之前解析出这个程序使用了哪些共享库,并且查看这些共享库是否能被找到,能被解析(决定这个程序是否能正确执行)。
注意:动态链接库运行时需要被加载(运行时环境在执行test程序的时候发现他动态链接了libfunc.so,于是乎会去固定目录(/user/lib)尝试加载libfunc.so,如果加载失败则会打印:error while loading shared libraries: libfunc.so: cannot open shared object file: No such file or directory
解决办法:
A.将动态库文件拷贝到系统库文件目录(不推荐)
B.将动态库文件所在目录导出到环境变量LD_LIBRARY_PATH,export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:path_name