专业做网站企业,百度站长管理平台,郑州注册网站,开发公司副总经理岗位职责程序编译一般需要经预处理、编译、汇编和链接几个步骤。在实际应用中#xff0c;有些公共代码需要反复使用#xff0c;就把这些代码编译成为“库”文件。在链接步骤中#xff0c;连接器将从库文件取得所需的代码#xff0c;复制到生成的可执行文件中#xff0c;这种库称为… 程序编译一般需要经预处理、编译、汇编和链接几个步骤。在实际应用中有些公共代码需要反复使用就把这些代码编译成为“库”文件。在链接步骤中连接器将从库文件取得所需的代码复制到生成的可执行文件中这种库称为静态链接库其特点是可执行文件中包含了库代码的一份完整拷贝缺点是被多次使用就会多份冗余拷贝。还有一种库就是程序在开始运行后调用库函数时才被载入这种库独立于现有的程序其本身不可执行但包含着程序需要调用的一些函数这种库称为动态链接库Dynamic Link Library。在widows平台下静态链接库是.lib文件动态库文件是.dll文件。在linux平台下静态链接库是.a文件动态链接库是.so文件。这里主要讲在linux平台下的动态库和静态库的生成以及链接。本文主要参考【1】【2】【3】【4】 一、库的基本知识 首先说明要对库有一个比较直观的理解。库是写好的现有的成熟的可以复用的代码。现实中每个程序都依赖很多基础的底层库不可能每个人的代码都从零开始因此库的存在意义非同寻常。本质上说来库是一种可执行代码的二进制形式注其本身不可执行可以被操作系统载入内存执行。 静态链接库之所以称为“静态库”是因为在链接阶段会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中因此对应的链接方式为静态链接。其实一个静态链接库可以简单看成一组目标文件(.o/.obj文件)的集合即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结 1. 静态库对函数库的链接是放在编译时期完成 2. 程序在运行时对函数库再唔瓜葛一直方便。 3. 浪费空间和资源因为所有相关的目标文件和牵涉到的函数库被链接合成一个可执行文件。 linux下使用ar工具windows下用lib.exe具体的用法参考【5】可以将目标文件压缩到一起并且对其进行编号和索引一便于查找和索引。一般创建静态链接库的步骤如下 静态链接库的命名规则库的名称和库文件名称不同有联系假定库名称为my_library_name那么起库文件名为lib[my_library_name].a(方括号是为了区分实际上没有) 动态链接库在程序编译是并不会被连接到目标代码中而是在程序运行时才被载入。不同的应用程序如果调用相同的库那么在内存里只需要有一份该共享库的实例规避了空间浪费问题。动态库的一些总结 1. 动态库把对一些库函数的链接载入推迟到程序运行时期 2. 可以实现进程之间的资源共享动态库也成为共享库 3. 将一些程序升级变得简单 4. 设置可以真正做到链接载入完全由程序员在程序代码中控制显式调用 Linux下gcc编译的执行文件默认是ELF格式不需要初始化入口亦不需要函数做特别的声明编写比较方便。与windows系统下的格式不同。与创建静态库不同的是不需要打包工具直接使用编译器即可创建动态库。 动态链接库的命名规则与静态链接库的方式相同不过其后缀名为.so命名形式为lib[my_library_name].so 。但是在实际使用过程中libxxx.so 大多数情况只是一个链接它链接到一个包含版本信息的库文件 libxxxx.so.xx如下图。当然自己可以使用 ln 命令制作链接 ln -s libxxxx.so.xx libxxxx.so。 二、库的编译和链接 下面使用一个例子来说明链接库是如何生成与链接的。这个例子的源代码参考【4】。这里有五个文件头文件“SoDemoTest.h”三个cpp文件“one.cpp”、two.cpp、three.cppmain函数实现文件“main.cpp”。 [cpp] view plaincopy #ifndef _SO_DEMO_TEST_HEADER_ #define _SO_DEMO_TEST_HEADER_ #include iostream using namespace std; void one(); void two(); void three(); #endif [cpp] view plaincopy /* one.cpp */ #include SoDemoTest.h void one(){ cout call one() function endl; } [plain] view plaincopy /* two.cpp */ #include SoDemoTest.h void two(){ cout call two() function endl; } [cpp] view plaincopy /* three.cpp */ #include SoDemoTest.h void three(){ cout call three() function endl; } [cpp] view plaincopy /* main.cpp */ #include SoDemoTest.h int main(){ one(); two(); three(); return 0; } gcc/g的编译参数这里只介绍 -L 、-l、-include、-I、-shared、-fPIC -L 表示要链接的库所在的目录。-L. 表示要链接的库在当前目录 -L/usr/lib 表示要连接的库在/usr/lib下。目录在/usr/lib时系统会自动搜索这个目录可以不用指明。 -l (L的小写)表示需要链接库的名称注意不是库文件名称比如库文件为 libtest.so那么库名称为test -include 包含头文件这个很少用因为一般情况下在源码中都有指定头文件。 -I (i 的大写)指定头文件的所在的目录可以使用相对路径。 -shared 指定生成动态链接库 -fPIC 表示编译为位置独立的代码不用此选项的话编译后的代码是位置相关的所以动态载入时事通过代码拷贝的方式来满足不同进程的需要而不能达到真正代码共享的目的。 生成链接库 第1步生成目标文件g -c xxx.cpp 第2步创建静态链接库: ar cqs libxxxx.a xx1.o xx2.o xx3.o (参数选项请看【5】) 第3步程序中使用静态链接库 第4步创建动态链接库 g -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp 第5步动态链接库使用 库的链接上面简单演示了一遍库的生成过程但是还有很多细节没有讲清楚。以下问题需要注意 1. 链接过程中可能出现多种链接方式需要使用一些参数来指定下面只是一个演示在测试时自己填写具体的名称 [plain] view plaincopy g testmain.o -o testmain -WI,-Bstatic -lstaticlib -WI,-Bdynamic -ldynamiclib 2. 链接过程中同一个库名称相同的静态和动态两种链接库在链接过程中系统优先选择动态链接库 3. 动态链接库路径系统默认在/usr/lib 和/usr/local/lib两个库目录搜索自己定义的库需要格外指定路径设定变量LD_LIABRARY_PATH或者将其拷贝到这两个目录下在上面的例子的测试过程已经有说明。当然也可以将当前路径添加到/etc/ld.so.conf文件中或者/etc/ld.so.conf.d目录下的一个文件中。 4. 查看动态链接库。有时候可能需要查看一个库中到底有哪些函数nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多常见的有三种 一种是在库中被调用但并没有在库中定义表明需要其他库支持用U表示 一种是在库中定义的函数用T表示这是最常见的 另一种所谓的“弱态”符号它们虽然在库中定义但可能被其他库中的同名符号覆盖用W表示。 使用ldd命令可以查看程序的库依赖 注更多详细的信息请阅读下面的链接中的内容~ 【1】博客园C静态库与动态库 【2】CSDNLinux 静态库动态库调用 【3】博客园gcc/g 动态编译和链接问题 【4】Linux公社用g编译生成动态连接库*.so的方法及连接 【5】CSDNlinux ar命令