`
tulunta
  • 浏览: 358341 次
文章分类
社区版块
存档分类
最新评论

GCC编译动态和静态链接库

 
阅读更多

我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两
种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态
库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运
行时还需要动态库存在。本文主要通过举例来说明在Linux中如何创建静态库和动态库,以
及使用它们。

在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。


第1步 :编辑得到举例的程序--hello.h、hello.c和main.c;

hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"
Hello XXX!"。hello.h(见程序1)为该函数库的头文件。main.c(见程序3)为测试库文件的
主程序,在主程序中调用了公用函数hello。

#ifndef HELLO_H
#define HELLO_H

void hello(const char *name);

#endif //HELLO_H
程序1: hello.h

#include <stdio.h>

void hello(const char *name)
{
printf("Hello %s!/n", name);
}
程序2: hello.c

#include "hello.h"

int main()
{
hello("everyone");
return 0;
}
程序3: main.c

第2步 :将hello.c编译成.o文件;

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过g
cc先编译成.o文件。

在系统提示符下键入以下命令得到hello.o文件。

# gcc -c hello.c

#

我们运行ls命令看看是否生存了hello.o文件。

# ls

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

#


在ls命令结果中,我们看到了hello.o文件,本步操作完成。

下面我们先来看看如何创建静态库,以及使用它。

第3步 :由.o文件创建静态库;

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。 例如:我们将
创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,
需要注意这点。创建静态库用ar命令。

在系统提示符下键入以下命令将创建静态库文件libmyhello.a。

# ar crv libmyhello.a hello.o

#

我们同样运行ls命令查看结果:

# ls

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

#

ls命令结果中有libmyhello.a。

第4步 :在程序中使用静态库;

静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包
含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从
静态库中将公用函数连接到目标文件中。
注意,gcc会在静态库名前加上前缀lib,然后追
加扩展名.a得到的静态库文件名来查找静态库文件。

在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公
用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。

(# gcc -o hello main.c -L. -lmyhello??)

#gcc main.c libmyhello.a -o main

# ./hello

Hello everyone!

#

我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。

# rm libmyhello.a

rm: remove regular file `libmyhello.a'? y

# ./hello

Hello everyone!

#

程序照常运行,静态库中的公用函数已经连接到目标文件中了。

我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。

第5步 :由.o文件创建动态库文件;

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其
文件扩展名为.so。
例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyh
ello.so。用gcc来创建动态库。

在系统提示符下键入以下命令得到动态库文件libmyhello.so。

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

#

我们照样使用ls命令看看动态库文件是否生成。

# ls

hello.c hello.h hello.o libmyhello.so main.c

#

第6步 :在程序中使用动态库;

在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含
这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们
先运行gcc命令生成目标文件,再运行它看看结果。

# gcc -o hello main.c -L. -lmyhello

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory

#

哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,
会在/usr/lib和/lib等目录中查找需要的动态库文件。
若找到,则载入动态库,否则将提
示类似上述错误而终止程序运行。我们将文件libmyhello.so复制到目录/usr/lib中,再试
试。

# mv libmyhello.so /usr/lib

# ./hello

Hello everyone!

#

成功了。这也进一步说明了动态库在程序运行时是需要的。

我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,
那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,
来试试看。

先删除除.c和.h外的所有文件,恢复成我们刚刚编辑完举例程序状态。

# rm -f hello hello.o /usr/lib/libmyhello.so

# ls

hello.c hello.h main.c

#

在来创建静态库文件libmyhello.a和动态库文件libmyhello.so。

# gcc -c hello.c

# ar cr libmyhello.a hello.o

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

# ls

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

#

通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.s
o都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标
文件hello,并运行程序 hello。

# gcc -o hello main.c -L. -lmyhello

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory

#

从程序hello运行的结果中很容易知道,当静态库和动态库同名时, gcc命令将优先使用动
态库。

Note:
编译参数解析
最主要的是GCC命令行的一个选项:
-shared 该选项指定生成动态连接库 (让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
l -fPIC:表示编译为位置独立的代码, 不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
l -L.:表示要连接的库在当前目录中
l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
l LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
l 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

调 用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

分享到:
评论

相关推荐

    GCC编译动态和静态链接库.pdf

    GCC编译动态和静态链接库.pdf 学习资料 复习资料 教学资源

    gcc编译动态和静态链接库

    转载的gcc编译方法,开发时老是忘记,作为资源吧,省得找了。

    动态和静态链接库

    gcc编译动态和静态链接库.pdf,教你如何编译和使用库,提高程序的理解力

    GCC 编译使用动态链接库和静态链接库的方法

    根据链接时期的不同,库又有静态库和动态库之分。 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。 有别于静态库,动态...

    grpc-1.30.2 Linux 编译静动态库

    默认编译是静态库,但考虑到 linux 上动态库使用较多,所以使用 -DBUILD_SHARED_LIBS=ON 参数编译为动态库。 在 centos 7 下使用 gcc 4.8.5 + cmake 3.16.9 编译,包含 bin, include, lib, lib64, share 五个目录,...

    stm32代码在ubuntu linux使用gcc编译的链接文件

    stm32代码在ubuntu linux使用gcc编译的链接文件 link.ld 具体参考博客: http://blog.csdn.net/embbnux/

    再议GCC编译时的静态库依赖次顺问题

    这是最常规的解决办法,除此之外,只需要加入--start-group和--end-group两个链接参数,即可保持被依赖的库放在前头,也就是改成如下即可:g++ -g -o $@ -Wl,--start-group $^ -Wl,--end-group。 这里的“-Wl,”...

    gcc常用参数(静动态链接 优化 调试)

    介绍gcc下常用的一些参数,包括预编译、编译、汇编和链接,以及优化和调试。静态链接与动态链接的内容。绝对原创!!

    一文教你如何构建静态链接库.md

    话说ISOC99有自己的一系列标准C函数库,例如我们熟悉的libc.a(包含标准I/O函数、字符串操作函数和整数数学函数)和libm.a(浮点数数学函数),可供我们在使用gcc编译工具编译程序时调用。那么,如果我们在日常学习...

    Linux静态链接库与模板类的处理方式

    在阅读本文之前,小编先给大家介绍一篇相关文章:...4.编译main函数,并将该静态链接库链接,生成可执行文件。 OK,按照这个思路,我们将之前写的快速排序代码修改后,如下: lib_test.h: //lib_test.h //head file

    静态库和动态库:.doc

    源码经过编译生成对象文件,对象文件进一步处理可以生成可执行程序或者库文件。...对于可执行程序和动态库,此“进一步处理”指的是“链接”,使用gcc命令。 对于静态库,此“进一步处理”指的是“打包”,使用ar命令。

    动态库和静态库用法

    预处理 编译 汇编 链接 下面逐个使用 预编译:宏替换 ,文件引入 ,去除空行,注释,为编译做准备 预编译命令: gcc -E test.c -o test.i test.c中内容 #include int main(){ printf(“hello world!\n”); return 0; } -E...

    Linux静态库与动态库实例详解

    1. Linux 下静态链接库编译与使用 首先编写如下代码: // main.c #include test.h int main(){ test(); return 0; } // test.h #include using namespace std; void test(); // test.c #include test.h void test...

    Dev-CppMingw32环境介绍(DOC)

    第八章 制作自己的静态链接库 第九章 制作自己的动态链接库 第十章 使用自己的动态链接库 第十一章 在Dev-Cpp中创建自己的工程 第十二章 在Dev-Cpp中生成自己的包 第十三章 Dev-Cpp包制作补完篇 第十四章 wxWidget的...

    pocketcpp:使用Notepad ++和MinGWgcc 9.2.0编译C ++ 11 C ++ 14 C ++ 17 C ++ 20代码段

    静态链接( -static )用于生成输出( .exe文件),因此,它不依赖于外部.dll (例如C ++运行时)。 在下一版本中,您将能够链接多个.cpp文件,并使用Boost和SDL之类的第三方库(已经包含在Pocket C ++发行版中)。...

    wxMSW-3.1.2_gcc510TDMGCC_x64_Dev

    使用方法:包含编译器相关头文件、wx头文件、指定__WXMSW__、_UNICODE、NDEBUG(发行版专用)、WSUSINGDLL(动态库专用)这几个宏,指定-finput-chaaset=GBK(系统的编码),指定链接库,使用TDMGCC编译GBK(系统...

    qt-5.9.9-gcc485-libc217-static-qt-xcb.tar.gz

    Qt 5.9.9 Linux下静态编译的库,支持图形界面,编译出来的图形界面程序通过ldd查看依赖无Qt. 编译环境:Cent 7.6 x64, GCC 4.8.5, lic为2.17 自行编译请参考: ./configure -confirm-license -opensource -debug-...

    C++链接库的使用,二维向量,三维向量

    1.熟悉各种Linux操作命令;并编写程序,使用GNU gcc/g++进行...3)分别用静态链接和共享链接的方式测试向量的使用。 3.创建包含二维向量和三维向量的向量库:libVector.a和 libVector.so,并分别写出对应的MakeFile文件

    xilinx SDK : undefined reference to “xxx”

    发现我的工程的问题是gcc 链接时找不到库文件,如下图我在gcc链接命令中添加了 -llwip4 (该命令的意思时:指定程序要链接的库lwip4,使用了gcc中的-l命令),顺利的解决我的问题啦,从下图也可以看到gcc的编译...

Global site tag (gtag.js) - Google Analytics