一.GCC简介
gcc 又是一个交叉平台编译器,它能够在当前平台上为多种不同体系结构的硬件平台开发软件。
任意一款处理器都有自己的汇编语言,生成的机器码只能被自身的CPU识别。
arm-linux-gcc test.c –o test 此时linux平台下运行的代码可在arm平台上运行
1. 什么是GNU计划?
一种开源和*软件的计划。(GNU is notUNIX.)
2. 什么是交叉编译?为什么要进行交叉编译?
在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。
之所以要进行交叉编译,有时是因为目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
二.编译选项
1.编译器编译过程
一个.c文件转换成可执行文件大概需要四个阶段:
第一步 预处理 gcc -E test.c -o test.i //生成预编译处理文件
第二步 编译 gcc -c test.s-o test.o //生成目标文件
第三步 汇编 gcc -S test.i-o test.s //生成汇编文件
第四步 链接 gcc test.o -o test //生成可执行文件
1. 预处理(头文件加载、宏替换、条件编译(以#开头的代码))不做语法检查
gcc –Etest.c > test.i
vimtest.i 查看预处理后文件
*系统头文件存放目录:/user/include/stdio.h
#include<stdio.h>:在系统目录(/user/include/)中找stdio.h文件,若不存在则报错;
#include"stdio.h":先在当前目录中找stdio.h文件,若找不到,则再在系统目录中找,若仍找不到,则报错。
-I+第三方寻找目录,
例如:gcc –Wall -O3 main.c test,c -o main -I/root/include
*封装头文件
gcc main.c test.c –o main
在test.h中声明test.c,在main.c中包含头文件
#include”test.h”/#include “路径/test.h”
#include<test.h>将test.h复制到/user/include目录下
gcc–Wall –O3 main.c test.c –o main –I/root/include
(/root/include即为test.h所在目录)
2. 编译(语法检查、语法分析)
gcc -c test.s -o test.o
gcc -w test.c //关闭警告
gcc -Wall test.c //打开全部警告
gcc -static // gcc 进行静态编译,也把所有都需要的函数库都集成进编译出来的程序上,这个程序就可以不依赖外部的函数库运行
-static 选项: 强制使用静态链接库
gcc -o test test.c -L/user/lib -static –lfoo
要求GCC 链接时静态链接/user/lib/ 目录下的libfoo.a
3. 汇编(目标文件生成汇编代码)
gcc –ctest.s –o test.o
4. 链接阶段(符号链接、文件加载。核心工作是符号表解析和重定位。)
/user/lib:软件、程序所需运行的库文件
/lib:系统运行的库文件
库文件:看不到库文件里定义的函数和变量,但是可以使用
SDK:由大量库文件构成(系统开发包)
静态库:.a 在编译时将库文件里的代码段搬迁到可执行文件里
动态库:.so 在执行时将需要的库文件里的代码段搬迁到可执行文件里
静态库与动态库的优缺点:
静态库:代码体积小、执行效率高、不易于升级、编译效率低、易于代码布局
动态库:代码体积大、执行效率低、易于升级、编译效率高、不易于代码布局
printf,scanf,strcpy——>libc.a,libc.so
sin——>libm.a,libm.so
gccmain.c –lm
(-l链接一个库,m为库名)
2. 编译器优化
gcc默认提供了5级优化选项的集合:
-O0:无优化(默认)
-O和-O1:使用能减少目标文 件 大小以及执行时间并且不会使编译时间明显增加的优化.在编译大型程序的时候会显著增加编译时内存的使用.
-O2: 包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化.编译器不执行循环展开以及函数内联.此选项将增加编译时间和目标文件的执行性 能.
-Os:专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项.并且执行专门减小目标文件大小的优化选项.
-O3: 打开所有-O2的优化选项并且增加 -finline-functions, -funswitch-loops,-fpredictive-commoning,-fgcse-after-reload and -ftree-vectorize优化选项.
3. 编译器警告
(1). -w 选项: 关闭警告信息
(2). -Wall 选项: 打开所有警告信息
4. 编译器宏定义(-D)
gcc test.c -D__DEBUG__:在代码中加入__DEBUG__宏定义
5. 编译器指定第三方文件搜索路径(-l)
(1).-I选项:向 GCC的头文件搜索路径中添加新的目录。
gcc -o hello hello.c -I /home/crosstar/include
要求 gcc在 /home/crosstar/include/目录下寻找所需要的头文件。
(2).-L选项:向 GCC的库文件搜索路径中添加新的目录。
gcc -o test test.c -L /home/crosstar/lib –lfoo
要求 gcc在 /home/crosstar/lib/目录下寻找所需的库文件 libfoo.so
(3).-l选项:要求 GCC链接库文件 libfoo.so。
注: Linux下的库文件命名约定 :
通常以 lib三个字母开头。
由于所有的库文件都遵循同样的规范,因此在用 -l选项指定链接的库文件名时可以省去 lib三个字母,也就是说GCC在对 -lfoo进行处理时,会自动去链接名为 libfoo.a/libfoo.so的文件。
三.静态库与动态库的制作与使用
*静态库的生成:
arrcs libtest.a test.o(编译后的.o文件封装到test.a库文件中)
gcc main.c -ltest -L.(当前目录)
(rc:若静态库不存在,则创建;s:若静态库存在,则更新)
(-L……:指定库的搜索路径)
*动态库的生成:
gcc-shared -fPIC test.c -o libtest.so
gcc main.c ./libtest.so(当前路径)