编译生成动态库时,被关联的静态库会被编译到动态库里面

合集下载

静态链接与动态链接:理解不同链接方式的原理与应用

静态链接与动态链接:理解不同链接方式的原理与应用

静态链接与动态链接:理解不同链接方式的原理与应用静态链接和动态链接是计算机软件开发中常用的两种链接方式。

静态链接是将编译后的目标文件与其他源文件中的代码拼接在一起,生成一个完整的可执行文件。

而动态链接是在程序运行时,通过动态链接库(Dynamic Link Library,简称DLL)将所需的函数和资源加载到内存中。

本文将从原理和应用两个方面进行详细介绍。

一、静态链接的原理与应用静态链接是将目标文件和库文件在编译时将所有代码链接成一个单独的可执行文件。

它的原理是在编译时将所有被调用的函数和数据区域的物理地址固定下来,程序运行时不再需要链接库文件。

静态链接的主要优点是程序运行时不需要依赖外部库文件,便于程序的分发和部署。

但缺点是会引入冗余代码,造成可执行文件体积较大,并且更新或修改库文件时需要重新编译整个程序。

静态链接的应用非常广泛。

在Windows操作系统中,常见的静态链接库是.lib文件,如kernel32.lib、user32.lib等。

在Linux系统中,常见的静态链接库是.a文件,如libc.a、libm.a等。

静态链接库可以直接在编译时链接到目标文件中,使用起来非常方便。

二、动态链接的原理与应用动态链接是在程序运行时,将程序所需的函数和资源从动态链接库中加载到内存中。

它的原理是通过操作系统提供的动态链接库加载机制,在程序启动时将动态链接库中的函数和变量绑定到程序中,程序运行过程中通过动态链接库提供的接口来调用函数和使用资源。

动态链接的主要优点是可以节约内存空间,多个程序可以共享同一个动态链接库,同时也便于动态库的更新和升级。

但缺点是程序运行时需要依赖外部的动态链接库,如果动态链接库缺失或版本不兼容,程序会无法正常运行。

动态链接在操作系统中得到了广泛应用。

在Windows系统中,常见的动态链接库是.dll文件,如user32.dll、kernel32.dll等。

在Linux系统中,常见的动态链接库是.so文件,如libc.so、libm.so 等。

静态库和动态库编译

静态库和动态库编译

静态库和动态库编译静态库和动态库是编程中常用的两种库文件形式,本文将介绍它们的编译过程和使用方法。

1. 静态库编译静态库是一种在编译时被链接到程序中的库文件,它包含了程序所依赖的所有函数和数据结构,因此程序在运行时不需要再加载库文件。

静态库的编译过程包括以下步骤:(1)创建一个或多个源文件,使用编译器将它们编译成目标文件(.o 或 .obj)。

(2)将多个目标文件打包成一个静态库文件,通常使用 ar 工具完成此操作。

例如,在 Linux 系统下,可以使用以下命令创建名为 libfoo.a 的静态库文件:$ ar rcs libfoo.a foo1.o foo2.o ...其中,rcs 参数分别表示创建、向库文件中添加目标文件和生成索引表。

(3)在编译器中使用静态库,需要将其链接到目标程序中。

在Linux 系统下,可以使用以下命令编译名为 main.c 的源文件和名为libfoo.a 的静态库文件:$ gcc -o main main.c -L. -lfoo其中,-L 参数指定库文件搜索路径,. 表示当前目录;-l 参数指定链接库文件,实际上是将其前缀 lib 和后缀 .a 去掉,即 foo。

2. 动态库编译动态库是一种在程序运行时动态加载的库文件,它只包含程序所需要的部分函数和数据结构,因此可以减小程序的尺寸和加载时间。

动态库的编译过程包括以下步骤:(1)创建一个或多个源文件,使用编译器将它们编译成目标文件。

(2)将多个目标文件打包成一个共享库文件,通常使用 ld 或链接器完成此操作。

例如,在 Linux 系统下,可以使用以下命令创建名为 libfoo.so 的动态库文件:$ gcc -shared -o libfoo.so foo1.o foo2.o ...其中,-shared 参数表示生成共享库文件。

(3)在编译器中使用动态库,需要将其链接到目标程序中。

在Linux 系统下,可以使用以下命令编译名为 main.c 的源文件和名为libfoo.so 的动态库文件:$ gcc -o main main.c -L. -lfoo其中,-L 和 -l 参数的含义同静态库。

静态库的调用方法

静态库的调用方法

静态库的调用方法静态库是一种在编译时将代码和函数打包成一个文件的库文件,它包含了可被程序调用的函数、数据和其他资源。

与之对应的是动态库,动态库在程序运行时才被加载,而静态库在编译时就被链接到可执行文件中。

静态库的调用方法主要分为以下几个步骤:1. 创建静态库:首先需要创建一个静态库,静态库通常是通过编译源代码并将其打包成一个.a文件的方式创建的。

在一些开发环境中,可以使用特定的命令来创建静态库,比如使用gcc或g++编译源码并使用ar命令将多个对象文件打包成静态库。

2. 导入静态库:在使用这个静态库的项目中,需要将这个静态库导入到项目中。

通常有两种方式来导入静态库。

一种是将静态库复制到项目的目录中,然后在项目文件中设置相关的路径以便编译器可以找到这个静态库。

另一种方式是在项目文件中设置相关的路径,使得编译器能够找到这个静态库的存放位置。

3. 引入头文件:在使用静态库的项目中,需要引入静态库的头文件,以便在项目中使用静态库中定义的函数和数据结构。

头文件通常可以通过#include语句来引入,具体的语句形式为#include "header.h",其中header.h是静态库中包含的头文件。

4. 编写代码:在项目中可以直接调用静态库中定义的函数和使用静态库中定义的数据结构。

具体的调用方式和使用方法可以参考静态库的文档或者示例代码。

在编写代码的过程中,可能需要包括静态库的头文件,调用静态库中的函数,以及使用静态库中的数据结构。

5. 编译链接:在编译项目时,需要设置编译选项和链接选项,以便编译器可以找到和链接静态库。

其中编译选项可以通过编译器的命令行参数或IDE的设置来指定。

链接选项通常包括静态库的路径和静态库的文件名。

6. 编译运行:在完成编译和链接后,可以运行生成的可执行文件来测试静态库的调用效果。

执行文件会调用静态库中的函数和使用静态库中的数据结构,从而实现特定的功能。

总结来说,静态库的调用方法主要包括创建静态库、导入静态库、引入头文件、编写代码、编译链接和编译运行这几个步骤。

linux动态库和静态库调用方法

linux动态库和静态库调用方法

linux动态库和静态库调用方法
在Linux操作系统中,动态库和静态库的调用方法如下:
1. 动态库(Shared Library):动态库在程序运行时被载入内存,可以被多个程序同时使用,节省内存空间。

在Linux中,动态库一般存放在/usr/lib或/lib目录下。

调用方法:在程序中使用extern "C"来声明函数接口,然后通过dlopen(), dlsym()等函数来动态调用动态库中的函数。

2. 静态库(Static Library):静态库在程序编译时被包含进可执行程序中,每个程序都有一份自己的库副本。

静态库一般存放在/usr/lib或/lib目录下。

调用方法:在程序中直接使用静态库中的函数,不需要额外的调用方法。

只需要在编译时使用"-l"选项指定要链接的库名,例如"gcc -o test test.c -lmylib"。

需要注意的是,对于动态库和静态库的使用,一般建议优先使用动态库,因为这样可以节省内存空间,并且可以在不停止程序运行的情况下更新库文件。

第1页/ 共1页。

Linux下Makefile中动态链接库和静态链接库的生成与调用

Linux下Makefile中动态链接库和静态链接库的生成与调用

Linux下Makefile中动态链接库和静态链接库的⽣成与调⽤Linux下Makefile中动态链接库和静态链接库的⽣成与调⽤ 背景:写这篇博客的原因是:最近在搞嵌⼊式,需要交叉编译opencv库⽂件,⾃⼰写Makefile,通过arm-linux-g++编译、链接、⽣成可执⾏⽂件,从⽽实现了移植的过程。

平台是Toradex的Apalis TK1,三千多元,买回来我就后悔了,全是英⽂资料,还各种Bug,迟迟⽆法上⼿。

早知如此,还不如直接买Nvidia的Jetson TK1呢。

书归正传,今天写⼀下Makefile⽂件中,动态链接库和静态链接库的⽣成与调⽤。

⼀、概念 动态链接库:是⼀种不可执⾏的⼆进制程序⽂件,它允许程序共享执⾏特殊任务所必需的代码和其他资源。

Windows平台上动态链接库的后缀名是”.dll”,Linux平台上的后缀名是“.so”。

Linux上动态库⼀般是libxxx.so;相对于静态函数库,动态函数库在编译的时候并没有被编译进⽬标代码中,你的程序执⾏到相关函数时才调⽤该函数库⾥的相应函数,因此动态函数库所产⽣的可执⾏⽂件⽐较⼩。

由于函数库没有被整合进你的程序,⽽是程序运⾏时动态的申请并调⽤,所以程序的运⾏环境中必须提供相应的库。

动态函数库的改变并不影响你的程序,所以动态函数库的升级⽐较⽅便。

静态链接库:这类库的名字⼀般是libxxx.a;利⽤静态函数库编译成的⽂件⽐较⼤,因为整个函数库的所有数据都会被整合进⽬标代码中,他的优点就显⽽易见了,即编译后的执⾏程序不需要外部的函数库⽀持,因为所有使⽤的函数都已经被编译进去了。

当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

Makefile:利⽤IDE开发调试的⼈员可能对Makefile不⼤理解,其实Makefile就是完成了IDE中的编译、链接、⽣成等⼯作,并遵循shell脚本中变量定义与调⽤的规则。

⼆、编写Makefile实现编译与链接1、准备⽂件 我们写⼀个简单的⼯程吧,此⼯程包含3个⽂件,分别是main.cpp,func.cpp和func.h。

gcc -fPIC编译选项分析

gcc -fPIC编译选项分析

gcc -fPIC编译选项分析1、-fPIC 作用于编译阶段,在编译动态库时(.so文件)告诉编译器产生与位置无关代码(Position-Independent Code),若未指定-fPIC选项编译.so文件,则在加载动态库时需进行重定向。

2、64位编译器下编译生成动态库时,出现以下错误:/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-li nux/bin/ld: ../../CI/script/server/lib/libz.a(adler32.o): relocation R_X86_64_32 against `.text' can not be used when making a shared object; recompile with -fPIC../../CI/script/server/lib/libz.a: could not read symbols: Bad value原因:提示说需要-fPIC编译,然后在链接动态库的地方加上-fPIC的参数编译结果还是报错,需要把共享库所用到的所有静态库都采用-fPIC编译一遍,才可以成功的在64位环境下编译出动态库。

3、为何在32位的编译器下编译,就不会报错呢?对于我们的32位环境来说, 编译时是否加上-fPIC, 都不会对链接产生影响, 只是一份代码的在内存中有几个副本的问题(而且对于静态库而言结果都是一样的).但在64位的环境下装载时重定位的方式存在一个问题就是在我们的64位环境下用来进行位置偏移定位的cpu指令只支持32位的偏移, 但实际中位置的偏移是完全可能超过64位的,所以在这种情况下编译器要求用户必须采用fPIC的方式进行编译的程序才可以在共享库中使用。

静态链接与动态链接的区别

静态链接与动态链接的区别

静态链接与动态链接的区别动态链接库、静态库、import库区别动态链接库(Dynamic Linked Library): Windows为应⽤程序提供了丰富的函数调⽤,这些函数调⽤都包含在动态链接库中。

其中有3个最重要的DLL,Kernel32.dll,它包含⽤于管理内存、进程和线程的各个函数;User32.dll,它包含⽤于执⾏⽤户界⾯任务(如窗⼝的创建和消息的传送)的各个函数;GDI32.dll,它包含⽤于画图和显⽰⽂本的各个函数。

静态库(Static Library):函数和数据被编译进⼀个⼆进制⽂件(通常扩展名为.LIB)。

在使⽤静态库的情况下,在编译链接可执⾏⽂件时,链接器从库中复制这些函数和数据并把它们和应⽤程序的其它模块组合起来创建最终的可执⾏⽂件(.EXE⽂件)。

导⼊库(Import Library):在使⽤动态链接库的时候,往往提供两个⽂件:⼀个引⼊库和⼀个DLL。

引⼊库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。

在编译链接可执⾏⽂件时,只需要链接引⼊库,DLL中的函数代码和数据并不复制到可执⾏⽂件中,在运⾏的时候,再去加载DLL,访问DLL中导出的函数。

在运⾏Windows程序时,它通过⼀个被称作“动态链接”的进程与Windows相接。

⼀个Windows的.EXE⽂件拥有它使⽤不同动态链接库的引⽤,所使⽤的函数即在那⾥。

当Windows程序被加载到内存中时,程序中的调⽤被指向DLL函数的⼊⼝,如果DLL不在内存中,系统就将其加载到内存中。

当链接Windows程序以产⽣⼀个可执⾏⽂件时,你必须链接由编程环境提供的专门的“导⼊库(import library)库”。

这些导⼊库包含了动态链接库名称和所有Windows函数调⽤的引⽤信息。

链接程序使⽤该信息在.EXE⽂件中构造⼀个表,当加载程序时,Windows使⽤它将调⽤转换为Windows函数。

静态库与导⼊库的区别:导⼊库和静态库的区别很⼤,他们实质是不⼀样的东西。

c语言链接原理

c语言链接原理

c语言链接原理C语言链接原理什么是链接链接是将多个源文件组合成一个可执行的程序的过程。

在C语言中,链接分为静态链接和动态链接两种方式。

静态链接静态链接是在编译时将所有源文件和依赖的库文件打包合并为一个可执行文件。

在静态链接的过程中,会将所有被调用的函数和符号解析成绝对地址,并进行地址重定位,以便在程序运行时能正确找到对应的函数或变量。

静态链接的好处是,可执行文件独立,不依赖于外部的库文件,可以方便地在不同操作系统或机器上进行传输和运行。

但同时,也会使得可执行文件的大小变大,并且无法共享已被其他程序加载的库文件。

动态链接动态链接是在程序运行时,将程序所需要的库文件动态加载到内存中,并建立起调用关系。

相比于静态链接,动态链接的主要优势在于节省了磁盘空间,同时可以方便地共享已加载的库文件。

在动态链接的过程中,程序除了需要链接器的支持外,还需要动态链接器或运行时链接器(如)的支持。

动态链接器会根据程序中对函数和符号的引用,到指定的共享库文件中查找对应的函数或变量地址,并进行重定位。

这种方式需要在程序运行时动态解析符号地址,因此速度可能比静态链接慢一些。

符号解析在链接的过程中,一个非常重要的步骤就是符号解析。

符号解析是将函数名或变量名与其对应的地址进行关联的过程。

在C语言中,通过extern关键字来声明外部变量或函数。

在链接时,链接器会根据这些声明找到对应的定义,并确定其地址。

符号解析的过程是由链接器完成的,它会先查找目标文件中是否存在该符号的定义,如果存在则将其地址记录下来,否则会继续在其他目标文件或库文件中进行查找。

如果所有的目标文件和库文件都没有找到符号的定义,链接器将会报链接错误。

链接顺序在进行静态链接时,链接器需要按照一定的顺序来合并多个目标文件和库文件。

常见的链接顺序是从左到右,从上到下。

这个顺序决定了符号解析的优先级,后面的文件中的符号会覆盖前面的文件中的同名符号。

如果出现了重复定义符号的情况,链接器会报重复定义的错误。

头文件和库文件-静态库和动态库

头文件和库文件-静态库和动态库

头⽂件和库⽂件-静态库和动态库⼀、头⽂件和库⽂件头⽂件提供声明,库⽂件提供定义/实现。

C代码的编译过程: 预处理(需要头⽂件) -> 编译 -> 汇编 -> 链接(需要库⽂件); 执⾏时可能还有动态链接过程。

编译的时候,只要有头⽂件中的声明就⾜够了。

在链接的时候,把已经编译好的.obj和现有的.lib⽂件进⾏链接,这时就可以最终⽣成可执⾏⽂件了。

其实头⽂件与其实现⽂件或相应lib⽂件都没有直接的联系。

头⽂件是告诉编译器函数是如何去调⽤如何返回的,所有实现都是分别编译,最后在链接阶段链在⼀起。

头⽂件包含声明, 库⽂件包含实现或者与DLL库的连接所以,如果在代码⾥要⽤到这些函数那么就要包含头⽂件,编译的时候才能知道这些函数的原形;在进⾏代码连接的时候就需要库⽂件了,这时连接器就把函数的实现代码(静态库)连接到你的程序或者将你的函数调⽤连接到相应的DLL的对应函数(动态库)lib是静态库, 编译的时候代码直接插⼊到你的程序 ,DLL是动态库,编译的时候,只是产⽣⼀些调⽤DLL内代码的导⼊表,真正运⾏的时候是调⽤的DLL内的代码。

总结起来就是,库⽂件通过头⽂件向外导出接⼝。

⽤户通过头⽂件找到库⽂件中函数实现的代码从⽽把这段代码链接到⽤户程序中去。

.a代表传统的静态函数库(也称作归档⽂件:archive).so代表共享函数库⼆、创建静态库⽂件:1.创建源⽂件willku1.c和willku2.c2.编译源⽂件⽣成.o⽂件(将要包含在库⽂件中的⽬标⽂件)gcc -c willku1.c willku2.c =>willku1.o willku2.o3.创建头⽂件ishead.h内容:void willku1(char *);void willku2(int);4.创建应⽤程序app.c(将调⽤willku2.c⽂件)#include "ishead.h"5.编译、测试应⽤程序app.cgcc -c app.cgcc -o app app.o willku2.o./app6.创建并使⽤库⽂件(.a),使⽤ar创建归档⽂件并将⽬标⽂件加进去。

linux下静态链接库和动态链接库编译和使用

linux下静态链接库和动态链接库编译和使用

Linux 下编译链接动静态库2010年03月29日星期一 17:11Linux 版本是 Red Hat 9 ,内核版本是 2.4.18输入 which gcc 查看 gcc 的位置在 /usr/bin/gccgcc -v 查看 gcc 编译前的配置信息--prefix=/usr 说明了安装目录没有 --with-headers 说明默认的 include 就在安装目录下所以 gcc 默认的 include 目录是 /usr/include ,要包含另一个目录,可以用 -I dir 选项包含该目录,想要更方便的可以在 /etc/profile 中添加一个环境变量 C_INCLUDE_PATHC_INCLUDE_PATH="your include path"export C_INCLUDE_PATHgcc 默认的 lib 目录很多,一般是 /lib 和 /usr/lib可以输入 gcc -print-search-dirs 查看同样可以在编译时通过 -L dir 来添加,也可以在 /etc/profile 中添加LD_LIBRARY_PATH="your ldlib path"export LD_LIBRARY_PATH还有就是可以/etc/ld.so.conf中添加目录,这对于安装别的库很方便当然修改了库文件后需要运行一下ldconfig自己制作交叉编译工具太复杂了,直接下一个arm-linux-gcc-3.4.1.tar.bz2 tar jxvf arm-linux-gcc-3.4.1.tar.bz2 -C / 解压缩到根目录下其实由于压缩包带的目录是 usr/local/arm/3.4.1所以实际还是在 /usr/local/arm/3.4.1 目录下在bin中可以看到各个工具 arm-linux-gcc ...输入 ./arm-linux-gcc -v 可以看到配置信息有 --with-headers=/usr/local/arm/3.4.1/arm-linux/include 说明了默认的include目录输入 ./arm-linux-gcc -print-search-dirs 查看搜索的 lib 目录,主要的库文件还是在/usr/local/arm/3.4.1/arm-linux/lib目录下.arm-linux-gcc 3.4.1 可以用来编译2.6的内核而编译bootloader还是用原来的2.95.2版的 arm-linux-gcc程序的预处理、编译、链接都可以由gcc完成,gcc会自动调用cpp来做预处理,ld来进行链接。

GCC编译使用动态链接库和静态链接库的方法

GCC编译使用动态链接库和静态链接库的方法

GCC编译使⽤动态链接库和静态链接库的⽅法根据链接时期的不同,库⼜有静态库和动态库之分。

静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以⽣成的可执⾏⽂件就不受库的影响了,即使库被删除了,程序依然可以成功运⾏。

有别于静态库,动态库的链接是在程序执⾏的时候被链接的。

所以,即使程序编译完,库仍须保留在系统上,以供程序运⾏时调⽤。

(TODO:链接动态库时链接阶段到底做了什么)链接静态库其实从某种意义上来说也是⼀种粘贴复制,只不过它操作的对象是⽬标代码⽽不是源码⽽已。

因为静态库被链接后库就直接嵌⼊可执⾏⽂件中了,这样就带来了两个问题。

⾸先就是系统空间被浪费了。

这是显⽽易见的,想象⼀下,如果多个程序链接了同⼀个库,则每⼀个⽣成的可执⾏⽂件就都会有⼀个库的副本,必然会浪费系统空间。

再者,⼈⾮圣贤,即使是精⼼调试的库,也难免会有错。

⼀旦发现了库中有bug,挽救起来就⽐较⿇烦了。

必须⼀⼀把链接该库的程序找出来,然后重新编译。

⽽动态库的出现正弥补了静态库的以上弊端。

因为动态库是在程序运⾏时被链接的,所以磁盘上只须保留⼀份副本,因此节约了磁盘空间。

如果发现了bug或要升级也很简单,只要⽤新的库把原来的替换掉就⾏了。

那么,是不是静态库就⼀⽆是处了呢?答⽈:⾮也⾮也。

不是有句话么:存在即是合理。

静态库既然没有湮没在滔滔的历史长河中,就必然有它的⽤武之地。

想象⼀下这样的情况:如果你⽤libpcap库编了⼀个程序,要给被⼈运⾏,⽽他的系统上没有装pcap库,该怎么解决呢?最简单的办法就是编译该程序时把所有要链接的库都链接它们的静态库,这样,就可以在别⼈的系统上直接运⾏该程序了。

所谓有得必有失,正因为动态库在程序运⾏时被链接,故程序的运⾏速度和链接静态库的版本相⽐必然会打折扣。

然⽽瑕不掩瑜,动态库的不⾜相对于它带来的好处在现今硬件下简直是微不⾜道的,所以链接程序在链接时⼀般是优先链接动态库的,除⾮⽤-static参数指定链接静态库。

关于静态链接库(Lib)与动态链接库(DLL)

关于静态链接库(Lib)与动态链接库(DLL)

关于静态链接库(Lib)与动态链接库(DLL)静态链接库(Lib)和动态链接库(DLL)的问题困扰了我很长时间,而当中关键的问题是两者有何联系?又有何区别呢?怎么创建?怎么使用?使用的过程中要注意什么?一直想把这个问题总结一下。

在windows下一般可以看到后缀为dll和后缀为lib的文件,但这两种文件可以分为三种库,分别是动态链接库(Dyna mic-Link Libraries),目标库(Object Li braries)和导入库(Import Libra ries),下面一一解释这三种库。

目标库(Object Li braries)目标库又叫静态链接库,是扩展名为.LIB的文件,包括了用户程序要用到的各种函数。

它在用户程序进行链接时,“静态链接”到可执行程序文件当中。

例如,在V C++中最常使用到的C运行时目标库文件就是LIB C.LIB。

在链接应用程序时常使用所谓“静态链接”的方法,即将各个目标文件(.obj)、运行时函数库(.lib)以及已编译的资源文件(.res)链接到一起,形成一个可执行文件(.exe)。

使用静态链接时,可执行文件需要使用的各种函数和资源都已包含到文件中。

这样做的缺点是对于多个程序都使用的相同函数和资源要重复链接到exe文件中,使程序变大、占用内存增加。

导入库(I mport Li braries)导入库是一种特殊形式的目标库文件形式。

和目标库文件一样,导入库文件的扩展名也是.LIB,也是在用户程序被链接时,被“静态链接”到可执行文件当中。

但是不同的是,导入库文件中并不包含有程序代码。

相应的,它包含了相关的链接信息,帮助应用程序在可执行文件中建立起正确的对应于动态链接库的重定向表。

比如KERNEL32.LIB、USER32.LIB和GDI32.LIB就是我们常用到的导入库,通过它们,我们就可以调用Windows提供的函数了。

如果我们在程序中使用到了Rec tangle这个函数,GDI32.LIB就可以告诉链接器,这个函数在GDI32.DLL动态链接库文件中。

动态库和静态库

动态库和静态库
使用共享库
gcc -o main -Ldir -ltest main.c
查看动态库
在库文件夹下,可以查看动态库文件的依赖 关系
#ldd libadd.so
在当前文件夹下可以查看可执行文件的信息
#file hello 可以看hello文件使用的是动态库
创建库示例
/*main.c*/ #include<stdio.h> main() { int x=5; int y=6; printf(“x+y=%d\n”,add(x,y)); }
共享库:编译时,只是在生成的可执行程序中简 单的指定需要使用的库函数信息,程序运行过程 中需要利用库函数。
动态库:共享库的一种变化形式,目前大多采用 共享库的方式。
函数库分类
也就是说: 静态库在程序编译时会被连接到目标代码中,程
序运行时将不再需要该静态库。 动态库在程序编译时并不会被连接到目标代码中,
创建库示例
/*add.c*/ add(int x,int y) { int result; result=x+y; return result; }
创建静态库示例
1. #gcc add.c -c -o add.o //生成一 个二进制内容的.o文件,只进行前三步编译
2. #ar -cr libadd.a add.o //静态库 生成了,而且文件名必须以lib开头
#LD_LIBRARY_PATH=$PWD #export LD_LIBRARY_PATH
编译时指定路径
#gcc -o cacul -Wl,-rpath,. -L -lalg caculation.c
3. #gcc main.c -L. –ladd -static o ok //把库文件和.o文件生成可执行文 件ok

gcc编译动态和静态链接库

gcc编译动态和静态链接库

gcc编译动态和静态链接库我们通常把一些公用函数制作成函数库,供其它程序使用。

函数库分为静态库和动态库两种。

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。

第1步:编辑得到举例的程序--hello.c和test.c;测试程序test.c调用了公用函数my_lib_function。

hello.c:#include <stdio.h>void my_lib_function(){printf("library routine called\n");}test.c:int main(){my_lib_function();return 0;}第2步:将hello.c编译成.o文件;无论静态库,还是动态库,都是由.o文件创建的(动态库可以直接通过.c)。

因此,我们必须将源程序hello.c通过gcc先编译成.o文件。

在系统提示符下键入以下命令得到hello.o文件。

# gcc -c hello.c第3步:由.o文件创建静态库;静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。

例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。

在创建和使用静态库时,需要注意这点。

创建静态库用ar命令。

在系统提示符下键入以下命令将创建静态库文件libmyhello.a。

# ar crv libmyhello.a hello.o第4步:在程序中使用静态库;静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。

动静态库的依赖关系

动静态库的依赖关系

动静态库的依赖关系一、动态库的依赖关系动态库(Dynamic Link Library,简称DLL)是一种在程序运行时才加载的库文件,它可以被多个程序共享使用。

在编译阶段,动态库并不会被直接链接到可执行文件中,而是在程序运行时动态加载到内存中。

动态库的依赖关系主要体现在两个方面:一是动态库之间的相互依赖关系,二是可执行文件与动态库之间的依赖关系。

1. 动态库之间的相互依赖关系在某些情况下,一个动态库可能会依赖于其他的动态库,这种依赖关系可以通过动态库的导入表来实现。

导入表中记录了动态库所依赖的其他动态库的名称和函数入口地址,程序在运行时会根据导入表来动态加载所需的依赖库。

2. 可执行文件与动态库之间的依赖关系可执行文件与动态库之间的依赖关系主要体现在链接阶段。

编译器在链接可执行文件时,会将可执行文件中使用到的动态库的信息(如库的名称、函数入口地址等)记录在可执行文件的导入表中。

在程序运行时,操作系统会根据导入表的信息来加载相应的动态库。

二、静态库的依赖关系静态库(Static Library)是在编译阶段被链接到可执行文件中的库文件。

静态库的依赖关系主要体现在可执行文件与静态库之间的链接关系。

1. 可执行文件与静态库之间的链接关系在编译可执行文件时,编译器会将使用到的静态库的代码复制到可执行文件中,使得可执行文件包含了静态库的全部代码。

因此,可执行文件与静态库之间的依赖关系是静态的,不需要在运行时动态加载。

2. 静态库之间的相互依赖关系静态库之间的相互依赖关系主要体现在链接阶段。

当一个静态库中使用到了其他的静态库时,编译器会将被使用的静态库的代码复制到当前的静态库中,使得当前的静态库包含了所有依赖的代码。

三、动态库和静态库的应用场景动态库和静态库各有其适用的场景和优势。

1. 动态库的应用场景动态库主要适用于需要共享代码的场景,它可以被多个程序共享使用,减少了代码的重复编译和内存占用。

动态库的更新和维护也更加方便,只需要替换动态库文件即可,无需重新编译可执行文件。

cmake文件编写规则中,用于生成静态链接库和动态库

cmake文件编写规则中,用于生成静态链接库和动态库

cmake文件编写规则中,用于生成静态链接库和动态库CMake是一个开源的跨平台构建工具,它使用简洁的语法来描述软件构建过程。

在CMake文件编写规则中,我们可以使用一些指令来生成静态链接库和动态库。

本文将以生动、全面、有指导意义的方式介绍如何编写CMake文件以生成静态链接库和动态库。

一、生成静态链接库静态链接库是在编译时将库的代码直接嵌入到可执行文件中的库文件。

下面是生成静态链接库的CMake代码示例:```设置库名称set(LIB_NAME my_static_library)设置源文件列表set(SRC_FILESfile1.cppfile2.cpp)生成静态链接库add_library(${LIB_NAME} STATIC ${SRC_FILES})```上述代码中,首先需要设置库的名称(LIB_NAME),然后指定源文件的列表(SRC_FILES)。

最后,使用add_library命令来生成静态链接库。

二、生成动态库动态库是在运行时加载的库文件,它与可执行文件分开存储。

下面是生成动态库的CMake代码示例:```设置库名称set(LIB_NAME my_dynamic_library)设置源文件列表set(SRC_FILESfile1.cppfile2.cpp)生成动态库add_library(${LIB_NAME} SHARED ${SRC_FILES})```同样,我们需要设置库的名称(LIB_NAME)和源文件的列表(SRC_FILES)。

使用add_library命令,指定库类型为SHARED,就可以生成动态库了。

三、区分不同平台的库生成CMake可以根据不同平台来生成对应的库文件。

下面是一个区分不同平台的CMake代码示例:```设置库名称set(LIB_NAME my_library)设置源文件列表set(SRC_FILESfile1.cppfile2.cpp)判断平台类型if(WIN32)# 生成Windows平台的库add_library(${LIB_NAME} STATIC ${SRC_FILES})elseif(UNIX)# 生成UNIX平台(Linux、Mac等)的库add_library(${LIB_NAME} SHARED ${SRC_FILES})endif()```在上述代码中,我们使用if语句来判断当前的平台类型。

gcc中动态库和静态库的链接顺序

gcc中动态库和静态库的链接顺序

gcc中动态库和静态库的链接顺序so⽂件:动态库a⽂件:静态库exe⽂件:可执⾏程序(linux下以⽂件属性来标⽰是否是可执⾏⽂件,与后缀名⽆关)经过⾃⼰写的⼀些测试程序,⼤致了解了下gcc中链接顺序问题,总结出以下⼏点:1,动态库中可以包含另⼀个静态库,通过参数 -lxxx 把静态库libxxx.a加⼊so⽂件中,这样so⽂件中就包含了libxxx.a的所有实现。

当然,如果不包含libxxx.a也没有问题,这样⽣成的so会⼩⼀点。

如果不包含libxxx.a,最终使⽤这个so的可执⾏⽂件,在其⽣成时必须加⼊ -lxxx。

2, 2个so⽂件可以包含同⼀个静态库libxxx.a,最终⽣成exe⽂件时,不会产⽣冲突。

更⼴泛的说,⽣成exe⽂件时候,可以链接多个so⽂件和a⽂件,如果其中的a⽂件有多份实现,最终只会有⼀份⽣效,其他都会被忽略。

不⽤担⼼冲突。

3,当⽣成exe时候,当a⽂件有多份实现时,最左边指定的a⽂件才⽣效。

具体例⼦来说:libstatic.a :⼀个静态库⽂件libdynamic1.so:需要使⽤libstatic.a中的函数,但是没有包含libstatic.alibdynamic2.so:需要使⽤libstatic.a中的函数,包含libstatic.alibdynamic3.so:需要使⽤libstatic.a中的函数,也包含libstatic.atest.exe:最终的⽣成的可执⾏⽂件(linux对后缀没有要求,为了说明⽂件,姑且⽤exe后缀来表⽰可执⾏⽂件)gcc -o test.exe -ldynamic1 :错误,libdynamic1.so中没有包含libstatic.a,找不到libstatic.a的实现。

gcc -o test.exe -ldynamic1 -lstatic:正确,so中没有,但是指定了libstatic.a,可以编译过gcc -o test.exe -ldynamic2 :正确,libdynamic2.so中有libstatic.a的实现。

静态链接库与动态链接库

静态链接库与动态链接库

静态链接库的生成使用:
• 静态链接库在编写运行成功后会生成一个.lib文件, 在需要调用静态库的项目使用静态库时,需要将生成静态 库的头文件.h文件和.lib文件同时放在项目文件目录下(头 文件也可以写绝对地址,如: #include"E:\Cfile\funlib1\funlib1\funlib1.h";库文件也可以 在:项目-xx(项目)属性-VC++目录-库目录 中添加.lib文 件的路径),项目中还需要加载.h文件,在.cpp文件中调 用该头文件。 • 库函数中需要用到的函数,需要在头文件或者源文件 中声明,再加上链接库语句:#pragma comment(lib,"lib001.lib")就可以使用了,当使用绝对路径 时,如:#pragma comment(lib,"E:\\Cfile\\fundll1\\Debug\\fundll1.lib") 就不 需要在项目中添加路径了。

• • •
动态链接库:
• 在程序装载内存的时候,才真正的链接库函数代码, 进行确定它们的地址,即使有几个程序同时运行,内存中 也只有存在一份函数代码。 • 动态装载分为两类。 • 静态绑定,程序开始载入内存的时候,载入程序会把 所有调用到的动态代码的地址算出来,确定下来,此方式 初始化时间较长,完成动态装载后,运行速度很快。 • 动态绑定,需要调用的动态库代码,载入程序才会计 算动态代码的逻辑地址。初始化时间短,运行期间性能不 及静态绑定的程序。
动态链接库的使用:
• 调用动态链接库函数时需要将生成的.lib文件和.dll文 件都放入项目文件目录下(lib文件也可以在项目-xx(项 目)属性-VC++目录-库目录 中添加;dll文件需要放到exe 文件同目录下,或者放入系统盘的windows文件夹中), 除了上面提到的声明函数还需要 “#pragma comment(lib,"lib002.lib")”语句(当使用绝对路 径时,如: #pragma comment(lib,"E:\\Cfile\\fundll1\\Debug\\fundll1.lib") 就不 需要在项目中添加路径了),用于链接引入库文件,就可 以调用动态链接库了

C++静态库与动态库

C++静态库与动态库

C++静态库与动态库1、⼀个程序从源⽂件编译⽣成可执⾏⽂件的步骤:预编译 --> 编译 --> 汇编 --> 链接(1)预编译主要处理在源代码⽂件中以“#”开始的预编译指令,如宏展开、处理条件编译指令、处理#include指令等。

(2)编译过程就是把预处理完的⽂件进⾏⼀系列词法分析、语法分析、语义分析以及优化后⽣成相应的汇编代码⽂件。

(3)汇编是将汇编代码转变成机器指令。

(4)链接主要是把分散的数据和代码收集并合成⼀个单⼀的可加载并可执⾏的的⽂件。

链接可以发⽣在代码静态编译、程序被加载时以及程序执⾏时。

链接过程的主要⼯作是符号解析和重定位。

2、库库是⼀组⽬标⽂件的包,就是⼀些最常⽤的代码编译成⽬标⽂件后打包存放。

⽽最常见的库就是运⾏时库(Runtime Library),如C运⾏库CRT.库⼀般分为两种:静态库(.a 、.lib)动态库(.so 、.dll )所谓静态、动态是指链接过程。

3、静态链接与静态链接库静态链接:源程序经过编译器⽣成⽬标⽂件,⽬标⽂件和库⼀起⽣成最终的可执⾏⽂件。

链接的过程就是把分布在各个可重定位的⽬标⽂件中相应的节合并起来,同时完成符号解析和重定位。

静态库:⼀组⽬标⽂件的集合,即很多⽬标⽂件经过压缩打包后形成的⼀个⽂件。

静态库可以作为链接器的输⼊,如果程序需要引⽤静态库提供的某个函数,链接时只需要在命令⾏中输⼊该库。

连接器只拷贝被程序引⽤的⽬标模块,以及该⽬标模块索依赖的那些⽬标模块。

特点:(1)静态链接是在编译时期完成的(2)静态链接形成可执⾏⽂件后,运⾏时与静态库再⽆关系,⽅便移植。

(3)浪费内存和磁盘空间。

通过静态链接产⽣可执⾏程序时,会复制所依赖的静态库中所有数据和代码到该可执⾏程序中。

(4)更新困难。

当程序所依赖的静态库有任何更新,整个程序就要重新链接。

Windows下创建与使⽤静态库:以VS2010为例编写⼀个简单的计算器类,编成静态库供其他程序使⽤,代码如下:ifndef CALCULATOR_H_#define CALCULATOR_H_extern double g_max_number;double GetMinNumber();class Calculator{public:double Add(double a, double b) const;double Sub(double num1, double num2) const;double Mul(double num1, double num2) const;double Div(double num1, double num2) const;};#endifcpp⽂件#include "calculator.h"double g_max_number = 999;double Calculator::Add( double a, double b ) const{return (a + b);}double Calculator::Sub( double num1, double num2 ) const{return (num1 - num2);}double Calculator::Mul( double num1, double num2 ) const{return (num1 * num2);}double Calculator::Div( double num1, double num2 ) const{if (num2 != 0){return (num1 / num2);}return 0;}double GetMinNumber(){return (-999);}在创建VS⼯程时,在设置⼯程属性时,配置类型选择静态库即可,build即可⽣成静态库。

GCC程序编译的静态链接和动态链接

GCC程序编译的静态链接和动态链接

GCC程序编译的静态链接和动态链接(给Linux爱好者加星标,提升Linux技能)转自:Mr_Bluyee在链接阶段中,所有对应于源文件的 .o 文件、'-l' 选项指定的库文件、无法识别的文件名(包括指定的.o目标文件和.a库文件)按命令行中的顺序传递给链接器。

下面看一下,链接的过程是怎样的:gcc -v -o helloworld helloworld.oUsing built-in specs.COLLECT_GCC=gccCOLLECT_LTO_WRAPPER=d:/software/mingw/bin/../libexec/gcc/mingw32/6.3.0/lto-wrapper.exeTarget: mingw32Configured with: .. d:/software/mingw/bin/../lib/gcc/mingw32/6.3.0/crtend.oCOLLECT_GCC_OPTIONS='-v' '-o' 'helloworld.exe' '-mtune=generic' '-march=i586'crt2.o 、crtbegin.o、crtend.o是gcc加入的系统标准启动文件,对于一般应用程序,这些启动是必须的。

-Ldir:在库文件的搜索路径列表中添加dir目录。

-lname:添加链接库文件。

静态链接与动态链接库有两种:静态库(.a、.lib)和动态库(.so、.dll)。

window上对应的是 .lib、.dll。

linux上对应的是 .a、.so如果函数库的一份拷贝是可执行文件的物理组成部分,称之为静态链接。

静态链接当链接程序时,需要使用的每个库函数的一份拷贝被加入到可执行文件中。

静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,不过静态链接生成的程序体积较大(即使是在静态链接中,整个库文件也并没有全部装入到可执行文件中,所装入的只是需要如果可执行文件只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数库,称之为动态链接。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

动态库调用静态库.
生成动态库: 需要的目标文件得用-fPIC选项生成.
而静态库所需的目标文件可以不用-fPIC选项.
一个应用程序调用动态库, 而这个动态库其中的函数调用某静态库时,如何生成应用程序呢?
例:
/////// static.h
void static_print();
///////static.cpp
#include <iostream>
#include "static.h"
void static_print() {
std::cout<<"This is static_print function"<<std::endl;
}
////// shared.h
void shared_print();
////// shared.cpp
#include <iostream>
#include "shared.h"
#include "static.h"
void shared_print() {
std::cout<<"This is shared_print function";
static_print();
}
////////test.cpp
#include "share.h"
int main()
{
shared_print();
return 0;
}
方法一:
静态库的.o文件也用-fPIC生成. 生成动态库时把静态库加入.
生成应用程序时只加载动态库
g++ -c -fPIC static.cpp // 生成static.o
ar -r libstatic.a static.o // 生成静态库libstatic.a
g++ -c -fPIC shared.cpp // 生成shared.o
g++ -shared shared.o -lstatic -o libshared.so // 生成动态库libshared.so 注: -shared是g++的选项,与shared.o无关. -lstatic选项把libstatic.a的函数加入动态库中.
g++ test.cpp -lshared -o test.exe // link libshared.so 到test.exe中.
方法二:
静态库的.o文件不用-fPIC生成. 生成动态库时不加静态库.
生成应用程序时加载动态库和静态库.
g++ -c static.cpp // 生成static.o
ar -r libstatic.a static.o // 生成静态库libstatic.a
g++ -c -fPIC shared.cpp // 生成shared.o
g++ -shared shared.o -o libshared.so // 生成动态库libshared.so 注: -shared是g++的选项,与shared.o无关. 这时如果加-lstatic. error:relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
g++ test.cpp -lshared -lstatic -o test.exe // link libshared.so 到test.exe中.
两种方法的不同之处在于static_print的实际代码一个在.so中.一个在最后test.exe文件中. 个人觉得第一种方法更好, 因为动态库应该看成一个可以独立运行的程序.。

相关文档
最新文档