静态库链接动态库时,如何使用该静态库
2018-01-26 11:43
337 查看
转自:http://blog.csdn.net/newchenxf/article/details/51735600
网上有各种静态库的创建&使用的例子,但都是超级简单的例子,比如,静态库,就直接来个printf(),就完事了!
其实,实际使用时,静态库会复杂很多,比如会调用很多其他的动态库。
下图就是个例子:
假设libXXX.a用了libpthread.so的函数“pthread_create”,那libXXX.a在链接时,有没有把“pthread_create”函数copy到自己身上,使其完全独立?main.c在链接时,只需要链接libXXX.a,还是连libpthread.so也要链接?!这就是我要讨论的内容!
为了证实问题,我们写个测试程序吧。一个是libXXX.a,一个是main.c。
static_lib_example.h
2
3
4
5
6
7
static_lib_example.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
一个头文件,一个原文件,很简单。
好吧,然后得来个Makefile
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
其实Makefile相当于2句命令。所以你不写Makefile,敲下面2句command也行。
gcc -c static_lib_example.c -o static_lib_example.o
ar rcs libstatic_lib_example.a static_lib_example.o
好了,编译结果如下:
ls
libstatic_lib_example.a Makefile static_lib_example.c static_lib_example.h static_lib_example.o
我们就写一个main.c,它会链接libstatic_lib_example.a,并调用函数testFunc(int x)
2
3
4
5
6
7
8
编译main.c(只需要一个命令,就不写Makefile啦)
gcc -g -O3 -Wall main.c -o main -I/home/chenxf/static_lib_sample/ -L/home/chenxf/static_lib_sample/ -lstatic_lib_example
-I表示头文件的路径
-L表示库的路径,即libstatic_lib_example.a的路径。
上面的命令,表示main程序,只链接静态库libXXX.a。(好吧,就是libstatic_lib_example.a啦,干嘛这么纠结名字!^^)
编译结果
/home/chenxf/static_lib_sample/libstatic_lib_example.a(static_lib_example.o):在函数‘testFunc’中:
static_lib_example.c:(.text+0x86):对‘pthread_create’未定义的引用
static_lib_example.c:(.text+0xd4):对‘pthread_join’未定义的引用
collect2: error: ld returned 1 exit status
出错啦!!!!!!
在main.c链接的时候,说找不到pthread_create了!
看来,静态库libXXX.a并没有把动态库的函数copy到自己身上,只留了符号表,所以main.c要用libXXX.a时,还必须链接动态库libpthread.so。也就是
gcc -g -O3 -Wall main.c -o main -I/home/chenxf/static_lib_sample/ -L/home/chenxf/static_lib_sample/ -static -lstatic_lib_example -lpthread
(libpthread.so在默认的系统库目录/usr/lib,不需要再写-L/usr/lib/)
这样一写,就OK啦!编译就成功了!
我们还可以用 nm 工具,来确认libXXX.a到底有木有把pthread_create()函数copy到自己身上。
2
3
4
5
6
7
8
9
10
11
12
U表示仅仅调用,而没有定义。也就是该库并不独立,而是依赖于其他库,比如libpthread.so
总结一下成果吧!
如果有静态库libXXX.a,它有个函数叫testFunc(),该函数用了其他的动态库的函数,比如libAA.so的AA()函数,libBB.so的BB()函数,libCC.so的CC()函数,那么,该libXXX.a对这些动态库的调用仍是动态调用,而不是把动态库的相关函数copy到自己身上。
任何其他程序,想用libXXX.a,链接时都需要链接libXXX.a所依赖的动态库。
至于程序跑起来时,动态库是否要在现场?这个就跟编译程序加不加-static有关系了。
请看我另一博文就知道。gcc-static命令
anyway,知道真相的你,是不是觉得静态库不方便?!
我也觉得!
个人看法是,如果你要写的静态库libXXX.a是完全独立的,比如里面只有一些数学运算,不依赖与其他动态库,那静态库挺好的,任何用他的程序,只需要链接时用到,程序跑起来,就不需要它在现场了!
但是,如果你要写的库,依赖很多其他的库,那你还是改写成动态库吧!否则,作为写其他程序的人,如果要用你的库,那写Makefile时,还得知道你到底依赖了什么动态库,否则编译都编译不过,多痛苦啊!!!
网上有各种静态库的创建&使用的例子,但都是超级简单的例子,比如,静态库,就直接来个printf(),就完事了!
其实,实际使用时,静态库会复杂很多,比如会调用很多其他的动态库。
下图就是个例子:
假设libXXX.a用了libpthread.so的函数“pthread_create”,那libXXX.a在链接时,有没有把“pthread_create”函数copy到自己身上,使其完全独立?main.c在链接时,只需要链接libXXX.a,还是连libpthread.so也要链接?!这就是我要讨论的内容!
为了证实问题,我们写个测试程序吧。一个是libXXX.a,一个是main.c。
1 静态库文件libXXX.a源代码
static_lib_example.h//static_lib_example.h #ifndef STATIC_LIB_EXAMPLE_H_INCLUDED #define STATIC_LIB_EXAMPLE_H_INCLUDED int testFunc(int x); #endif1
2
3
4
5
6
7
static_lib_example.c
//static_lib_example.c #include "static_lib_example.h" #include <stdio.h> #include <pthread.h> /* this function is run by the second thread */ void *thread_exe(void *x_void_ptr) { /* increment x to 100 */ int *x_ptr = (int *)x_void_ptr; while(++(*x_ptr) < 100); printf("x increment finished\n"); return NULL; } int testFunc(int x) { printf(" testFunc %i\n",x); pthread_t inc_x_thread; int y; /* create a second thread which executes thread_exe(&y) */ if(pthread_create(&inc_x_thread, NULL, thread_exe, &y)) { fprintf(stderr, "Error creating thread\n"); return 1; } return 0; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
一个头文件,一个原文件,很简单。
好吧,然后得来个Makefile
#chenxf make file #some notice #target: prerequisites - the rule head #$@ - means the target #$^ - means all prerequisites #$< - means just the first prerequisite OUT_LIB = libstatic_lib_example.a LIB_SRC := static_lib_example.c TEMP_O := static_lib_example.o $(TEMP_O): $(LIB_SRC) @gcc -c -o $@ $^ all: $(OUT_LIB) $(OUT_LIB): $(TEMP_O) @ar rcs $@ $^ clean: @rm -r *.a *.o1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
其实Makefile相当于2句命令。所以你不写Makefile,敲下面2句command也行。
gcc -c static_lib_example.c -o static_lib_example.o
ar rcs libstatic_lib_example.a static_lib_example.o
好了,编译结果如下:
ls
libstatic_lib_example.a Makefile static_lib_example.c static_lib_example.h static_lib_example.o
2. 调用静态库的程序main.c源代码
我们就写一个main.c,它会链接libstatic_lib_example.a,并调用函数testFunc(int x)//main.c #include "static_lib_example.h" int main(int argc, char* argv[]) { testFunc(100); return 1; }1
2
3
4
5
6
7
8
3 编译main.c的情况分析
编译main.c(只需要一个命令,就不写Makefile啦)gcc -g -O3 -Wall main.c -o main -I/home/chenxf/static_lib_sample/ -L/home/chenxf/static_lib_sample/ -lstatic_lib_example
-I表示头文件的路径
-L表示库的路径,即libstatic_lib_example.a的路径。
上面的命令,表示main程序,只链接静态库libXXX.a。(好吧,就是libstatic_lib_example.a啦,干嘛这么纠结名字!^^)
编译结果
/home/chenxf/static_lib_sample/libstatic_lib_example.a(static_lib_example.o):在函数‘testFunc’中:
static_lib_example.c:(.text+0x86):对‘pthread_create’未定义的引用
static_lib_example.c:(.text+0xd4):对‘pthread_join’未定义的引用
collect2: error: ld returned 1 exit status
出错啦!!!!!!
在main.c链接的时候,说找不到pthread_create了!
看来,静态库libXXX.a并没有把动态库的函数copy到自己身上,只留了符号表,所以main.c要用libXXX.a时,还必须链接动态库libpthread.so。也就是
gcc -g -O3 -Wall main.c -o main -I/home/chenxf/static_lib_sample/ -L/home/chenxf/static_lib_sample/ -static -lstatic_lib_example -lpthread
(libpthread.so在默认的系统库目录/usr/lib,不需要再写-L/usr/lib/)
这样一写,就OK啦!编译就成功了!
我们还可以用 nm 工具,来确认libXXX.a到底有木有把pthread_create()函数copy到自己身上。
chenxf@chenxf-PC:~/static_lib_sample$ nm libstatic_lib_example.a static_lib_example.o: U fwrite U printf U pthread_create U pthread_join U puts U stderr 0000000000000040 T testFunc 0000000000000000 T thread_exe1
2
3
4
5
6
7
8
9
10
11
12
U表示仅仅调用,而没有定义。也就是该库并不独立,而是依赖于其他库,比如libpthread.so
3 总结
总结一下成果吧! 如果有静态库libXXX.a,它有个函数叫testFunc(),该函数用了其他的动态库的函数,比如libAA.so的AA()函数,libBB.so的BB()函数,libCC.so的CC()函数,那么,该libXXX.a对这些动态库的调用仍是动态调用,而不是把动态库的相关函数copy到自己身上。
任何其他程序,想用libXXX.a,链接时都需要链接libXXX.a所依赖的动态库。
至于程序跑起来时,动态库是否要在现场?这个就跟编译程序加不加-static有关系了。
请看我另一博文就知道。gcc-static命令
anyway,知道真相的你,是不是觉得静态库不方便?!
我也觉得!
个人看法是,如果你要写的静态库libXXX.a是完全独立的,比如里面只有一些数学运算,不依赖与其他动态库,那静态库挺好的,任何用他的程序,只需要链接时用到,程序跑起来,就不需要它在现场了!
但是,如果你要写的库,依赖很多其他的库,那你还是改写成动态库吧!否则,作为写其他程序的人,如果要用你的库,那写Makefile时,还得知道你到底依赖了什么动态库,否则编译都编译不过,多痛苦啊!!!
相关文章推荐
- 静态库链接动态库时,如何使用该静态库
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- 如何使用cmake生成基于静态库的动态链接库
- g++ 编译链接C++代码, 生成与使用静态库和动态库
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库
- Linux 如何使用gcc生成静态库和动态库
- 如何在vc中使用mingw编译出来的动态库和静态库
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- 图解如何使用VS2010和Qt导出和使用静态库,动态库
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库
- 如何使用Eclipse的NDK开发动态库,静态库
- 图解如何使用VS2010和Qt导出和使用静态库,动态库
- 如何在vc中使用mingw编译出来的动态库和静态库
- C/C++ 关于生成静态库(lib)/动态库(dll)文件如何使用(基于windows基础篇)
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- 如何使用Eclipse的NDK开发动态库,静态库
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库