gcc编译过程

一、概述

c语言的编译其实就是把.c文件编译成可在cpu上运行的二进制文件的过程,这个过程可以分成四步:预编译、编译、汇编及链接。

二、编译过程

2.1 预编译

预编译就是做一些编译之前的准备工作,具体如下:

1)头文件展开,就是把#include在源文件中展开。
2)宏替换。#define A b 把代码中的A用b进行替换。
3)条件编译,如#ifdef,#ifndef,#else,#elif,#endif等,根据指令把不需要的代码去掉。
4)特殊符号处理,如FILELINE
5)去除代码中的注释。

gcc -E test.c -o test.i

2.2 编译

通过编译器把高级语言解析成对等的汇编语言。

gcc -S test.c -o test.s

2.3 汇编

把源码编译成目标文件,通常是.o文件。该过程只关注调用的函数是否被定义,并不关心它的具体实现,链接的时候才查找其具体实现的位置。所以如果只对函数进行了定义,并没有具体实现,该编译阶段是不会报错的。

gcc -c test.c -o test.o

2.4 链接

目标文件并不能在cpu上面执行,还需要链接过程,链接的作用就是把目标文件及使用到的静态库或者动态库彼此相连接,形成可加载可执行的二进制文件。链接分为静态链接和动态链接。

2.41 静态链接

静态链接库:就是把多个目标文件(.o)打包成一个.a文件。名称一般是libxxx.a。

1.静态库生成:
    1)源文件编译成目标文件
        gcc -c add.c -o add.o
        gcc -c sub.c -o sub.o
    2)使用目标文件生成静态链接库

    ar crus libmath.a add.o sub.o

上述命令中 crus 是 ar的命令选项:
-c 如果需要生成新的库文件,不要警告
-r 代替库中现有的文件或者插入新的文件,当和 -u 标志(更新)一起使用时,-r 标志仅替换自从最后一次添加到库中以后修改的文件。
-s    无论 ar 命令是否修改了库内容都强制重新生成库符号表。请在库上使用 strip 命令之后,使用此标志来恢复库符号表。

2.静态库的使用
   编译的时候在main函数中包含头文件,然后编译时指定需要链接的库及其路径。
       gcc main.c -o main -lmath -L.
   -l-L是gcc的选项,其中-l指定使用到的库名称,-L指定该库的存放路径。.是指当前路径。 

3.静态库的优缺点:
优点:程序运行时不依赖于环境。
缺点:1)编译的时候静态库会被copy到可执行程序的代码段,这样会造成可执行程 序过大。
2)如果静态库有更新的话,可执行程序也需要重新进行编译。
3)如果好多程序都使用这个静态库的话,也是对内存的一种浪费。如下图(网上搜来 的):

因为静态库有这么多缺点,所以就产生了动态库。

这里写图片描述

2.42 动态库

1.动态库的创建:
           gcc -fPIC -c add.c -o add.o
           gcc -fPIC -C sub.c -o sub.o
           gcc -shared libmath.so add.o sub.o

 -fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
 -shared 提示创建的是共享库。

也可以用一条命令实现:
           gcc -shared -fPIC libmath.so add.c sub.c 
2.动态库的使用
           gcc main.c -o main -lmath -L./lib

注意:编译期间只是把动态库的名称告诉了编译器,而动态库的加载时机是在程序运行期间,如果加载器找不到编译器指定的动态库,程序是运行不起来的。加载器的搜索路径如下,按优先级从高到低:
1)编译目标代码时指定的动态库加载搜索路径;

在编译时通过gcc 的参数”-Wl,-rpath=路径”指定。当指定多个动态库搜索路径时,路径之间用冒号”:”分隔。

gcc main.c -o main -lmath -L./lib -Wl,-rpath=/usr/local/lib

2)环境变量LD_LIBRARY_PATH指定的动态库搜索路径。

一般用”export LD_LIBRARY_PATH=绝对路径名” 来临时指定动态库的加载路径,但该命令只在本终端中有效,再开启另一个终端运行程序的时候需要在重新设置。

3)配置文件/etc/ld.so.conf中指定的动态库搜索路径。

/etc/ld.so.conf的第一行有个引用命令:include ld.so.conf.d/*.conf

因此,最优雅的方式是在ld.so.conf.d目录下创建一个你的程序依赖的配置文件,配置文件内容为程序依赖的动态链接库的路径,一个路径一行。添加完配置文件后执行ldconfig使其生效。

4)默认的动态库搜索路径/lib;

5)默认的动态库搜索路径/usr/lib;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值