前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux gcc编译生成静态库和共享动态库的过程

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

作者头像
typecodes
发布于 2024-03-29 06:14:12
发布于 2024-03-29 06:14:12
97700
代码可运行
举报
文章被收录于专栏:typecodestypecodes
运行总次数:0
代码可运行

这篇文章主要通过实例演示在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 <stdio.h> 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
代码运行次数:0
运行
AI代码解释
复制
[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
代码运行次数:0
运行
AI代码解释
复制
[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
代码运行次数:0
运行
AI代码解释
复制
[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
代码运行次数:0
运行
AI代码解释
复制
[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
代码运行次数:0
运行
AI代码解释
复制
##### 生成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
error while loading shared libraries

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

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

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

代码语言:txt
AI代码解释
复制
 ##### 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命令查看系统动态库路径
ldconfig命令查看系统动态库路径
3.2 先生成real name动态库文件,然后创建soname软连接,最后创建link name软链接
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
##### 生成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.o
gcc通过-Wl,-soname参数生成动态库
gcc通过-Wl,-soname参数生成动态库

如下图所示,使用readelf -d libmyhello.so.1.0.1命令查看动态库libmyhello.so.1.0.1的信息,可以看到对应的soname为libmyhello.so.1:

readelf查看动态库信息
readelf查看动态库信息

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

ldconfig命令生成soname文件软链接
ldconfig命令生成soname文件软链接

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

创建链接到real name的Link Name库文件
创建链接到real name的Link Name库文件

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[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查看动态库信息
设置LD_LIBRARY_PATH变量后,使用readelf查看动态库信息

解决方法三:gcc链接动态库生成可执行文件时,加入rpath参数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[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参数
gcc链接动态库生成可执行文件时,加入rpath参数

解决方法四:最简单的操作就是直接将生成的动态库文件拷贝到Linux系统动态库搜索目录下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/lib、/lib64:                        系统必备共享库
/usr/lib、/usr/lib64:                标准共享库和静态库
/usr/local/lib:                 本地/第三方函数库
4 总结(update 2017.04.18 12:10)

小节2中讲述了静态库文件的生成方法,小节3中讲述了动态库的生成方法。同时,在执行程序时如果报错提示找不到对应的库文件(可以通过readelf -d hello验证),那么一共有4种方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1、添加库路径到 /etc/ld.so.conf.d/ 目录下的配置文件中,然后执行命令ldconfig;
2、添加库路径到 LD_LIBRARY_PATH 环境变量中;
3、在编译链接命令中加入参数 -rpath=库文件所在路径 ;
4、最简单的方式:把库文件拷贝到Linux系统库文件所在目录下(/lib、/lib64、/usr/lib、/usr/lib64、/usr/local/lib等)。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-01-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux编译工具:gcc入门
1. 什么是gcc gcc的全称是GNU Compiler Collection,它是一个能够编译多种语言的编译器。最开始gcc是作为C语言的编译器(GNU C Compiler),现在除了c语言,还支持C++、java、Pascal等语言。gcc支持多种硬件平台。 2. gcc的特点 gcc是一个可移植的编译器,支持多种硬件平台。例如ARM、X86等等。 gcc不仅是个本地编译器,它还能跨平台交叉编译。所谓的本地编译器,是指编译出来的程序只能够在本地环境进行运行。而gcc编译出来的程序能够在其他平台进行运
Tencent JCoder
2018/07/02
5K0
Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别
昨天在自己的CentOs7.1上写makefile的时候,发现在一个C程序在编译并链接一个已生成好的lib动态库的时候出错。链接命令大概是这样的:
typecodes
2024/03/29
1.2K0
Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别
Linux 中的静态库和动态库简介及生成过程示例
Linux中的静态库和动态库简介及生成过程示例 【文章摘要】 在实际的软件开发项目中,不是每一行代码都需要我们亲自写。在我们的软件产品中,有一些代码(尤其是函数)的出现频率很高,它们可以被当作公共代码来反复使用。为了避免重复劳动,我们就把这些公共代码编译为库文件,供需要的程序调用。在Linux中,库分为静态库和动态库两种。 本文对静态库和动态库进行了详细的介绍,并用实际的C代码演示了这两种库的生成过程。 一、静态库和动态库简介 众所周知,程序一般需要经过预处理、编译、汇编和链接这几个步骤才能变成可执行的程
用户2017109
2018/06/19
1.6K0
【Linux系统编程】——深入理解 GCC/G++ 编译过程及常用选项详解
⼀般我们的云服务器,C/C++的静态库并没有安装,可以采⽤如下⽅法安装 Centos yum install glibc-static libstdc++ -static -y
用户11286421
2025/01/17
4920
动态库与静态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
二肥是只大懒蓝猫
2023/03/30
2.5K0
动态库与静态库
【库函数】Linux下动态库.so和静态库.a的生成和使用
我在路径/root/host/my_program/asoc/include下创建四个文件
SarPro
2024/04/25
2.3K0
【库函数】Linux下动态库.so和静态库.a的生成和使用
GCC写个库给你玩,就这?
「静态库(.a)」:程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。静态库比较占用磁盘空间,而且程序不可以共享静态库。运行时也是比较占内存的,因为每个程序都包含了一份静态库。
DeROy
2021/01/05
1.1K0
静态库(.a)与动态库(.so)的简明介绍
gcc有很多关于静态库,动态库的选项如-l,-L,-fPIC,-shared -Wl,-soname,看着很复杂容易混淆,其实静态库和动态库都是应需而生,只要有了一个线索都很容易理解。
racaljk
2018/10/10
1.7K0
【一站式解惑】Linux中.a、.so和.o文件以及-I,-L,LIBRARY_PATH,LD_LIBRARY_PATH等
在说明Linux的.a、.so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系。
自学气象人
2023/01/13
5.9K0
gcc编译器参数_gcc for c4droid
虽然我们称Gcc是C语言的编译器,但使用gcc由C语言源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历四个相互关联的步骤∶预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
全栈程序员站长
2022/11/04
1.1K0
C语言---静态库VS动态库
在编程的过程中,使用已经封装好的库函数是十分方便的,也是十分高效的,因此会使用函数库是很重要的。在C语言中,函数库文件分为两种类型,一种是静态库(库程序是直接注入目标程序的,不分彼此,库文件通常以.a结尾),另一种是动态库(库程序是在运行目标程序时(中)加载的,库文件通常以.so结尾),下面我们就探索一下这两种库文件的特点和使用方式吧!
HeaiKun
2020/07/07
9.2K0
linux 动态库 静态库_静态库里面包含动态库
那么这三个时间有什么作用呢? 我们在使用自动化构建工具Makefile时,如果连续make会发现:
全栈程序员站长
2022/11/10
7.8K0
linux 动态库 静态库_静态库里面包含动态库
深入理解GCC 和 G++ 编译器
GCC(GNU Compiler Collection)和 G++ 是 GNU 项目的一部分。GCC 是一个多语言支持的编译器,可以处理 C、C++、Fortran 等语言,而 G++ 是 GCC 的 C++ 前端,用于专门处理 C++ 源代码。
DevKevin
2024/12/31
3890
【linux学习指南】Linux编译器 gcc和g++使用
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。 预处理指令是以#号开头的代码行。 实例: gcc –E hello.c –o hello.i 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。
学习起来吧
2024/09/11
4630
【linux学习指南】Linux编译器 gcc和g++使用
详解动态库和静态库
在C、C++中我们使用过标准库,比如在使用strerror、vector、string等时,都只是调用了这些函数接口,这些都是需要具体的实现。
南桥
2024/06/03
3210
详解动态库和静态库
Linux基础——gcc编译、静态库与动态库(共享库)
1、静态库的命名格式 lib + 库的名字 + .a 例:libMyTest.a (MyTest为静态库的名字)
全栈程序员站长
2022/11/10
9.2K0
Linux基础——gcc编译、静态库与动态库(共享库)
动态库与静态库:深入解析与应用
静态库 是一种在编译时被链接到目标代码中的库。它通常以 .a 文件(在 Unix/Linux 系统中)或 .lib 文件(在 Windows 系统中)的形式存在。
用户11396661
2025/02/16
2470
库的概念:动态库与静态库
库是一组封装好的函数或方法,它们可以被多个程序复用,从而避免重复编写相同功能的代码。例如,标准的数学函数库、字符串操作库都属于常用的库。
DevKevin
2025/01/03
4350
深度解析Linux中的编译器gcc/g++
我们需要进入到/etc/sudoers这个文件里面,我们需要使用我们的root账户,不然得话我们进去之后什么都看不见的
Undoom
2025/01/17
2060
深度解析Linux中的编译器gcc/g++
动态库与静态库优缺点比较分析_c静态库和动态库的区别
我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期的代码维护。我们可以把他们制作成相应的功能函数,使用时直接调用就会很方便,还可以进行后期的功能升级。
全栈程序员站长
2022/11/11
3.4K0
推荐阅读
相关推荐
Linux编译工具:gcc入门
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验