Linux - 如何使用gcc命令生成静态库和动态库

来源:互联网 发布:mac 删除桌面安装程序 编辑:程序博客网 时间:2024/05/29 23:46

一、库的简述

简单的说,库(Library)是由系统提供的一组具有特定功能的函数的集合,是为提高开发效率和运行效率而设计的。从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。

静态库:

静态是指每个用到该库的应用程序都会将该库拷贝到自己的目标代码中,因此利用静态库生成的文件比较大。

命名:lib****.a

动态库(也叫共享库):

动态库在编译时并没有将该库带进目标代码中,当程序执行到相关函数时才调用该库,因此使用这类库生成的文件会比较小。动态库的改变并不会影响你自己的程序,因此动态库的升级比较方便。除此之外,动态库有一个最显著的特点就是:当多个程序调用同个共享库时,内存中只有一个动态库实例。

命名: lib****.so

linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。


二、库的生成

我们以下列代码为例讲解静态库与动态库的生成,准备好test.c  hello.c   hello.h文件

"test.c"

#include "hello.h"int main(){  hello("world!");  return 0;}

"hello.c"

#include"hello.h"#include<stdio.h>void hello(const char *name){  printf("hello %s! \n",name);}

"hello.h"

#ifndef _HELLO_H_#define _HELLO_H_void hello(const char *name);#endif

无论动态库或者静态库都是从.o文件生成的,因此在讲解动态库和静态库之前,我们先执行以下命令生成 hello.o 文件和 test.o 文件:

$ gcc -c hello.c

$ gcc -c test.c

再 ls 一下就可以看到当前目录下多了两个文件:hello.o 和 test.o



·生成静态库

①通过gcc编译生成.o文件(无论静态库还是动态库都是由.o文件生成的)

②使用ar命令创建静态库,ar命令将很多.o文件转换成.a文件

命令:ar rcs lib****.a  ***.o

举例,假设我们要生成libmyhello.a的静态库文件,就是 ar rcs libmyhello.a hello.o



·生成动态库

我们从.o文件开始,首先需要创建一个名为myhello的动态库,则动态库文件名就是libmyhelli.so

执行这条命令以生成 libmyhello.so 的文件。

$ gcc -shared -fPIC -o libmyhello.so hello.o

·笔记:“PIC”命令行标记告诉gcc产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译出的 hello.o 可以被用于建立共享链接库。建立共享链接库只需要gcc的“-shared”标记即可。



调用动态库编译并链接文件,生成可执行程序hello:

$ gcc -o hello test.c -L. -lmyhello

·笔记:“-lmyhello”标记告诉gcc驱动程序在链接阶段引用共享库 libmyhello.so

            “-L.”标记告诉gcc函数库可能位于当前目录。否则GNU连接器会查找标准系统函数目录,它会先后搜索以下路径:1. elf文件的 DT_RPATH段; 2. 环境变量LD_LIBRARY_PATH; 3. /etc/ld.so.cache文件列表; 4. /lib/,/usr/lib/ 目录,找到库文件后将其载入内存。



继续,我们接着执行hello:

$./hello

·笔记:当我们在命令行执行该指令后发现会有错误“./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory”,这是由于我们生成的共享库在当前文件下,而在我们上述的四个路径的任一个路径下。因此我们需要将 libmyhello.so 复制到 /usr/lib/下,当再次执行 hello 时便可执行成功。


注意:在我们拷贝 libmyhello.so 文件到 /usr/lib/ 时,要是root用户才可执行


既然连接器会搜寻LD_LIBRARY_PATH所指定的目录,所以我们也可以将这个环境变量设置为当前目录再执行 hello 也可以成功!



今天的分享就是这些了,主要是掌握上面的几条命令。


0 0
原创粉丝点击