编译链接基础知识——Linux

(菜鸡自救,仅做个人记录,谢谢大佬)

主要参考:编译链接基础知识 · FFmpeg原理 (xianwaizhiyin.net)

1、从简单的命令开始:

编译程序:
gcc -c -o hello.o hello.c

Linux命令格式 :命令 [选项] 参数

-c:只编译,不链接

hello.o:输出文件 

hello.c:输入文件

在编译时,对于一些函数的地址先用占位符占位,如00 00

链接程序:
gcc -o hello hello.o
链接动态库VS链接静态库 :

动态库:libc.so

静态库:libc.a

gcc默认使用动态库链接,找不到.so文件,才会采用静态链接找.a文件。

如何手动设置静态链接?
gcc -o hello hello.o -static -lc

-static:设置所有库都以静态的方式链接 ;

-l:这是一个需要链接的库,不需要加lib;

c:库名,指libc.so库,若-ltest 指链接libtest.so;

Linux 系统各个版本的 C运行时库版本 可能不一样,该怎么解决?

(1)静态链接;

(2)将动态链接库libc.so文件复制到运行程序当前目录,跟程序一起发布;再在 /etc/ld.so.conf.d/ ,添加相关配置,再执行 sudo ldconfig 即可。因为 ld.so.conf.d 里面的路径是优先于 /lib 跟 /usr/lib 目录的。

2、gcc编译多个C文件

无论是多庞大的C/C++ 项目,编译阶段,都是单个文件编译的,单个文件里面引用了外部的变量,函数。编译阶段只会把这些引用 替换成一些占位符号,例如 00 00 。

只有在链接阶段,gcc 才可以接受多个 文件作为输入。然后 扫描这些输入文件,找到各个 函数符号地址,然后进行替换。链接器通常会扫两次输入文件,第一次找到所有符号,第二次才开始替换占位符号。

提示:命令可以加上 -v 或者 -### 显示更多的编译信息。

大型C/C++项目编译时会遇到哪几种问题?
(1)找不到头文件:

加上-v函数,观察#include说明,查看目标头文件是否在相关路径下;如果头文件的目录不在编译器搜索路径当中,利用-I参数加上搜索路径:

gcc -v -c -o sun.o sun.c -I/home/ubuntu/

 #include引入头文件的两种写法:

#include "moon.h"
#include <moon.h>

<header.h>只在系统目录下查找

"header.h"在系统目录和当前目录找 

(2)undefined reference:

a.‘undefined reference to `std::ios_base::Init::Init()’

一般编译链接c++程序最好使用g++,若有如上的报错信息,需要在gcc后加上 -lstdc++

eg: gcc test.c -lstdc++

gcc和g++都是GNU的一个编译器。

g++:后缀.c的程序和.cpp的程序都会当成是c++的源程序来处理。
gcc:会把.c的程序处理成c程序。

对于**.cpp**的程序,编译可以用gcc/g++,链接可以用g++或者gcc -lstdc++。

b. undefined reference to `xxx'

找不到实现函数的库:命令中遗漏库引用,或者写错库名称

3、编译静态库

静态库VS动态库

参考:(85条消息) 静态库与动态库的区别与优缺点_静态库和动态库的优缺点_雨荔@秋垣的博客-CSDN博客

实践参考:

C++静态库与动态库 - 吴秦 - 博客园 (cnblogs.com)

静态库也称归档文件,就是对已经编译好的字节码进行封装,在编译时直接整合到目标程序中,编译成功的可执行文件可独立运行;

动态库在编译时,目标程序中只会存在一个“指向”的位置,可执行文件无法单独运行;

封装静态库:

Linux 的静态库封装,实际上就是打包,把多个 .o 文件打包在一个 .ar 文件里面:

ar -rcs libstar.a moon.o sun.o earth.o

ar:打包封装命令   

封装静态库不需要链接

引用静态库:

(1)直接写 静态库文件的全称,会在当前目录找 libstar.a:

gcc -o poseidon poseidon.o libstar.a

(2)  -static 指定后面的库是静态库,然后使用 -l 参数 指定库名称:

gcc -v -o poseidon poseidon.o -static -lstar

4、封装静态库

在第三方静态库基础上加一些功能——省流:解压静态库,将.o文件重新打包

ar -x libstar.a
ar -rcs libpower.a moon.o sun.o earth.o dog.o pig.o

5、编译动态库 

eg:

 g++ -fPIC -c name.cpp
 g++ -fPIC -c age.cpp
 g++ -fPIC -c hobby.cpp
 g++ -fPIC -c logan.cpp
 g++ -fPIC -shared -o libintro.so name.o age.o logan.o hobby.o

 -fPIC 是编译选项,PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码。

链接动态库:

g++ -o hello hello.o libintro.so

配置加载动态库路径:

(1) 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

(2) 运行sudo ldconfig ,该命令会重建/etc/ld.so.cache文件

(3)将动态库文件移动到/usr/lib下

6、显式使用动态库(这个感觉不重要)

参考:

Linux环境显式使用动态库—编译链接基础知识 · FFmpeg原理 (xianwaizhiyin.net)

7、封装静态库为动态库

省流:解压再编译

8、混合使用动态库 静态库 

在一些使用第三方动态库和第四方静态库的场景下——省流:复杂,看不懂

项目中通用做法:cpp 编译 .o, 一个目录或一个库生成*.a, 在把所有a链接成可执行的二进制的文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值