linux下生成静态库和动态库

一、动态库、静态库简介

库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:

静态库.a(win 系统下是lib)和动态库.so(win 系统下是.dll)。所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:

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

静态库特点总结:

-静态库对函数库的链接是放在编译时期完成的。

-程序在运行时与函数库再无瓜葛,移植方便。

-浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。
-是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。

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

动态库特点总结:

-动态库把对一些库函数的链接载入推迟到程序运行的时期。

-可以实现进程之间的资源共享。(因此动态库也称为共享库)

-将一些程序升级变得简单。

-甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

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

[ps:在windows平台和linux平台下都大量存在着库。由于windows和linux的平台不同(主要是编译器、汇编器和连接器的不同),因此二者库的二进制是不兼容的。本文仅限于介绍 linux 下的库。]

二、用gcc生成静态和动态链接库的示例

首先,本文主要通过举例来说明在 Linux 中如何创建静态库和动态库,以及使用它们。为了便于阐述,我们先准备下测试代码:hello.h、hello.c、main.c(我将这三个代码放在一个名为‘静态链接’的文件夹中)。如下所示

hello.h

#ifndef HELLO_H
#define HELLO_H
void hello(const char* name);
#endif

hello.c

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

main.c

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

注意:这个时候,hello.c 是无法通过gcc –o 编译,这个道理非常简单,hello.c 是一个没有main函数的.c程序,因此不够成一个完整的程序,如果使用gcc –o编译并连接它,gcc 将报错。

(ps:gcc -o 与gcc -c 的区别。gcc–o  是将.c源文件编译成为一个可执行的二进制代码,这包括调用作为 GCC 内的一部分真正的 C 编译器( ccl ),以及调用GNU C编译器的输出中实际可执行代码的外部 GNU 汇编器和连接器工具。而g -c是使用GNU汇编器将源文件转化为目标代码之后就结束,在这种情况下连接器并没有被执行,所以输出的目标文件不会包含作为 Linux 程序在被装载和执行时所必须的包含信息,但它可以在以后被连接到一个程序)

其实,我们的问题就是,如何让main.c中能使用hello这个函数。这时候我们有三种思路:

1、通过编译多个源文件,直接将目标代码合成一个.o 文件。

2、 通过创建静态链接库libmyhello.a ,使得 main 函数调用 hello 函数时可调用静态链接库。

3、 通过创建动态链接库libmyhello.so ,使得 main 函数调用 hello 函数时可调用静态链接库。

下面分别进行演示。

1.通过编译多个源文件,直接将目标代码合成一个.o 文件.首先利用gcc -c指令将hello.c和main.c编译生成hello.o和main.o文件,再用gcc -o指令将hello.o和main.o文件生成一个可执行文件hello。具体如下图所示:

2.通过创建静态链接库libmyhello.a ,使得main函数调用hello函数时可调用静态链接库。

下面我们先来看看如何创建静态库,以及使用它。Linux静态库命名规范,必须是"lib[your_library_name].a":lib为前缀,中间

是静态库名,扩展名为.a。例如:我们将创建的静态库名为 myhello ,静态库文件名就是 libmyhello.a。在创建和使用静态库时,

需要注意这点。Linux创建静态库分为两步:

第一步:将代码文件编译成目标文件。即将hello.c文件编译成hello.o文件,使用指令是:gcc -c hello.c

第二步:利用ar工具将目标文件hello.o打包成静态库文件.a(注意命名规则,我的静态库文件名为:libmyhello.a)

具体如下图所示:

现在我们已经生成了静态库文件libmyhello.a了,下面就是怎么使用它。Linux下使用静态库,只需要在编译的时候,指定静态库的

搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,-l选项)。

指令:

gcc -o hello main.c -L/Users/wangxuewei/Desktop/静态链接 -lmyhello

指令可以这么解释:利益gcc -o指令,将main.c编译成可执行文件hello。其中main.c函数中要使用的函数,存储在静态链接库

libmyhello.a 。"-L/Users/wangxuewei/Desktop/静态链接"是该静态库文件所在地址,"-lmyhello"表示的是要使用的静态库文

件的名字,看起来怪怪的哈,因为它不需要制定前缀lib和后缀.a,所以就变成了myhello,-l则是指令标示符号。

[ps:关于gcc指令中的-l和-L参数问题。-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so(.o),很容易看出,把库文件名的头lib和尾.so/.o去掉就是库名了。放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest]

进一步可以删除静态函数libmyhello.a,然后运行hello函数,看看其是否真的链接到了目标函数.

3、 通过创建动态链接库libmyhello.so ,使得 main 函数调用 hello 函数时可调用静态链接库。

linux动态库的命名规则

动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为“.so”。

l  针对于实际库文件,每个共享库都有个特殊的名字“soname”。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。

l  在文件系统中,soname仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件(lib+soname+.so)。

创建动态库(.so)可以分为两步:

第一步:生成目标文件,此时要加编译器选项-fPIC。[ps:-fPIC是创建与地质无关的编译程序,是为了能够在多个应用程序间共享]

gcc -fPIC -c hello.c

第二步:生成动态库,此时要加链接器选项-shared。[ps:-shared是指定生成动态链接库]

gcc -shared -o libmyhello.so hello.o

以上两步也可以写成一条指令:

gcc -shared -fPCI -o libmyhello.so hello.c

运行该指令后会生成一个libmyhello.so文件,如下图:

使用动态链接库
引用动态链接库,和静态库一样,在编译时指定动态链接库就好

gcc main.c -L. -lmyhello

-L.  代表动态库在当前路径下;-l后面跟的是动态链接库的名字( 与静态一样,可以舍去前缀lib和后缀.so)

执行该指令后,会生成一个a.out的可执行文件,可以执行下看看:


可以看到,是可以执行的!!但是,在网上看,很多博客说这样是不可以的,因为:库文件在连接(静态库和动态库)和运行(仅限于使用动态库的程序)时被使用,其搜索路径是在系统中进行设置的。一般Linux系统把/lib 和 /usr/lib(也可能是/usr/local/lib)三个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到搜索路径之中。但是,我电脑中,当动态库与执行程序在同一目录下时,也可以运行,可能是因为我用的mac吧,暂时没弄清楚。。。不过可以确定,当将动态库libmyhello.so移动到/usr/local/lib时,a.out仍可正常运行。

更一般的,对于处于默认路径之外的库,如何让系统找到它呢?一般有两种方法:

1.将动态库复制到/lib 或 /usr/lib 或 /usr/local/lib中。就像我上面做的一样,将libmyhello.so复制到/usr/local/lib中,这是系统是可以找到的。

2.如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:

2.1 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

2.2 运行ldconfig ,该命令会重建/etc/ld.so.cache文件

[ps:第二种方法我没有试,因为mac系统里好像跟这个不太一样,还在研究中。。。具体可以参考下面几篇文章,解释的比较详细]
参考:
http://www.cnblogs.com/skynet/p/3372855.html
http://blog.163.com/hitperson@126/blog/static/130245975201151552938133
http://blog.163.com/redhumor@126/blog/static/19554784201154101229272/
http://blog.csdn.net/jaylong35/article/details/6132087
http://www.aichengxu.com/view/10712254

linux下生成静态库和动态库相关推荐

  1. linux编译ios动态库,[Linux] linux下生成静态库和动态库

    g++使用 用g++编译hello world 1. 编写hello world代码 2. 使用g++命令编译生成可执行文件hello.out 3. g++命令规则 预编译 g++ -E hello. ...

  2. Linux 下的静态(函数)库、动态(函数)库

    0. 基本 在命名上,静态库的名字一般是 libxxx.a,动态库的名字一般是 libxxx.so,有时 libxxx.so.major.minor,xxx 是该 lib 的名字,major 是主版本 ...

  3. C语言 | Linux下的静态链接与动态链接

    1024G 嵌入式资源大放送!包括但不限于C/C++.单片机.Linux等.关注微信公众号[嵌入式大杂烩],回复1024,即可免费获取! 前言 上一篇分享了静态链接与动态链接的实验(Windows): ...

  4. Linux下CMake简明教程(六)动态库和静态库的编译控制

    代码在git 有时只需要编译出动态库和静态库,然后等着让其它程序去使用.让我们看下这种情况该如何使用cmake.首先按照如下重新组织文件,只留下testFunc.h和TestFunc.c ├── CM ...

  5. linux下项目开发加载动态库:ldconfig与 /etc/ld.so.conf

    场景:自己开发一个项目,程序里包含一些自定义动态库.运行,需要加载这些动态库. 假如这些库在/pro/output/lib/下面,可执行程序在/pro/output/bin/下面. 那么,我们需要: ...

  6. linux修改ip dhcp,Linux下在静态IP与动态DHCP之间切换的脚本

    因为经常在Vmware机上需要变动IP,有时要在静态与动态之间切换,下面这个小脚本可满足需要,在RHEL4,RHEL5下测试通过 1.创建文件changeIP.sh #vi   changeIP.sh ...

  7. linux 中如何将文件粘贴到usr下的lib内,学会在Linux下GCC生成和使用静态库和动态库...

    一.基本概念1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主 ...

  8. Linux下Gcc生成和使用静态库和动态库详解

    参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...

  9. Linux下GCC生成和使用静态库和动态库详解(二)

    2.1准备好测试代码hello.h.hello.c和main.c: hello.h(见程序1)为该函数库的头文件. hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏 ...

最新文章

  1. 【ACM】杭电OJ 2149
  2. python2和python3同时存在如何使用pip
  3. hihocoder1513 小Hi的烦恼
  4. 如何让你的百万级SQL运行得更快 else
  5. CSS魔法堂:那个被我们忽略的outline
  6. 为什么直播时要用CDN?
  7. 代码编辑器横评:为什么 VS Code 能拔得头筹
  8. 天才基本法_《天才基本法》强推!年度神仙小说,看完这本书我竟然爱上了数学...
  9. jvm oracle sun,JVM - 常见的JVM种类
  10. 宏基因组多少钱一个样_太阳能路灯价格是多少钱一盏(12米高杆灯报价)
  11. linux下mysql乱码_linux下mysql中文乱码
  12. 微服务 注册中心的作用_微服务架构Dubbo之注册中心(Zookeeper)
  13. python自动化办公excel-自动化办公:python 操作Excel
  14. FFmpeg 基本用法
  15. 【软件工程习题答案】第八章 维护
  16. excel Cell函数
  17. 架构设计的新思路,《架构之道》读书笔记
  18. github | 马赛克去除项目
  19. Love Letter
  20. C++语言的基本符号与词汇

热门文章

  1. Silverlight 3.0 RTW引入-- 鼠标滚动事件
  2. subtext blog装好了,老外的文档还是写的有些问题
  3. CentOS上安装Jekins
  4. 内网穿透工具 Ngrok
  5. android语音识别开源代码,android语音识别,有没有相应的源码,教程可以推荐啊?
  6. mysql索引的增删_mysql索引的增删改查怎么实现?
  7. 3、MapReduce详解与源码分析
  8. Docker 部署clickhouse-server及添加用户配置密码
  9. 【uni-app】使用定义在App.vue的方法
  10. 【规范化标准】之 ESLint、Stylelint