编译生成动态库时,被关联的静态库会被编译到动态库里面
动态库调用静态库.
生成动态库: 需要的目标文件得用-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文件中. 个人觉得第一种方法更好, 因为动态库应该看成一个可以独立运行的程序.。
静态链接与动态链接:理解不同链接方式的原理与应用
静态链接与动态链接:理解不同链接方式的原理与应用静态链接和动态链接是计算机软件开发中常用的两种链接方式。
静态链接是将编译后的目标文件与其他源文件中的代码拼接在一起,生成一个完整的可执行文件。
而动态链接是在程序运行时,通过动态链接库(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操作系统中,动态库和静态库的调用方法如下:
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中动态链接库和静态链接库的⽣成与调⽤ 背景:写这篇博客的原因是:最近在搞嵌⼊式,需要交叉编译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编译选项分析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语言中,通过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 下编译链接动静态库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来进行链接。
