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#