您的位置:首页 > 运维架构 > Linux

LINUX下动态库及静态库的学习记录

2013-06-12 15:14 260 查看
1.前言:

动态库是程序运行 的时候才去链接的库,默认链接路径为/lib/目录,规范命名为libxxx.so;静态库为编译可执行档时把需要调用到的函数

体嵌进到可执行程序里面,规范命名为libxxx.a.

2.一个动态库或静态库:

意思是指一个动态或静态库里面只有纯粹的源码生成,库中并没有再链接到其他静态库.下面给出实例:

func1.c

#include <stdio.h>
#include <stdlib.h>

void func1(void)
{
printf("######### %s | %d ##########\n",__func__,__LINE__);
}


func2.c

clude <stdio.h>
#include <stdlib.h>

void func2(void)
{
printf("######## %s | %d ########\n",__func__,__LINE__);
}


Makefile

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
CC=gcc
LD=ld
AR=ar
#LFLAGS+=-I/your_lib_dir/ -lyourlib
CFLAGS=-O2 -c -Wall -fpic

all:libfunc.so libfunc.a

libfunc.so:
$(CC) $(CFLAGS) $(SRCS)
$(CC) --shared -o $@ $(OBJS)

libfunc.a:
$(CC) $(CFLAGS) $(SRCS)
$(AR) -rcs $@ $(OBJS)

%.c:%.o
$(CC) -c $< $(CFLAGS)

clean:
rm -f *.o *.a *.so

.PHONY:
clean


直接make可以生成libfunc.so和libfunc.a.

测试程序main.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
func1();
func2();
return 0;
}


把libfunc.so和libfunc.a复制到main.c同一目录下,编译main.c:

gcc main.c -o main -L./ -lfunc


运行./main报错:

root@seven-laptop:~/learn/libforlinux# ./main
./main: error while loading shared libraries: libfunc.so: cannot open shared object file: No such file or directory
root@seven-laptop:~/learn/libforlinux#


可见,如果编译时同时存在动态库和静态库的时候,gcc优先选择动态库来参与编译.将libfunc.so复制到/lib/目录下,再次运行./main:

root@seven-laptop:~/learn/libforlinux# ./main
######### func1 | 6 ##########
######## func2 | 6 ########
root@seven-laptop:~/learn/libforlinux#


以上为动态库参与程序的编译,可知道需要把动态库更新到/lib/目录下.下面对比看一下静态库.先把libfunc.so从main.c的目录下删除.

编译main.c

gcc main.c -o main -L./ -lfunc
直接运行./main:

root@seven-laptop:~/learn/libforlinux# ./main
######### func1 | 6 ##########
######## func2 | 6 ########
root@seven-laptop:~/learn/libforlinux#
由此可见,静态库是作为可执行程序一部分实体链接进可执行程序的.而且静态编译生成的可执行档比动态编译生成的可执行档要大好多.

3.目标动态库链接静态库.

在日常的工作中,常常会遇到这种情况.比如说别人的源码不开放,只提供了一个libxxx.a库.我们的可执行程序先链接到我们自己的库,而我们

自己的库又链接到别人提供的libxxx.a库.比如,上述的libfunc.a假设是别人给的源码.将要生成的libfunc2.so是我们自己的目标库.

下面给出实例:

libfunc.a是由两个源码文件func1.c和func2.c生成.源码见上述.下面再写一个函数去调用func1.c和func2.c里面的函数.如下:

func3.h

ifndef _FUNC3_H_
#define _FUNC3_H_

extern void func1(void);
extern void func2(void);

#endif
func3.c

#include <stdio.h>
#include <stdlib.h>

#include "func3.h"

void func3(void)
{
func1();
func2();
printf("######## %s | %d #######\n",__func__,__LINE__);
}
注意:上述必须需要声明一下我们在libfunc.a里面调用的函数func1()和func2().否则编译提示下面警告:

func3.c: In function ‘func3’:
func3.c:8: warning: implicit declaration of function ‘func1’
func3.c:9: warning: implicit declaration of function ‘func2’
Makefile:

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
CC=gcc
LD=ld
AR=ar
LFLAGS+=-L./ -lfunc
CFLAGS=-O2 -c -Wall -fpic
OBJTA=*.o

all:libfunc2.so libfunc2.a

libfunc2.so:
$(CC) $(CFLAGS) $(SRCS)
$(CC) --shared -o $@ $(OBJS) $(LFLAGS)

libfunc2.a:
$(CC) $(CFLAGS) $(SRCS)
$(AR) -rcs -o $@ $(OBJTA)

%.c:%.o
$(CC) -c $< $(CFLAGS)

clean:
rm -f *.o *.so

.PHONY:
clean
注:上述Makefile中通过LFLAGS指定我们要链接进我们目标的动态库的静态库.

测试我们生成的目标动态库libfunc2.so:

root@seven-laptop:~/learn/libforlinux# gcc main2.c -o main2 -L./ -lfunc2
root@seven-laptop:~/learn/libforlinux# ./main2
./main2: error while loading shared libraries: libfunc2.so: cannot open shared object file: No such file or directory
root@seven-laptop:~/learn/libforlinux# cp libfunc2.so /lib/
root@seven-laptop:~/learn/libforlinux# ./main2
######### func1 | 6 ##########
######## func2 | 6 ########
######## func3 | 10 #######


4.静态库链接静态库

静态库链接静态库,这边测试没有成功.搜索GOOGLE结果如下:

静态库就是一堆.o,不需要“链接”任何东西,只有可执行文件和共享库(.so库)才需要“链接”.
因此,如果把依赖的.o作为元素而不是把.a库作为元素来加工我们的目标静态库.是OK的.

把func1.o、func2.o复制到我们目标的.a库目录下.Makefile如下:

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
CC=gcc
LD=ld
AR=ar
LFLAGS+=-L./ -lfunc
CFLAGS=-O2 -c -Wall -fpic
OBJTA=*.o

all:libfunc2.so libfunc2.a

libfunc2.so:
$(CC) $(CFLAGS) $(SRCS)
$(CC) --shared -o $@ $(OBJS) $(LFLAGS)

libfunc2.a:
$(CC) $(CFLAGS) $(SRCS)
$(AR) -rcs -o $@ $(OBJTA)

%.c:%.o
$(CC) -c $< $(CFLAGS)

clean:
rm -f *.o *.so

.PHONY:
clean
注:这里的OBJTA变量除了func3.o是动态生成之外,还包括了从别处复制过来的func1.o和func2.o.

make生成libfunc2.a

测试结果如下:

root@seven-laptop:~/learn/libforlinux# cp example2/libfunc2.a ./
root@seven-laptop:~/learn/libforlinux# rm -rf /lib/libfu
libfunc.so        libfuse.so.2      libfuse.so.2.7.2
root@seven-laptop:~/learn/libforlinux# rm -rf /lib/libfu
libfunc.so        libfuse.so.2      libfuse.so.2.7.2
root@seven-laptop:~/learn/libforlinux# rm -rf main2
root@seven-laptop:~/learn/libforlinux# gcc main2.c -o main2 -L./ -lfunc2
root@seven-laptop:~/learn/libforlinux# ./main2
######### func1 | 6 ##########
######## func2 | 6 ########
######## func3 | 10 #######
root@seven-laptop:~/learn/libforlinux#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: