有动态库编译包含静态库和静态库,g++编译时如何指定链接静态库

gcc链接g++编译生成的静态库和动态库的makefile示例
使用c++开发程序或者库时,将库提供给其他人使用。
然而使用者是使用c开发的程序,链接g++编译生成的库时,于链接gcc生成的库,有所不同。
首先是静态库,以链接g++编译生成的libmylib.a为例子
mylib依赖于pthread,rt,math库,链接时必须放在mylib之后。
同时-Wl,--no-as-needed -ldl添加在末尾是必须的。
arm和x86有些不同,就是arm的gcc不会自动链接数学库math,需要手动添加链接。
1 CC=arm-linux-gnueabihf-gcc -std=c99
2 CCLDFLAGS= -L. -lmylib -lstdc++ -pthread -lrt -lm -Wl,--no-as-needed -ldl
3 #CC=gcc -m32 -std=c99
4 #CCLDFLAGS=-L. -lmylib -lstdc++ -pthread -lrt -Wl,--no-as-needed -ldl
6 all:test
8 test.o:test.c
$(CC) -I../inc/ test.c -c -o test.o
11 test:test.o libmylib.a
$(CC) test.o -o test $(CCLDFLAGS)
14 .PHONY: clean
-rm test test.o -f
gcc链接g++生成的动态库示例:
libmylib.so库,使用g++编译时,静态链接了stdc++库(-static-libstdc++)。
1 CC=gcc -m32 -std=c99
2 #CC=arm-linux-gnueabihf-gcc -std=c99
3 CCLDFLAGS=-lstdc++ -L. -lmylib
5 Root:root
7 root.o:test.c
$(CC) -I../inc/ test.c -c -o root.o
10 root:root.o libmylib.so
$(CC) root.o -o root $(CCLDFLAGS)
14 .PHONY: clean
-rm root *.o
没有更多推荐了,博客分类:
首先我们创建一个static_lib.c文件,内容如下:
int add(int a,int b)
return a+b;
int sub(int a,int b)
return a-b;
然后在shell中编译该文件,生成一个重定位的目标文件如下:
gcc -c static_lib.c
Linux下使用ar工具创建一个静态库,或者将目标文件加入到已经存在的静态库中
ar rcs 静态库名 目标文件1 目标文件2.....目标文件n
该命令表示将目标文件1-n加入到指定的静态库中。如果该静态库不存在,则创建静态库文件,并且将库文件的拓展名为.a ,其中ar工具的参数rcs起了至关重要的作用。这三个参数分别表示:把列表中的目标文件加入到静态库中(参数r)若指定的静态库不存在,则创建该库文件(参数c);最后更新静态库文件的索引,失之保函新加入的目标文件文件的内容(参数s)
现在需要使用刚刚生成的static.o目标文件创建一个静态库static_lib.a,其执行命令如下:
ar rcs static_lib.a static_lib.o
然后你就能够在目录下看到你创建的静态库了
下面是使用静态库
在vi编辑器中编辑头文件static_lib.h如下:
extern int add(int a,int b);
extern int sub(int a,int b);
然后在vi编辑器中编辑使用库程序: main.c
#include&stdio.h&
#include"static_lib.h"
int main(){
printf("Please input a and b:");
scanf("%d%d",&a,&b);
printf("the add :%d\n",add(a,b));
printf("the sub :%d\n",sub(a,b));
然后使用命令:
gcc main.c -static ./static_lib.a -o app
动态库也很方便,编译命令是:gcc -shared -fPIC -o share_lib.so static_lib.c
使用时:gcc main.c ./ static_lib.so -o app
浏览: 160306 次
来自: 杭州
你好,我想问一下。为什么我在java工程里测试没有问题。但是到 ...
求jasonpeak 写道我的为什么按返回键还是不关闭呢?求破 ...
我的为什么按返回键还是不关闭呢?
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'静态库如何链接静态库_百度知道
静态库如何链接静态库
我有更好的答案
在工程搭建时,可能会有将静态库链接成动态库的需求,如出于代码保护的角度,某些模块会发布.a扩展名的静态库,我们要将多个这样的静态库链接成一个动态库。但与直接link目标文件不同的是,ld以默认参数执行时,并把静态库中没有用到的函数过滤掉,导致生成的so并未包含所要的函数,因此要加上--whole-archive参数,以保证所有的函数都包含在生成的so中。在使用cmake时,CMakeLists.txt的写法如下:add_library(${MODULE_NAME}SHARED${CMAKE_SOURCE_DIR}/builttime.c #要生成一个so,至少要包含一个源文件,实在没有可以把库的编译时间戳打到这儿。)target_link_libraries(${MODULE_NAME}${${MODULE_NAME}_EXTRA_LDFLAGS}&-Wl,--whole-archive& #告诉编译器,从这里开始,所有的库的内容都包含到so中${LOCAL_MODULES} #可以是以源代码生成的静态库${PREBUILT_MODULES} #可以是预先生成的静态库&-Wl,--no-whole-archive& #告诉编译器,从这里开始,以后的库的内容不用都包含到so中)
毅衣公司京东小二
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。技巧:Linux 动态库与静态库制作及使用详解
两个要知道的基本知识 Linux 应用程序因为 Linux 版本的众多与各自独立性,在工程制作与使用中必须熟练掌握如下两点才能有效地工作和理想地运行。
Linux 下标准库链接的三种方式(全静态 , 半静态 (libgcc,libstdc++), 全动态)及其各自利弊。 Linux 下如何巧妙构建 achrive(*.a),并且如何设置链接选项来解决 gcc 比较特别的链接库的顺序问题。三种标准库链接方式选项及对比 为了演示三种不同的标准库链接方式对最终应用程序产生的区别, 这里用了一个经典的示例应用程序 HelloWorld 做演示,见 。 整个工程可以在文章末尾下载。 清单 1.
HelloWorld #include &stdio.h&
#include &iostream&
using std::
using std::
int main(int argc, char* argv[])
printf("HelloWorld!(Printed by printf)\n");
cout&&"HelloWorld!(Printed by cout)"&&
}三种标准库链接方式的选项及区别见 表 1表 1. 三种标准库链接方式的选项及区别标准库连接方式示例连接选项优点缺点全静态-static -pthread -lrt
-ldl不会发生应用程序在 不同 Linux
版本下的标准库不兼容问题。生成的文件比较大,
应用程序功能受限(不能调用动态库等)全动态-pthread -lrt
-ldl生成文件是三者中最小的比较容易发生应用程序在
不同 Linux
版本下标准库依赖不兼容问题。半静态
(libgcc,libstdc++)-static-libgcc -L. -pthread -lrt
-ldl灵活度大,能够针对不同的标准库采取不同的链接策略, 从而避免不兼容问题发生。
结合了全静态与全动态两种链接方式的优点。比较难识别哪些库容易发生不兼容问题,
目前只有依靠经验积累。 某些功能会因选择的标准库版本而丧失。 上述三种标准库链接方式中,比较特殊的是 半静态链接方式,主要在于其还需要在链接前增加额外的一个步骤:
ln -s `g++ -print-file-name=libstdc++.a`,作用是将 libstdc++.a(libstdc++
的静态库)符号链接到本地工程链接目录。 -print-file-name 在 gcc 中的解释如下:
-print-file-name=&lib& Display the full path to library &lib&
为了区分三种不同的标准库链接方式对最终生成的可执行文件的影响,本文从两个不同的维度进行分析比较: 维度一:最终生成的可执行文件对标准库的依赖方式(使用 ldd
命令进行分析) ldd 简介:该命令用于打印出某个应用程序或者动态库所依赖的动态库
涉及语法:ldd [OPTION]... FILE...
其他详细说明请参阅 man 说明。
三种标准库链接方式最终产生的应用程序的可执行文件对于标准库的依赖方式具体差异见 、、所示: 图 1. 全静态标准库链接方式图 2. 全动态标准库链接方式图 3. 半静态(libgcc,libstdc++)
标准库链接方式 通过上述三图,可以清楚的看到,当用
全静态标准库的链接方式时,所生成的可执行文件最终不依赖任何的动态标准库, 而
全动态标准库的链接方式会导致最终应用程序可执行文件依赖于所有用到的标准动态库。
区别于上述两种方式的 半静态链接方式则有针对性的将 libgcc 和 libstdc++
两个标准库非动态链接。 (对比 与 ,可见在
中这两个标准库的动态依赖不见了)
从实际应用当中发现,最理想的标准库链接方式就是半静态链接,通常会选择将 libgcc 与 libstdc++ 这两个标准库静态链接,
从而避免应用程序在不同 Linux 版本间标准库依赖不兼容的问题发生。 维度二 : 最终生成的可执行文件大小(使用 size
命令进行分析) size 简介:该命令用于显示出可执行文件的大小
涉及语法:size objfile... 其他详细说明请参阅 man 说明。
三种标准库链接方式最终产生的应用程序的可执行文件的大小具体差异见 、、所示: 图 4. 全静态标准库链接方式图 5. 全动态标准库链接方式图 6. 半静态(libgcc,libstdc++)
标准库链接方式 通过上述三图可以看出,最终可执行文件的大小随最终所依赖的标准动态库的数量增加而减小。 从实际应用当中发现,最理想的是
半静态链接方式,因为该方式能够在避免应用程序于
不同 Linux
版本间标准库依赖不兼容的问题发生的同时,使最终生成的可执行文件大小最小化。 示例链接选项中所涉及命令(引用 GCC
原文): -llibrary -l library:指定所需要的额外库
-Ldir:指定库搜索路径
-static:静态链接所有库
-static-libgcc:静态链接 gcc 库
-static-libstdc++:静态链接 c++ 库
关于上述命令的详细说明,请参阅 GCC 技术手册 Linux 下静态库(archive)的制作方式:涉及命令:ar ar 简介:处理创建、修改、提取静态库的操作
涉及选项: t - 显示静态库的内容
r[ab][f][u] - 更新或增加新文件到静态库中
[s] - 创建文档索引
[&mri-script] - 使用 ar 脚本处理
其他详细说明请参阅 man 说明。 示例情景: 假设现有如 所示两个库文件 图 7. 示例静态库文件 从 中可以得知,CdtLog.a 只包含 CdtLog.o 一个对象文件 , 而 xml.a 包含
TXmlParser.o 和 xmlparser.o 两个对象文件
现将 CdtLog.o 提取出来,然后通过 方式创建一个新的静态库 demo.a,可以看出,demo.a 包含的是 CdtLog.o 以及
xml.a, 而不是我们所预期的 CdtLog.o,TXmlParser.o 和 xmlparser.o。这正是区别于 Windows
下静态库的制作。 图 8. 示例静态库制作方式 1 这样的 demo.a 当被链接入某个工程时,所有在 TXmlParser.o 和 xmlparser.o
定义的符号都不会被发现,从而会导致链接错误, 提示无法找到对应的符号。显然,通过图 8 方式创建 Linux 静态库是不正确的。 正确的方式有两种: 将所有静态库中包含的对象文件提取出来然后重新打包成新的静态库文件。 用一种更加灵活的方式创建新的静态库文件:ar 脚本。 显然,方式 1 是比较麻烦的,因为涉及到太多的文件处理,可能还要通过不断创建临时目录用于保存中间文件。 推荐使用如 所示的 ar
脚本方式进行创建: 清单 2
createlib.sh rm demo.a
echo CREATE demo.a & ar.mac
echo SAVE && ar.mac
echo END && ar.mac
ar -M & ar.mac
ar -q demo.a CdtLog.o
echo OPEN demo.a & ar.mac
echo ADDLIB xml.a && ar.mac
echo SAVE && ar.mac
echo END && ar.mac
ar -M & ar.mac
rm ar.mac 如果想在 Linux makefile 中使用 ar 脚本方式进行静态库的创建,可以编写如 所示的代码: 清单 3
BUILD_LIBRARY define BUILD_LIBRARY
$(if $(wildcard $@),@$(RM) $@)
$(if $(wildcard ar.mac),@$(RM) ar.mac)
$(if $(filter %.a, $^),
@echo CREATE $@ & ar.mac
@echo SAVE && ar.mac
@echo END && ar.mac
@$(AR) -M & ar.mac
$(if $(filter %.o,$^),@$(AR) -q $@ $(filter %.o, $^))
$(if $(filter %.a, $^),
@echo OPEN $@ & ar.mac
$(foreach LIB, $(filter %.a, $^),
@echo ADDLIB $(LIB) && ar.mac
@echo SAVE && ar.mac
@echo END && ar.mac
@$(AR) -M & ar.mac
@$(RM) ar.mac
$(TargetDir)/$(TargetFileName):$(OBJS)
$(BUILD_LIBRARY) 通过 ,我们可以看到,用这种方式产生的 demo.a 才是我们想要的结果。 图 9. 巧妙创建的静态库文件结果Linux 静态库链接顺序问题及解决方法: 正如 GCC 手册中提到的那样: It makes a difference where in the command you write
the linker searches and processes libraries and object
files in the order they are specified. Thus, ‘ foo.o -lz bar.o ’
searches library ‘ z ’ after file ‘ foo.o ’ but before ‘ bar.o ’ . If
‘ bar.o ’ refers to functions in ‘ z ’ , those functions may not be
为了解决这种库链接顺序问题,我们需要增加一些链接选项 : $(CXX) $(LINKFLAGS) $(OBJS)
-Xlinker "-(" $(LIBS) -Xlinker "-)" -o $@ 通过将所有需要被链接的静态库放入
-Xlinker "-(" 与 -Xlinker "-)" 之间,可以是 g++ 链接过程中,
自动循环链接所有静态库,从而解决了原本的链接顺序问题。 涉及链接选项:-Xlinker -Xlinker option Pass option as an option to the linker. You can use
this to supply system-specific linker options which GCC does not know
how to recognize. 小结 本文介绍了 Linux 下三种标准库链接的方式及各自利弊,同时还介绍了 Linux 下静态库的制作及使用方法,相信能够给 大多数需要部署 Linux
应用程序和编写 Linux Makefile 的工程师提供有用的帮助。
下载资源 (HelloWorld.zip | 2.49KB) (gcc.pdf | 2.88MB)相关主题有关 ar, 请参考: 。 有关静态链接,请参考:。 在
寻找为 Linux 开发人员(包括 )准备的更多参考资料,查阅我们 。 在 developerWorks 上查阅所有
和 。 随时关注 developerWorks 和。
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=http://www.ibm.com/developerworks/js/artrating/SITE_ID=10Zone=LinuxArticleID=769215ArticleTitle=技巧:Linux 动态库与静态库制作及使用详解publish-date=阅读排行榜
评论排行榜

我要回帖

更多关于 静态编译与动态编译 的文章

 

随机推荐