gcc介绍
GNU编译器套件(GNU Compiler Collection)包括C、C++、Objective-C、Fortran、Java、Ada和Go语言的前端,也包括了这些语言的库(如libstdc++、libgcj等等)。GCC的初衷是为GNU操作系统专门编写的一款编译器。GNU系统是彻底的自由软件。
1)gcc是一个可移植的编译器,支持多种硬件平台
2)gcc不仅仅是个本地编译器,它还能跨平台交叉编译。
3)gcc有多种语言前端,用于解析不同的语言。
4)gcc是按模块化设计的,可以加入新语言和新CPU架构的支持
5)gcc是自由软件
gcc常用编译选项
选项 作用
-o 产生目标(.i、.s、.o、可执行文件等)
-c 通知gcc取消链接步骤,即编译源码并在最后生成目标文件
-E 只运行C预编译器
-S 告诉编译器产生汇编语言文件后停止编译,产生的汇编语言文件扩展名为.s
-Wall 使gcc对源文件的代码有问题的地方发出警告
-Idir 将dir目录加入搜索头文件的目录路径
-Ldir 将dir目录加入搜索库的目录路径
-llib 链接lib库
-g 在目标文件中嵌入调试信息,以便gdb之类的调试程序调试
gcc编译过程
gcc -E hello.c -o hello.i(预处理)
gcc -S hello.i -o hello.s(编译)//在这到之前生成出来的文件都是可以直接看到的
gcc -c hello.s -o hello.o(汇编)//由汇编代码生成一个二进制文件
gcc hello.o -o hello(链接)//此时这个hello是linux下的可执行文件
以上四个步骤,可合成一个步骤
gcc hello.c -o hello(直接编译链接成可执行目标文件)
!gcc 运行上一个gcc命令
gcc编译警告提示
#include <stdio.h>
int main(void)
{
printf("2+1 is %f", 3);
return 0;
}
上面一段代码,编译可以通过,但是运行结果:
而且我们编译的时候,没有给我们任何提示。
所以我们一般编译的时候,需要加上-Wall命令
gcc编译多个文件
一次行编译
gcc 1.c 2.c -o hello
分多次编译
gcc -Wall -c 1.c -o mainf.o
gcc -Wall -c 2.c -o fun.o
gcc fun.o mainf.o -o hello//汇编,进行链接
然后就可以./hello 运行得出结果
用脚本文件静态库生成并且链接
我的目录结构:
inc:存放的是.h文件
lib:存放的是生成的静态库.a文件
src:存放静态库函数
test:测试程序
script:里面是gcc编译命令以及一些其他命令(后面文章会用makefile代替)
需要chmod 775 script 将script变为可执行文件
script内容:
#将myadd.c生成一个二进制文件,-I ./inc 代表从这个里面找头文件
gcc -c -Wall -I ./inc ./src/myadd.c -o myadd.o
#将myadd.o的二进制文件生成静态库,静态库文件名为libmyadd.a(为什么lib开头后面讲)
ar rcs libmyadd.a myadd.o
#删除.o结尾的文件,将静态库移动到lib目录下
rm *.o
mv libmyadd.a ./lib
*静态库名称一般为libXXX.a
那么我们调用这个静态库就要在结尾加上-lXXX
编译测试程序将静态库链接进来
gcc -Wall -L./lib -I ./inc ./test/main.c -o ./main.out -lmyadd
这个时候,静态库会包含到main.out这个程序里面去,就可以不需要libmyadd.a这个静态库了
此时可以运行这个程序
nm命令
nm 静态库名称
这个就可以查看到静态库里面的哪些函数
生成动态库并链接
1生成动态库
目录结构和上面的结构一样,这里我们会将生成的动态库也放到lib目录下,此时不生成静态库
在script下的脚本
gcc -shared -fPIC -I ./inc ./src/myadd.c -o libmyadd.so
mv *so ./lib
shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
这个动态库,可在任何位置加载,叫做位置无关码。
这个动态库,在指定位置加载,成为与位置有关
这个时候生成一个so文件动态库文件在lib目录下
2调用动态库
编译test下的测试程序
gcc -Wall -I ./inc -L ./lib ./test/main.c -o main -lmyadd
-L:指定动态库的位置
这个时候我们调用main这个程序发现报错:找不到动态库,默认/usr/lib
是因为系统不知道我们这个库所在的目录
1我们通过cd命令进入桌面目录目录
2vi .bash_profile #这个文件是隐藏的,是环境变量,不同的用户不一样
添加如下:寻找当前目录和当前目录下的lib目录
3source .bash_profile 刷新这个配置文件使配置文件生效
4运行成功
ldd命令
ldd命令:查看程序链接了库的位置
file命令
file 文件名查看文件的属性