gcc编译过程

1、几个文件(//main.c,//visit.c,//study.c,//visit.h,//study.h)

在同一个目录下,编译出a.out文件的几种方法

(1)头文件的声明和作用https://blog.csdn.net/colourpen/article/details/6293065

 ①编译器 在扫描到一条【函数调用】语句时首先 应当知道该 函数的原型 或 定义 。即,读到这条语句之前,应该已经出现过函数的声明(或者定义)。这样编译器才知道这是个函数,然后通过指针跳转到存储函数的内存区间。

②函数原型一般都放在头文件中,函数定义则放在源文件中,当源文件或头文件通过#include指令包含另一个头文件的时候,编译预处理器 用头文件的内容代#include伪指令。这就是说,头文件的所有内容最终都会被合并到某一个或某几个源文件中,如此将每一个包含的头文件递归地展开后形成 的源文件就叫编译单元。

③通过改变连接性( extern/static ), 可以 使 一个编译单元 中 函数和变量 让其他编译单元使用。

 声明只是告诉编译器,叫XXX的是个变量或者是个函数 。你要用,还得找定义在哪。

 ④定义是具体实现,会在.o文件中生成符号 。  函数和变量都默认外部连接性(所有编译单元都能看到,这里有一个叫做XXX的变量或函数的导出符号,比如_XXX)。

         连接时,这个编译单元需要什么符号 (声明说了,这个XXX是个函数,但自己没有定义,只能去别的地方找 ),就从别的编译单元导出的符号里找。    

         因此,头文件里声明一个函数,一般都只是声明。很多cpp都会include它,然后cpp就知道了叫XXX的是个函数,但是发现自己这里没定义,再去别的cpp里找。

         //  如果 .h 里放了定义,有两个cpp文件都include这个.h, 一连接,这个定义就出现了两次(冒出两个一样的符号 duplicated external simbols )。

         所以,对于外部连接性的东西(函数和变量),声明可以每个文件里都有,但是定义只能有一个 !

头文件用途:

 1、通过头文件来调用库功能。源代码不便向用户公布,只 要向用户提供 头文件 和 二进制的库 即可。头文件中找接口声明,然后调用库函数。连接器会从库中提取相应的代码,并和用户的程序连接生成可执行文件 或者 动态连接库文件。
2、头文件能加强类型安全检查。接口被实现的方式与头文件中的声明不一致,编译器就会指出错误。

【头文件的内容】:

(1)头文件注释(包括文件说明、功能描述、版权声明等)(必须有);
(2)内部包含卫哨开始(#ifndef XXX/#define XXX)(必须有);
(3)#include其他头文件(如果需要);
(4)外部变量和全局函数声明(如果需要);
(5)常量和宏定义(如果需要);
(6)类型前置声明和定义(如果需要);
(7)全局函数原型和内联函数的定义(如果需要);
(8)内部包含卫哨结束:#endif   // XXX(必须有);
(9)文件版本及修订说明。
 

(1)gcc -c main.c visit.c study.c -o a.out

通过gcc工具直接将多个c文件链接编译;有一些gcc编译器是需要注意文件顺序的;如果main.c中没有#include“visit.h”,我们也可以通过执行命令的方式指定头文件的位置;但是这种方法一般不用;如果头文件不在当前目录,也可以通过-I选项指定头文件目录

 

(2)通过链接库文件和头文件编译

gcc -c visit.c -o visit.o

gcc -c study.c -o study.o

ar -rcs libadd.a visit.o study.o

gcc main.c -o a.out -ladd或者gcc  main.c -o a.out libadd.a

gcc头文件的搜索路径: 头文件 gcc在编译时如何去寻找所需要的头文件:

头文件的搜索会从-I指定的目录开始;
然后搜索gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,finOBJC_INCLUDE_PATH 设置的目录;
再搜索系统目录 /usr/include 和 /usr/local/include(centos7中该目录下是空的);
最后搜索gcc的一系列自带目录(如/usr/include/c++/4.8.5)。
 

GCC与库文件
gcc -参数:

-L :指定连接的动态库或者静态库路径(相对路径或绝对路径,建议相对路径)
-l (L的小写):指定需要链接的库的名字(链接 libc.a : -lc 链接动态库:libc.so : -lc)。 注意:-l后面可以直接添加库名省去“lib”和“.so”或“.a”。 -l(L的小写)链接的到底是动态库还是静态库,如果链接路径下同时有 .so 和 .a 那优先链接 .so 。
 

如果路径下同时有静态库和动态库如何链接静态库?

使用显示链接, gcc -l:lib***.a (将静态库的名字显示写出来)
在 gcc 编译的时候 加入参数 -static -lXXX, 则可以添加路径下面的静态库。
ldd命令
可以通过 ldd 命令查看生成的目标文件链接的库,使用方法:ldd加 二进制文件可执行文件。除非指定链接后生成的二进制文件名,否则默认为.out文件就是扩展名为out的文件,它本身不代表任何信息。在Linux中判断文件是否是可执行文件,首先要看文件的属性是否是可执行的,它没有一个默认的扩展名表示此文件为可执行文件。为了方便,Linux中可执行文件一般都是没有扩展名的。
 

库文件编译的搜索路径

gcc会先搜索-L指定的目录;
再搜索gcc的环境变量LIBRARY_PATH;
再搜索系统目录:/lib和/lib64、/usr/lib 和/usr/lib64、/usr/local/lib和/usr/local/lib64,这是当初compile gcc时写在程序内的。(静态库和动态库的搜索)

 

运行时动态库的搜索路径,动态库的搜索路径搜索的先后顺序是:

编译目标代码时指定的动态库搜索路径;
环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
配置文件/etc/ld.so.conf中指定的动态库搜索路径;
默认的动态库搜索路径/lib;/lib64
默认的动态库搜索路径/usr/lib 。 /usr/lib64当然,如果是64位系统,还包括 /lib64 和 /usr/lib64。

 

静态库的搜索路径

ld会去找GCC命令行中的参数-L的目录中是否有该静态库;
再去找GCC的环境变量LIBRARY_PATH
再找内定目录/lib /lib64、/usr/lib /usr/lib64、/usr/local/lib /usr/local/lib64是否有该链接库,这是当初compile gcc的时候确定的。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyDog0623

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值