GCC的基础用法


前言

GCC(GNU Compiler Collection,GNU编译器套件)是由GNU开发的编程语言编译器。GNU编译器套件包括C、C++、 Objective-C、 Fortran、Java、Ada和Go语言前端,也包括了这些语言的库(如libstdc++,libgcj等。)


一、程序编译流程

编译器对程序编译形成可执行程序(Windows:.exe,Linux:.elf)有4个步骤:预处理编译汇编链接
1 预处理:主要是展开头文件,替换宏定义,去掉注释,生成.i结尾的文件。
gcc -E xxx.c -o xxx.i
2 编译:GCC编译器对预处理完的文件进行一系列词法分析,语法分析,语义分析,代码优化等后生成.s结尾的汇编文件。
gcc -S xxx.i -o xxx.s
3 汇编:GCC编译器对汇编代码转变成机器可以执行的二进制指令,生成.o结尾的二进制文件。
gcc -c xxx.s -o xxx.o
4 链接:GCC编译器将各个目标文件链接起来,生成可执行文件。
gcc xxx.o -o xxx

示例:
这里使用g++来进行编译.cpp文件。本质上gcc与g++没有什么区别,两者都可以编译c程序和c++程序,但还有一些细微的区别:
1 在编译阶段,对于.c结尾的c程序而言,gcc将其当作c程序编译,而g++将其当作c++程序来进行编译。
2 在链接阶段,对于.cpp结尾的c++程序而言,g++可以自动链接到标准c++库,而gcc只需要参数 -lstdc++。
在这里插入图片描述

二、静态库和动态库

静态库
在编译过程中,静态库中的代码会被完整地复制到目标程序中,因此生成的可执行文件较大,但不需要依赖外部库文件。
在Linux系统中,由ar工具生成。命名规则如下:
以lib作为前缀,中间由自己命名,.a结尾。libxxx.a。(windows系统以.lib结尾)
1 静态库的工作原理
在程序编译的链接阶段,静态库会被打包到可执行程序当中,静态库中的代码会被被加载到内存当中,不会出现找不到静态库的问题。
2 静态库生成
首先将源文件进行汇编操作得到二进制文件**(gcc -c xxx.c -o xxx.o)**,然后使用ar工具将目标文件进行打包,生成静态库文件libxxx.a。
ar工具参数:
c:创建一个库,不管这个库是否存在。
s:将目标文件索引,可以提升静态库的生成速度。
r:在库中插入模块。如果库中存在则替换,没有则添加在库的结尾。
在这里插入图片描述
3 静态库使用
在这里插入图片描述

动态库
在编译时不会被链接到目标程序中,而是在程序运行时由操作系统动态加载到内存中,因此生成的可执行文件较小,但依赖于外部的动态库文件。
在Linux系统中,由ar工具生成。命名规则如下:
以lib作为前缀,中间由自己命名,.so结尾。libxxx.so。(windows系统以.dll结尾)
1 动态库的原理
在编译的链接阶段,动态库不会打包到可执行程序中,只是记录了动态库的名字。在可执行程序执行起来后,会检测所需的动态库是否存在,找不到则报错。当程序执行过程中,动态库中的函数被调用,此时动态库才会加载到内存中。(检测和加载都是由动态链接器来完成的)
动态链接器
动态链接器是一个独立于应用程序的进程,属于操作系统。当需要加载动态库的时,动态链接器就开始工作了。动态链接器检索动态库的顺序为:可执行程序内部的DT_RPATH,系统的环境变量LD_LIBRARY_PATH,系统动态库缓存文件/etc/ld.so.cache,存储动态库/静态库的系统目录。
2 动态库的生成
动态库的生成可以直接使用gcc。首先gcc汇编生成二进制文件时加上参数-fpic(该参数意思是代码与位置无关)生成二进制文件,然后gcc加上参数-shared打包生成动态库。
在这里插入图片描述
3 动态库使用
在这里插入图片描述
通过ldd命令可以查看当前执行程序所需的动态库是否可以找到。
在这里插入图片描述

生成可执行程序后,执行发现找不到动态库,如下图所示:
在这里插入图片描述
解决方案:
1 编译生成可执行程序时,指定可执行的DT_RPATH段。
在这里插入图片描述
2 修改系统的环境变量LD_LIBRARY_PATH。
在这里插入图片描述
发现系统并没有设置LD_LIBRARY_PATH环境变量,可以通过export命令来设置这个值。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这种方法只在当前终端生效,为了在任何终端生效,我们可以修改~/.bashrc配置文件。
在这里插入图片描述
3 更新/etc/ld.so.cache缓存文件。
4 拷贝动态库文件到系统库目录。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值