2024年最新GCC 编译 C(C++)静态链接库(gcc -L、gcc -l)和动态链接库,2024年最新我先收藏为敬

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

将源文件打包为静态链接库的过程很简单,只需经历以下 2 个步骤:

  1. 将所有指定的源文件,都编译成相应的目标文件
wohu@ubuntu:~/cpp/src$ g++ -c greeting.cpp  name.cpp 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

  1. 然后使用 ar 压缩指令,将生成的目标文件打包成静态链接库,其基本格式如下:
ar rcs 静态链接库名称 目标文件1 目标文件2 ...

有关 ar 打包压缩指令,以及 rcs 各选项的含义和功能,请参考 Linux ar命令

重点说明的是,静态链接库的不能随意起名,需遵循如下的命名规则:

libxxx.a

  • Linux 系统下,静态链接库的后缀名为 .a
  • Windows 系统下,静态链接库的后缀名为 .lib

其中,xxx 代指我们为该库起的名字,比如 Linux 系统自带的一些静态链接库名称为 libc.alibgcc.alibm.a,它们的名称分别为 cgccm

下面,将 greeting.oname.o 打包到一个静态链接库中:

wohu@ubuntu:~/cpp/src$ ar rcs libmyfunction.a name.o greeting.o 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

其中,libmyfunction.a 就是 name.ogreeting.o 一起打包生成的静态链接库,myfunction 是我们自定义的库名。

2.2 使用静态链接库

静态链接库的使用很简单,就是在程序的链接阶段,将静态链接库和其他目标文件一起执行链接操作,从而生成可执行文件。

以前面代码为例,首先我们将 main.cpp 文件编译为目标文件:

wohu@ubuntu:~/cpp/src$ g++ -c main.cpp 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  main.o  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

在此基础上,我们可以直接执行如下命令,即可完成链接操作:

wohu@ubuntu:~/cpp/src$ g++ -static main.o libmyfunction.a 
wohu@ubuntu:~/cpp/src$ ls
a.out  function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  main.o  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

其中,-static 选项强制 GCC 编译器使用静态链接库。

注意,如果 GCC 编译器提示无法找到 libmyfunction.a,还可以使用如下方式完成链接操作:

wohu@ubuntu:~/cpp/src$ g++ -static main.o -L /home/wohu/cpp/src -lmyfunction
wohu@ubuntu:~/cpp/src$ ls
a.out  function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  main.o  name.cpp  name.o

其中,

  • -L(大写的 L)选项用于向 GCC 编译器指明静态链接库的存储位置(可以借助 pwd 指令查看具体的存储位置);
  • -l(小写的 L)选项用于指明所需静态链接库的名称,注意这里的名称指的是 xxx 部分,且建议将 -lxxx 直接连用(即 -lxxx),中间不需有空格。

由此,就生成了 a.out 可执行文件:

wohu@ubuntu:~/cpp/src$ ./a.out 
hello,world
My name is wohu
wohu@ubuntu:~/cpp/src$ 

3. 动态链接库

动态链接库,又称为共享链接库。和静态链接库不同,采用动态链接库实现链接操作时,程序文件中哪里需要库文件的功能模块,GCC 编译器不会直接将该功能模块的代码拷贝到文件中,而是将功能模块的位置信息记录到文件中,直接生成可执行文件。

显然,这样生成的可执行文件是无法独立运行的。采用动态链接库生成的可执行文件运行时,GCC 编译器会将对应的动态链接库一同加载在内存中,由于可执行文件中事先记录了所需功能模块的位置信息,所以在现有动态链接库的支持下,也可以成功运行。

采用动态链接库实现程序的连接操作,其优势和劣势恰好和静态链接库相反:

  • 优势是,由于可执行文件中记录的是功能模块的地址,真正的实现代码会在程序运行时被载入内存,这意味着,即便功能模块被调用多次,使用的都是同一份实现代码(这也是将动态链接库称为共享链接库的原因)。
  • 劣势是,此方式生成的可执行文件无法独立运行,必须借助相应的库文件(可移植性差)。

和使用静态链接库生成的可执行文件相比,动态链接库生成的可执行文件的体积更小,因为其内部不会被复制一堆冗余的代码。

  • Linux 发行版系统中,动态链接库的后缀名通常用 .so 表示;
  • Windows 系统中,动态链接库的后缀名为 .dll

GCC 编译器生成可执行文件时,默认情况下会优先使用动态链接库实现链接操作,除非当前系统环境中没有程序文件所需要的动态链接库,GCC 编译器才会选择相应的静态链接库。如果两种都没有(或者 GCC 编译器未找到),则链接失败。

3.1 创建动态链接库

总的来说,动态链接库的创建方式有 2 种。

  1. 直接使用源文件创建动态链接库,采用 gcc 命令实现的基本格式如下:
gcc -fpic -shared 源文件名... -o 动态链接库名

其中,

  • -shared 选项用于生成动态链接库;
  • -fpic(还可写成 -fPIC)选项的功能是,令 GCC 编译器生成动态链接库(多个目标文件的压缩包)时,表示各目标文件中函数、类等功能模块的地址使用相对地址,而非绝对地址。这样,无论将来链接库被加载到内存的什么位置,都可以正常使用。

例如,将前面项目中的 greeting.cppname.cpp 这 2 个源文件生成一个动态链接库,执行命令为:

wohu@ubuntu:~/cpp/src$ g++ -fPIC -shared name.cpp  greeting.cpp  -o libmyfunction.so 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  libmyfunction.a  libmyfunction.so  main.cpp  name.cpp
wohu@ubuntu:~/cpp/src$ 

注意,动态链接库的命名规则和静态链接库完全相同,只不过在 Linux 发行版系统中,其后缀名用 .so 表示;Windows 系统中,后缀名为 .dll

  1. 先使用 gcc -c 指令将指定源文件编译为目标文件,再由目标文件生成动态链接库

注意,为了后续生成动态链接库并能正常使用,将源文件编译为目标文件时,也需要使用 -fpic 选项。

wohu@ubuntu:~/cpp/src$ g++ -c -fPIC name.cpp greeting.cpp  
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

在此基础上,接下来利用上一步生成的目标文件,生成动态链接库:

wohu@ubuntu:~/cpp/src$ g++ -shared greeting.o name.o -o libmyfunction.so
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  libmyfunction.so  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

3.2 使用动态链接库

通过前面章节的学习我们知道,动态链接库的使用场景就是和项目中其它源文件或目标文件一起参与链接。以前面例子为例,前面我们将 greeting.cppname.cpp 打包到了 libmyfunction.so 动态链接库中,此时该项目中仅剩 main.cpp 源程序文件,因此执行 demo 项目也就演变成了将 main.cpplibmyfunction.so 进行链接,进而生成可执行文件。

注意,function.h 头文件并不直接参与编译,因为在程序的预处理阶段,已经对项目中需要用到的头文件做了处理。

执行如下指令,即可借助动态链接库成功生成可执行文件:

wohu@ubuntu:~/cpp/src$ g++ main.cpp  libmyfunction.so -o main
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  libmyfunction.so  main  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

注意,生成的可执行文件 main 通常无法直接执行,例如:

wohu@ubuntu:~/cpp/src$ ./main 
./main: error while loading shared libraries: libmyfunction.so: cannot open shared object file: No such file or directory
wohu@ubuntu:~/cpp/src$ 

可以看到,执行过程中无法找到 libmyfunction.so 动态链接库。通过执行 ldd main 指令,可以查看当前文件在执行时需要用到的所有动态链接库,以及各个库文件的存储位置:

wohu@ubuntu:~/cpp/src$ ldd main 
        linux-vdso.so.1 =>  (0x00007fffb17ea000)
        libmyfunction.so => not found
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f548673a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5486370000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5486067000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5486abc000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5485e51000)
wohu@ubuntu:~/cpp/src$ 

可以看到,main 文件的执行需要 7 个动态链接库的支持,其中就包括 libmyfunction.so,但该文件无法找到,因此 main 执行会失败。

运行由动态链接库生成的可执行文件时,必须确保程序在运行时可以找到这个动态链接库。常用的解决方案有如下几种:

  • 将链接库文件移动到标准库目录下(例如 /usr/lib/usr/lib64/lib/lib64);
  • 在终端输入
export LD_LIBRARY_PATH=$LD\_LIBRARY\_PATH:xxx

其中 xxx 为动态链接库文件的绝对存储路径(此方式仅在当前终端有效,关闭终端后无效);

  • 修改 ~/.bashrc~/.bash_profile 文件,即在文件最后一行添加
export LD_LIBRARY_PATH=$LD\_LIBRARY\_PATH:xxx


**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/9b422d242eac983836abafc3fd1b9938.png)
![img](https://img-blog.csdnimg.cn/img_convert/aa5e71e6a4aedfdc352ddda3987f34b5.png)

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
[外链图片转存中...(img-9WhOl34L-1715639957795)]
[外链图片转存中...(img-MQ4U0Mln-1715639957796)]

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值