在windows下,一般可以通过文件的后缀名来识别文件的类型。在Linux下大致上也是可以的。但是要明确的一点是,在linux下,文件的后缀与文件的类型是没有必然的联系的。这只是约定俗称的习惯罢了。
在linux 下进行C/C++开发,一般都是使用的编译器,所以本文的讲解以为主。
- 文件,即目标文件。一般通过或者文件编译而来,相当于编译出来的文件
- 文件,shared object 共享库(对象),相当于windows下的dll。
- 文件,archive 归档包,即静态库。其实质是多个文件打包的结果,相当于下的文件
- 文件,libtool archive 文件,是libtool自动生成的共享库文件。
下面对这四种文件进行逐个说明。
先说一下C/C++编译的几个过程。
- 预处理,展开头文件,宏定义,条件编译处理等。通过或者生成。
- 编译。这里是一个狭义的编译意义,指的是将预处理后的文件翻译成汇编代码的过程。通过生成。默认生成文件。
- 汇编。汇编即将上一步生成的汇编代码翻译成对应的二进制机器码的过程。通过来生成文件。
- 链接。链接是将生成目标文件和其引用的各种符号等生成一个完整的可执行程序的过程。链接的时候会进行虚拟内存的重定向操作。
上面四个步骤就是C/C++程序编译的几个基本步骤。前面三个步骤都是很简单,大多时候会合并为一个步骤。只有第四个步骤是复杂一点的。很多时候我们编译比较大的项目,报错的往往是在链接的时候缺少某些库,或者某些符号找不到定义,重定义等。
文件就是C/C++源码编译的结果。即上面所说的C/C++编译过程中的前三步。一般开发中很少将这三步分开来做,通常的做法是一步生成。
这里举个例子,我们来写一个函数。
头文件
源文件
这就是文件了。它保存了编译的时候引用到的符号(函数,全局变量等),这些符号,在链接的时候需要使用到。
使用的地方有很多,就不一一列举了。这里先不说怎么用,后面生成文件的时候用到了。
这个工具的作用看起来很简单,但是其是很强大,且参数的设置很复杂的。这里不是为了介绍这个工具,不细说了。
我们先使用上面生成的文件来生成一个文件。
参数的意思是替换已存在的或插入新的文件到archive包中。
创建了文件后,我们就可以来使用它了。这里我们写一个函数来调用。
文件
这一次我们先把编译为文件。
然后使用程序来链接和
上面报了一个错误,原因是在函数中使用未定义的引用 ,这个问题我们可以通过链接上或者来解决这个问题。通常的情况下,都是链接来解决的,如果使用glibc的静态库,那么你也必须将你的程序开源,不然这应该算是违反GPL协议的约定。
这里又报了一个警告,是没有发现符号的意思。这是因为没有发现程序主入口点的原因。在C语言中,程序的入口函数是,但是在汇编中,程序的主入口函数是。
这里我们可以把文件中的函数改为函数,然后再编译为再链接就没有问题了。但是这不是正确的做法,这样做虽然使用来链接是不会报错了,但是程序是运行不了的。会报错误
编译之后我们可以来看以下程序运行结果是否正确。
结果为5,与预期一致。
注:
第一次没有指定的时候出错了,原因是针对可迁移R_X86_64_32平台,只读数据段’.rodata’不能创建成共享对象,原因是在动态链接动态库的时候,如果没有编译成位置无关代码,那么链接的时候可能因为某些代码的位置具有相关性,而在执行时出现错误。可执行文件在链接时就知道每一行代码、每一个变量会被放到线性地址空间的什么位置,因此这些地址可以都作为常数写到代码里面。对于动态库,只有加载的时候才知道。
如果代码中没有只读数据段,那么就不会有这个问题。例如
使用文件的形式和使用也差不多,也是使用来进行链接。因为这过于复杂,还是使用来做这个操作(实际上gcc也是使用的ld)。
上面执行的时候报错,意思是找不到这个文件。原因是共享库的查找目录没有当前目录,我们可以添加环境变量来使系统动态载入器 (dynamic linker/loader)在当前目录也查找。
还有一种办法,比添加环境变量更好使,也更具有可移植性,那就是编译的时候指定运行的时候共享库的加载路径。gcc使用来指定,其中是共享库放置的路径(可以是绝对路径,也可以是相对路径)。
动态库还可以通过/等来使用,这里就不介绍了。
以下的内容,参考使用 GNU Libtool 创建库
这里先要说以下这个工具。
libtool是GNU的一个用来解决各个平台创建动态/静态库文件的不同操作的过于复杂的工具。它提供了使用抽象的接口进行动态/静态库的方法。
使用可以容易的在不同的系统中建立动态链接库。它通过一个称为库的抽象,隐藏了不同系统之间的差异,给开发人员提供了一致的的接口。对于大部分情况,开发人员甚至不用去查看相应的系统手册,只需要掌握的用法就可以了。并且,使用 的也只需要编写一次就可以在多个系统上使用。
libtool的使用一般分为以下几个步骤
1. 创建 Libtool 对象文件
2. 创建 Libtool 库
3. 安装 Libtool 库
4. 使用 Libtool 库
5. 卸载 Libtool 库
1. 创建 Libtool 对象文件
创建libtool对象文件的过程,实际上是生成、、文件的过程,同时还生成了一个文件。文件里面描述了两个.o文件的路径。这一步,就已经生成了相应的动态库和静态库。
其中一个是用于生成静态库的,一个是用于生产动态库的。
2. 创建 Libtool 库
注意这里使用作为输入文件,并指定生成的目标文件为。
选项是指定Libtool将这个库安装到的位置,如果省略了选项,那么不生成动态链接库。
因为在函数中使用了标准C库函数,所以带上选项,Libtool 会记住这个依赖关系,后续在使用我们的库时自动的将依赖的库链接进来。
可以看到这次在当前目录下生成了文件,而目录下的那个是一个符号链接,指向当前目录下的这个文件。这其实是一个文本文件,里面的内容比较长,就不贴了。贴几个比较重要的。
3. 安装 Libtool 库
上面操作报了一个,提示我们去运行 ,这个操作是使用libtool进行一个正确配置环境变量、等的过程。如果不能正常的使用安装好的库,运行这个命令。
查看一下,在当前目录生成了 libatoi.a、libatoi.so、libatoi.so.0、libatoi.so.0.0.0这几个文件。
4. 使用 Libtool 库
先编译文件
然后使用来进行链接操作。
从上面的输出可以看到,实际上它还是调用的来进行的操作,但是它添加了选项,这就是做的事情之一,它会解决依赖的问题。
上面的操作默认使用的动态库,可以使用选项来指定使用静态库。
使用选项重新生成。
已经不不需要了
5. 卸载 Libtool 库
这是对安装操作的反操作,会删除安装的所有库文件。
http://www.cnblogs.com/oloroso/p/4874801.html
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/3245.html