总觉得动态链接库与静态链接很牛,但作为使用者,我更关心的是如何实现它。
1.什么是动态链接库?
简单地说,当你用到这个库中的实现时,要使你的程序可以运行,你就必须包括这个库,因为这个库中的实现是在你程序运行时动态加载到你的程序中的,使用动态链接库的程序会更小(相对于静态链接)。
2.什么是静态链接库?
你用到的库中的实现 是直接编进你的程序中的,这样程序就可以直接运行,不用把库也带上,但这个程序会很大。这在嵌入式中并不好,一个程序就几个M,哪有那么多空间放它。
更多关于链接库,百度一下吧。
从最简单开始,下面以一个hello为例写一个完整的流程,其中有一些关于Makefile等等的东西,备忘一下
linux系统下
工程文件描述:
有四个文件夹
a).放测试源文件(main),
b).放库源码与相关头文件,
同时为了好管理我建了两个文件夹
c.)生成的库文件
d.)库的头文件
路径分别如下:
a.)/mnt/hgfs/mystudy/unix 高级编程练习/sig信号篇/src
目录下有文件:
Makefile sig_01.c 说明.txt
b.)/mnt/hgfs/mystudy/unix 高级编程练习/myLib/src
目录下有文件:
hello.c hello.h Makefile
别两个文件夹是空的,当编译库时会自动把lib,和.h文件分别放入的。
c.)/home/tenyee/lib
d.)/home/tenyee/include
好了,下面先
实现库文件
b.)/mnt/hgfs/mystudy/unix 高级编程练习/myLib/src
目录下有文件:
hello.c hello.h Makefile
/*************** hello.c ****************/
#include"hello.h"
#include<stdio.h>
void print_hello()
{
printf("hello world\n");
}
/*************** hello.h ****************/
#ifndef _HELLO_H
#define _HELLO_H
void print_hello();
#endif
/**********************makefile************************/
target:
gcc -c sig_sync.c -I./
gcc -shared -fPCI -o libsig_sync.so sig_sync.o
ar cr libsig_sync.a sig_sync.o
gcc -c hello.c -I./
gcc -shared -fPCI -o libhello.so hello.o
ar cr libhello.a hello.o
install:
cp *.so *.a ../lib
cp *.so *.a /home/tenyee/lib
cp *.so *.a /usr/lib
cp *.h ../../include/
cp *.h /home/tenyee/include/
rm -rf *.o *.so *.a
clean:
rm -rf *.o *.so *.a
关于makefile的一些参数,还真是要清楚,我的想法是够用就行。
1.生成.obj文件,这是生成静动态库的基础
gcc -c sig_sync.c -I./
这里默认生成sig_sync.o,后面的-I./表示生成这个文件所要用到的头文件相对路径,这里是当前目录。
</pre><pre name="code" class="cpp">2.生成动态库,照着写吧
gcc -shared -fPCI -o libsig_sync.so sig_sync.o
</pre><pre name="code" class="cpp">3.生成静态库
ar cr libsig_sync.a sig_sync.o
</pre><pre name="code" class="cpp">生成的库被放在指定的地方,这个随意了,只是到了Mainy文件里要指定好库的位置就好了。
</pre><pre name="code" class="cpp">下面是测试文件
/mnt/hgfs/mystudy/unix 高级编程练习/sig信号篇/src
目录下有文件:
Makefile sig_01.c 说明.txt
/*****************sig_01.c*****************/
</pre><pre name="code" class="cpp">#include"hello.h"
int main()
{
print_hello();
wait_child();
return 0;
}
/********************makefile*********************/
target:
gcc -o sig_01 sig_01.c -I/home/tenyee/include -L/home/tenyee/lib -lsig_sync -lhello
clean:
rm -rf ./sig_01 ./sig_01.o
</pre><pre name="code" class="cpp">参数说明:
-L 后面跟的是库所在的路径
-l后面直接接库名(注意,在生成库时,用的是libXXX.a的,如果是以lib开头,则只要写个l就可以了,像-lhello)
</pre><pre name="code" class="cpp">gcc 默认动态链接的,要想静态链接,加参数 -static
</pre><pre name="code" class="cpp">NOTE:
我试过在库源文件中写成如下:
static void print_hello()
{
printf("");
}
</pre><pre name="code" class="cpp">直接在sig_01.c链接时出错,报找不到定义。。。
sig_01.c:(.text+0xfa):undefined reference to `print_hello'
去了static就可以了,为什么?不知道,先不管吧。
上面就完成了
*********************************************************************************************************/
更多关于库使用的参数说明:
库依赖
使用<span style="font-family: Arial, Helvetica, sans-serif;">-I参数可以向gcc的头文件搜索路径中添加新目录。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">gcc hello.c -I /home/wuzhiguo/include -ohello</span>
<span style="font-family: Arial, Helvetica, sans-serif;">使用-L参数可以向gcc的库文件搜索路径中添加新目录。(但我试过了,不行,可能是因为路径含有中文字符吧。。好了,我测试过了,是不能有中文字符的)</span>
<span style="font-family: Arial, Helvetica, sans-serif;">gcc -o sig_01 sig_01.c -I../../include -L/home/tenyee/lib –lhello(可用)</span>
<span style="font-family: Arial, Helvetica, sans-serif;">gcc hello.c -L /home/wuzhiguo/lib -l mylib -ohello </span><span style="font-family: Arial, Helvetica, sans-serif;">-l mylib 是指示gcc去链接库文件libmylib.so。Linux下的库文件有一个约定,全部以lib开头,因此可以省去lib。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">动态库:.so结尾,在运行时加载。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">静态库:.a结尾,在编译时加载。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">默认gcc优先加载动态库,可以在通过-static选项强制使用静态链接库。</span>
<span style="font-family: Arial, Helvetica, sans-serif;">gcc hello.c -L /home/wuzhiguo/lib -static -lmylib -o hello</span>
<span style="font-family: Arial, Helvetica, sans-serif;">所以-L后面的点为当前目录,-l后面是要静态连接的库(libhellos.a)</span>