静态库与动态库的构建(含具体代码可以实操)

简介: 静态库与动态库的构建(含具体代码可以实操)

程序编译顺序

程序编译需要通过调用

  • 预处理器
  • main.c->main.i
    指令:gcc -E main.c -o main.i
    作用:#define删除、展开宏、处理带#的条件编译指令、条件语句中符合条件的会保留,不符合的会删除,插入include、删除注释、添加行号文件指示
  • 编译器
  • main.i->main.s
    指令:gcc -S main.i -o main.s
    **作用:**把高级语言编译成机器可识别的汇编语言
  • 汇编器
  • main.s->main.o
    指令:gcc -c main.s -o main.o
    **作用:**将汇编文件生成二进制文件(可重定位目标文件)
  • 链接器
  • main.o与其依赖的可重定位目标文件链接起来生成可执行目标文件
    **作用:**链接器把目标文件与所需要的附加的目标文件(如静态链接库、动态链接库)

静态库

编译器提供一种机制,将所有相关的目标模块打包成为一个单独的文件称为静态库。

链接器构造一个输出的可执行文件时,它只复制静态库里被应用程序引用的目标模块

静态库被提出之前用过的方法

  • 让编译器辨认出对标准函数的调用,并直接生成相应的代码
  • 缺点:
    增加了编译器的复杂性
    每次修改一个标准函数时就需要一个新的编译器版本
  • 将所有标准c函数都放在一个单独的可重定位目标模块
  • 缺点:
    每个正在运行的程序都将这些函数的副本放在内存中,极大的浪费了内存。
  • 为每个标准函数创建一个独立的可重定位文件,把他们放在一个大家都知道的目录中。
  • 缺点:
    要求程序员显式的链接合适的目标模块到他们的可执行文件中,这是一个容易出错且耗时的过程。

构建静态库

目录结构

.
├── stlib
│   ├── StaticMath.cpp
│   └── StaticMath.h
└── test
    └── staticmathtest.cpp

stlib下构建

> g++ -c StaticMath.cpp  # 生成可重定位目标文件StaticMath.o
> ar -crv libstaticmath.a StaticMath.o  # 打包

test下链接

# 使用
> g++ -c staticmathtest.cpp -I../stlib/
> g++ -static -o proc staticmathtest.o -L../stlib/ -lstaticmath
  • -L去哪个目录下找-l下的什么文件
  • 这里是去父目录的stliblibstaticmath.a文件
  • 参数说明:要做一般都放在相同目录
  • -L:表示要连接的库所在目录
  • -I./stlib/ 表示指定头文件的目录为父目录下的stlib目录
  • -l(小写L):指定链接时需要的库,去掉前缀和后缀

最后执行即可

> ./proc

注意点

如果依赖的静态库之间不是独立的则需要对他们的调用顺序排序

例如:

foo.c调用libx.alibz.a的函数,而这两个库有调用liby.a中的函数,那么libx.alibz.a必须出现在liby.a之前

> gcc foo.c libx.a libz.a libx.a

静态库的缺点

静态库将显式的将他们的程序与更新了的库重新连接,并且这些代码都会被复制到每个运行进程的文本段。

动态库

所有引用该库的可执行目标文件共享这个.so文件中的代码和数据,而不是像静态库的内容那样被复制和嵌入到引用他们的可执行文件中

动态库构建

目录结构

.
├── dylib
│   ├── DynamicMath.cpp
│   └── DynamicMath.h
└── test
    └── dynamcimathtest.cpp

dylib目录下构建

> g++ -c -fPIC -c DynamicMath.cpp
> g++ -shared -o libdynamicmath.so DynamicMath.o

现在就有了一个libdynamicmath.so动态库

test目录下链接

  • 汇编得到可重定位目标文件
> g++ -c dynamcimathtest.cpp -I../dylib
  • 链接器链接
> g++ -o proc dynamcimathtest.o -L../dylib -ldynamicmath
  • 然后将这个库放在/usr/lib/或者/lib/下则ld就默认能够找到
sudo cp ../dylib/libdynamicmath.so /lib/
  • 如果放在其他目录则可以添加到/etc/ld.so.cache文件然后ldconfig即可
./proc

上述代码结构我放在github上可以下载下来试一试

luopanforever/static_dynamic_learn (github.com)

相关文章
|
6月前
|
开发工具 iOS开发
制作传统动态库和静态库遇到的问题
制作传统动态库和静态库遇到的问题
40 1
|
6月前
|
C语言 C++
win32编程 -- 编写静态库空项目
win32编程 -- 编写静态库空项目
32 0
|
程序员 vr&ar C语言
C/C++静态库和动态库的制作、使用、优缺点
C/C++静态库和动态库的制作、使用、优缺点
215 0
|
C语言
静态库与动态库的构建(含具体代码可以实操)
静态库与动态库的构建(含具体代码可以实操)
113 0
|
存储 自然语言处理 IDE
【C进阶】——我们写的代码是如何一步步变成可执行程序(.EXE)的?
【C进阶】——我们写的代码是如何一步步变成可执行程序(.EXE)的?
635 0
|
自然语言处理 编译器 Linux
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(二)
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解
572 0
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(二)
|
存储 Ubuntu Unix
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(一)
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解
359 0
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(一)
|
NoSQL 编译器 Linux
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(三)
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解
309 0
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(三)
|
存储 Linux 编译器
【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库(一)
【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库
275 0
【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库(一)
|
Linux Shell 编译器
【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库(二)
【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库
389 0
【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库(二)