首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux 动态库与静态库制作及使用详解(2)

Linux 动态库与静态库制作及使用详解(2)

示例链接选项中所涉及命令(引用 GCC 原文): -llibrary
-l library:指定所需要的额外库
-Ldir:指定库搜索路径
-static:静态链接所有库
-static-libgcc:静态链接 gcc 库
-static-libstdc++:静态链接 c++ 库
关于上述命令的详细说明,请参阅 GCC 技术手册

Linux 下静态库(archive)的制作方式:涉及命令:ar ar 简介:处理创建、修改、提取静态库的操作

涉及选项:
t            - 显示静态库的内容
r[ab][f]  - 更新或增加新文件到静态库中
[s]          - 创建文档索引
ar -M [<mri-script] - 使用 ar 脚本处理
其他详细说明请参阅 man 说明。
示例情景:假设现有如 图 7所示两个库文件
图 7. 示例静态库文件图 7中可以得知,CdtLog.a 只包含 CdtLog.o 一个对象文件 , 而 xml.a 包含 TXmlParser.o 和 xmlparser.o 两个对象文件
现将 CdtLog.o 提取出来,然后通过 图 8方式创建一个新的静态库 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 是比较麻烦的,因为涉及到太多的文件处理,可能还要通过不断创建临时目录用于保存中间文件。
推荐使用如 清单 2 createlib.sh所示的 ar 脚本方式进行创建:
清单 2 createlib.sh rm demo.a  rm ar.mac  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所示的代码:
清单 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  )  endef  $(TargetDir)/$(TargetFileName)(OBJS)     $(BUILD_LIBRARY)
通过 图 9,我们可以看到,用这种方式产生的 demo.a 才是我们想要的结果。
图 9. 巧妙创建的静态库文件结果
Linux 静态库链接顺序问题及解决方法:正如 GCC 手册中提到的那样:
It makes a difference where in the command you write this option; 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 loaded.
为了解决这种库链接顺序问题,我们需要增加一些链接选项 :

$(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.
继承事业,薪火相传
返回列表