🎊 Linux gcc编译生成静态库和共享动态库的过程

Linux gcc编译生成静态库和共享动态库的过程

这篇文章主要通过实例演示在Linux下如何使用gcc分别编译生成静态库和动态库文件以及其它程序如何使用这个生成的静态库和动态库。

1 要用到的3个测试程序1、头文件hello.h:

1

2

3

4

#ifndef HELLO_H

#define HELLO_H

void hello(const char *name);

#endif

2、hello.c程序:

1

2

3

4

5

6

7

8

#include

void hello(const char *name)

{

printf( "Welcome to %s.\n", name );

printf( "libmyhello.so.1.0.1\n" );

//printf( "libmyhello.so.1.0.2\n" );

//printf( "libmyhello.so.1.0.3\n" );

}

3、主程序main.c:

1

2

3

4

5

6

#include "hello.h"

int main( int argc, char **argv )

{

hello("typecodes.com");

return 0;

}

2 生成静态库文件使用如下两个命令即可把.o目标文件聚合成.a静态库文件:

代码语言:javascript复制[root@typecodes howto_gen_static_lib]# ls

hello.c hello.h main.c

####生成目标文件 hello.o

[root@typecodes howto_gen_static_lib]# gcc -c hello.c

[root@typecodes howto_gen_static_lib]# ls

hello.c hello.h hello.o main.c

#####生成静态库文件 libmyhello.a

[root@typecodes howto_gen_static_lib]# ar rcs libmyhello.a hello.o

[root@typecodes howto_gen_static_lib]# ls

hello.c hello.h hello.o libmyhello.a main.c那么如何使用生成的静态库文件呢?这里以main.c中调用静态库文件并生成最终的可执行文件hello为例:

代码语言:javascript复制[root@typecodes howto_gen_static_lib]# gcc -o hello main.c libmyhello.a

####或者类似于动态共享库

[root@typecodes howto_gen_static_lib]# gcc -o hello main.c -L . -lmyhello

[root@typecodes howto_gen_static_lib]# gcc -o hello main.c -static -L. -lmyhello注意:如果出现下面这个错误,那么是由于程序链接需要静态库,系统没有安装静态库导致报错:

代码语言:javascript复制[root@typecodes howto_gen_static_lib]# gcc -o hello main.c -static -L. -lmyhello

/usr/bin/ld: cannot find -lc

collect2: error: ld returned 1 exit status

[root@typecodes ~]# yum info glibc-static

Loaded plugins: axelget, fastestmirror, langpacks

No metadata available for base

No metadata available for epel

No metadata available for extras

No metadata available for updates

Loading mirror speeds from cached hostfile

* base: mirrors.aliyun.com

* epel: mirrors.yun-idc.com

* extras: mirrors.aliyun.com

* updates: mirrors.aliyun.com

Available Packages

Name : glibc-static

Arch : i686

Version : 2.17

Release : 106.el7_2.1

Size : 1.2 M

Repo : updates/7/x86_64

Summary : C library static libraries for -static linking.

URL : http://www.gnu.org/software/glibc/

License : LGPLv2+ and LGPLv2+ with exceptions and GPLv2+

Description : The glibc-static package contains the C library static libraries

: for -static linking. You don't need these, unless you link statically,

: which is highly discouraged.

Name : glibc-static

Arch : x86_64

Version : 2.17

Release : 106.el7_2.1

Size : 1.5 M

Repo : updates/7/x86_64

Summary : C library static libraries for -static linking.

URL : http://www.gnu.org/software/glibc/

License : LGPLv2+ and LGPLv2+ with exceptions and GPLv2+

Description : The glibc-static package contains the C library static libraries

: for -static linking. You don't need these, unless you link statically,

: which is highly discouraged.解决方法:使用如下命令,安装glibc-static程序即可。

代码语言:javascript复制[root@typecodes howto_gen_static_lib]# yum -y install glibc-static

[root@typecodes howto_gen_static_lib]# ls

hello hello.c hello.h hello.o libmyhello.a main.c

#####运行可执行文件即可

[root@typecodes howto_gen_static_lib]# ./hello

Hello everyone!

[root@typecodes howto_gen_static_lib]#3 生成动态库文件可以如下面3.1小节所示通过gcc直接生成动态库文件,也可以像3.2小节中那样依次生成realname、soname、linkname库文件。不经常更新动态库版本的话,一般会采用3.1小节中的做法;版本更新较频繁的动态库,诸如MySQL的一些动态库就是采用的3.2小节中的做法。

3.1 直接编译生成symbolic link动态库文件代码语言:javascript复制##### 生成hello.o目标文件

[root@typecodes ~]# gcc -c -fPIC hello.c

##### 生成动态库文件libmyhello.so

[root@typecodes ~]# gcc -shared -fPIC -o libmyhello.so hello.o

##### main.c调用动态库文件并生成可执行文件hello

[root@typecodes ~]# gcc -o hello main.c -L. -lmyhello

##### 如果直接执行程序则会报错

[root@typecodes ~]# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory如下图所示,可执行文件hello找不到链接的动态库libmyhello.so而报错:

error while loading shared libraries ​

原因分析:使用ldd hello命令查看可执行文件hello依赖的动态库libmyhello.so,结果是not found。

ldd命令查看可执行文件所依赖的动态库 ​

解决方法一:使用root用户把自己生成的动态共享库路径添加系统动态库中即可。 ​

代码语言:txt复制 ##### ldconfig更新配置文件目录下的所有动态链接库为Linux系统所共享 [root@typecodes ~]# echo "/root/">/etc/ld.so.conf.d/test.conf [root@typecodes ~]# ldconfig ##### 运行可执行文件 [root@typecodes ~]# ./hello Welcome to typecodes.com.这时使用ldconfig -v命令查看系统动态库的搜索路径,可以看到libmyhello.so.1动态库所在的路径为绝对路径/root/:

ldconfig命令查看系统动态库路径3.2 先生成real name动态库文件,然后创建soname软连接,最后创建link name软链接代码语言:javascript复制##### 生成hello.o目标文件

[root@typecodes ~]# gcc -c -fPIC hello.c

##### 生成共享库:对应real name是libmyhello.so.1.0.1, 对应soname是libmyhello.so.1

[root@typecodes ~]# gcc -g -shared -Wl,-soname,libmyhello.so.1 -o libmyhello.so.1.0.1 hello.ogcc通过-Wl,-soname参数生成动态库如下图所示,使用readelf -d libmyhello.so.1.0.1命令查看动态库libmyhello.so.1.0.1的信息,可以看到对应的soname为libmyhello.so.1:

readelf查看动态库信息如下图所示,使用ldconfig -vn .命令在当前目录自动生成一个软链接:将soname(libmyhello.so.1)链接到real name(libmyhello.so.1.0.1)。

ldconfig命令生成soname文件软链接如下图所示,使用ln -sf libmyhello.so.1 libmyhello.so命令创建链接到soname的共享库文件名(Link Name):libmyhello.so。 ​

创建链接到real name的Link Name库文件这里如果和前面一样,直接链接创建的动态库文件libmyhello.so生成可执行文件hello,然后直至执行hello,那么也会提示找不到链接的动态库libmyhello.so:

代码语言:javascript复制[root@typecodes ~]# gcc -o hello main.c -L. -lmyhello原因也是一样的,可执行文件hello找不到链接库:

1

2

3

4

5

root@typecodes ~# ldd hello

linux-vdso.so.1 => (0x00007ffd7e7f7000)

libmyhello.so.1 => not found

libc.so.6 => /lib64/libc.so.6 (0x00007f641cb7d000)

/lib64/ld-linux-x86-64.so.2 (0x00007f641cf53000)

3.1小节中的方法需要root用户权限,对于非root用户有方法二来解决:如前文《Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别》所述,只要在当前Linux系统中配置LD_LIBRARY_PATH变量,就可以搜索到依赖的动态库libmyhello.so。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

root@typecodes ~# gcc -o hello main.c -L. -lmyhello

##### 把当前动态库路径添加到Linux环境变量LD_LIBRARY_PATH中

root@typecodes ~# export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/root

root@typecodes ~# echo $LD_LIBRARY_PATH

/root

##### 执行程序

root@typecodes ~# ./hello

Welcome to typecodes.com.

libmyhello.so.1.0

##### ldd查看可执行文件依赖的动态库

root@typecodes ~# ldd hello

linux-vdso.so.1 => (0x00007fffccf0d000)

libmyhello.so => /root/libmyhello.so (0x00007f6b58770000)

libc.so.6 => /lib64/libc.so.6 (0x00007f6b5839b000)

/lib64/ld-linux-x86-64.so.2 (0x00007f6b58973000)

root@typecodes ~#

设置LD_LIBRARY_PATH变量后,使用readelf查看动态库信息解决方法三:gcc链接动态库生成可执行文件时,加入rpath参数。

代码语言:javascript复制[root@typecodes ~]# gcc -o hello main.c -Wl,-rpath=./ -L. -lmyhello

[root@typecodes ~]# ./hello

Welcome to typecodes.com.

libmyhello.so.1.0.1

[root@typecodes ~]#gcc链接动态库生成可执行文件时,加入rpath参数解决方法四:最简单的操作就是直接将生成的动态库文件拷贝到Linux系统动态库搜索目录下。

代码语言:javascript复制/lib、/lib64: 系统必备共享库

/usr/lib、/usr/lib64: 标准共享库和静态库

/usr/local/lib: 本地/第三方函数库4 总结(update 2017.04.18 12:10)小节2中讲述了静态库文件的生成方法,小节3中讲述了动态库的生成方法。同时,在执行程序时如果报错提示找不到对应的库文件(可以通过readelf -d hello验证),那么一共有4种方法。

代码语言:javascript复制1、添加库路径到 /etc/ld.so.conf.d/ 目录下的配置文件中,然后执行命令ldconfig;

2、添加库路径到 LD_LIBRARY_PATH 环境变量中;

3、在编译链接命令中加入参数 -rpath=库文件所在路径 ;

4、最简单的方式:把库文件拷贝到Linux系统库文件所在目录下(/lib、/lib64、/usr/lib、/usr/lib64、/usr/local/lib等)。

🎈 相关推荐

Arctime字幕软件
🏷️ 足球比分365cv

Arctime字幕软件

📅 07-03 👀 2664
如何编辑微信表情包
🏷️ 日博官网365bet

如何编辑微信表情包

📅 09-05 👀 586
仓库管理表格大全汇总,仓库管理全套常用表格模板
🏷️ 日博官网365bet

仓库管理表格大全汇总,仓库管理全套常用表格模板

📅 09-03 👀 4466
突发,Wish将被收购!“美版拼多多”折断“低价之翅”
🏷️ 2022年bet体育365官网合法吗

突发,Wish将被收购!“美版拼多多”折断“低价之翅”

📅 07-13 👀 2116
《王者荣耀》五周年活动福利汇总 五周年福利有哪些
🏷️ 日博官网365bet

《王者荣耀》五周年活动福利汇总 五周年福利有哪些

📅 10-10 👀 2699
怎么吃小龙虾步骤图解,怎么吃小龙虾步骤图
🏷️ 2022年bet体育365官网合法吗

怎么吃小龙虾步骤图解,怎么吃小龙虾步骤图

📅 09-09 👀 9619