使用make更新静态库文件
来源:互联网 发布:生物研究所知乎 编辑:程序博客网 时间:2024/05/22 01:57
静态库文件也称为“文档文件”,它是一些.o文件的集合。在Linux(Unix)中使用工具“ar”对它进行维护管理。它所包含的成员(member)是若干.o文件。
1.1 库成员作为目标
一个静态库通常由多个.o文件组成。这些成员(.o文件)可独立的被作为一个规则的目标,库成员作为目标时需要按照如下的格式来书写:
ARCHIVE(MEMBER)
注意,这种书写方式只能出现在规则的目标和依赖,不能出现在规则的命令行中!因为,绝大多数命令不能支持这种语法,命令不能直接对库的成员进行操作。这种表达式在规则的目标或者依赖中,它表示库“ARCHIVE”的成员“MEMBER”。含有这种表达式的规则的命令行只能是“ar”命令或者其它可以对库成员进行操作的命令。例如:下边这个规则用于创建库“foolib”,并将“hack.o”成员加入到库:
foolib(hack.o) : hack.o
ar cr foolib hack.o
实际上,这个规则实现了对库的所有成员进行了更新,其过程使用了隐含规则(创建需要的.o文件)。另外需要注意工具“ar”的用法(可参考ar的man手册)。
如果在规则中需要同时指定库的多个成员,可以将多个成员罗列在括号内,例如:
foolib(hack.o kludge.o)
它就等价于:
foolib(hack.o) foolib(kludge.o)
在描述库的多个成员时也可以使用shell通配符。例如:“foolib(*.o)”,它代表库文件“foolib”的所有.o成员。
1.2 静态库的更新
上一节已经讲述了规则中形如“A(M)”目标的含义,它代表静态库“A”的成员“M”。make为这样的一个目标搜索隐含规则时,可重建“(M)”的隐含规则,同样也被认为是可重建“A(M)”这个目标的隐含规则。
这就出现了一个特殊的模式规则,它的目标模式是“(%)”。这个特殊的规则被用来更新目标“A(M)”,规则将文件“M”拷贝到库“A”中,如果之前在静态库文件“A”不存,则首先创建这个库文件。例如:目标为“foo.a(bar.o)”的规则,执行时将完成:首先使用隐含规则生成其成员“bar.o”,之后将“bar.o”加入到库“foo.a”中。那么“bar.o”就作为库文件“foo.a”的一个成员(当然如果“foo.a”不存在,就会被创建。这个特殊规则的命令行一般都是“ar”命令)。
这个特殊的规则可以和其它隐含规则一起构成一个隐含规则链。因此我们可以直接在命令行中执行“make‘foo.a(bar.o)’”(注意“foo.a(bar.o)”作为命令行选项,需要使用引号,否则shell会将“(”作为特殊字符处理),只要当前目录下存在“bar.c”这个文件,就会执行如下命令:
cc -c bar.c -o bar.o
ar r foo.a bar.o
rm -f bar.o
我们可以看到文件“bar.o”是被作为中间过程文件来处理的。需要说明的是,包含上述命令的规则,在规则的命令行中使用自动化变量“$%”来代表库成员“bar.o”。
在一个静态库(文档文件)中,其所有的成员名是不包含目录描述的。就是说对于静态库,当使用“nm”命令查看其成员时,能够获得的信息只是静态库所包含的成员名字(一系列.o文件,文件名中并没有包含目录)。但我们在Makefile中,采用“A(M)”格式的目标,书写建立(重建或者更新)静态库的规则时,可以指定为库它的成员指定路径。就是说在描述它的成员时,可以使用包含路径的文件名。例如一个规则的目标可以这样书写“foo.a(dir/file.o)”,在这个规则被执行时可能会执行如下的命令:
ar r foo.a dir/file.o
和上边的例子类似,它将指定目录下的.o文件加入到库中,此文件(“dir/file.o”)被作为静态库的一个成员。对于类似这样的目标,重建它的隐含规则的命令行中可能就需要使用自动化变量“%D”和“%F”。
1.2.1 更新静态库的符号索引表
本小节的内容相对简单。前边提到过,静态库文件需要使用“ar”来创建和维护。当给静态库增建一个成员时(加入一个.o文件到静态库中),“ar”可直接将需要增加的.o文件简单的追加到静态库的末尾。之后当我们使用这个库进行连接生成可执行文件时,链接程序“ld”却提示错误,这可能是:主程序使用了之前加入到库中的.o文件中定义的一个函数或者全局变量,但连接程序无法找到这个函数或者变量。
这个问题的原因是:之前我们将编译完成的.o文件直接加入到了库的末尾,却并没有更新库的有效符号表。连接程序进行连接时,在静态库的符号索引表中无法定位刚才加入的.o文件中定义的函数或者变量。这就需要在完成库成员追加以后让加入的所有.o文件中定义的函数(变量)有效,完成这个工作需要使用另外一个工具“ranlib”来对静态库的符号索引表进行更新。
我们所使用到的静态库(文档文件)中,存在这样一个特殊的成员,它的名字是“__.SYMDEF”。它包含了静态库中所有成员所定义的有效符号(函数名、变量名)。因此,当为库增加了一个成员时,相应的就需要更新成员“__.SYMDEF”,否则所增加的成员中定义的所有的符号将无法被连接程序定位。完成更新的命令是:
ranlib ARCHIVEFILE
通常在Makefile中我们可以这样来实现:
libfoo.a: libfoo.a(x.o) libfoo.a(y.o) ...
ranlib libfoo.a
它所实现的是在更新静态库成员“x.o”和“y.o”之后,对静态库的成员“__.SYMDEF”进行更新(更新库的符号索引表)。
如果我们使用GNU ar工具来维护、管理静态库,我们就不需要考虑这一步。GNU ar本身已经提供了在更新库的同时更新符号索引表的功能(这是默认行为,也可以通过命令行选项控制ar的具体行为。可参考 GNU ar工具的man手册)。
1.3 make静态库的注意事项
在make静态库(文档文件)时,特别需要注意:make的并行执行(执行make时使用“-j”选项)给更新静态库带来的影响。因为在同一时刻,当同时使用多个“ar”命令来操作相同的静态库时,将会静损坏态库,甚至导致此静态库不可用。
可能在后期的make版本中,会提供一种在并行执行时防止同时多个“ar”命令对同一静态库的操作的机制。但是就目前的版本来说,这个问题是存在的。因此要求我们在书写Makefile时,加入控制策略来避免make并发执行时多个“ar”命令同时操作同一个静态库文件。或者放弃使用make的并发执行功能。
1.4 静态库的后缀规则
静态库的后缀规则属于后缀规则的特殊应用,后缀规则在目前版本的GNU make中已经被模式规则替代。但目前版本make同样支持旧风格的后缀规则,主要是为了兼容老版本的make。对于静态库的重建也可以使用后缀规则。目标后缀需要是“.a”(在Linux(Unix)中、静态库的后缀为.a)。例如这样一个后缀规则:
.c.a:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
它相当于模式规则:
(%.o): %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
对于老风格的后缀规则,它的目标是“.a.c”,当转换为模式规则时。后缀规则中的“.a”被作为模式规则的目标文件后缀(目标文件就是N.a);“.c”被作为了模式规则依赖文件的后缀(依赖文件就是N.c)。
存在这样一种情况:可能一个不是静态库的文件使用了后缀.a。那么make也会按照正常的方式静态库的后缀规则转换成为一个模式规则。因此对于一个双后缀规则的目标“.x.a”,经过make转换后会产生两个模式规则:“(%.o): %.x”和“%.a: %.x”。具体的转换过程可参考后缀规则一节
总结:
ar t libxxx.a 可查看该静态库包含那几个.o文件
nm libxxx.a 可查看该静态库内所包含的所有成员函数。“U”后面为C库函数,“T”后面为自定义的函数。
nm libxxx.a | grep XXX 可查看该静态库中是包含某个函数
ar命令参数:
x 命令解出来, a 命令添加, t命令列表
如何将静态库合并:
假设A.a, B.a C.a 在/usr/local/lib目录下
mkdir /tmp/libABC
cd /tmp/libABC
ar x /usr/local/lib/A.a
ar x /usr/local/lib/B.a
ar x /usr/local/lib/C.a
ar cru libABC.a *.o
ranlib libABC.a //ranlib作用:对静态库的符号索引表进行更新,相当于"ar -s"
//如果使用GNU ar工具来维护、管理静态库,就不需要考虑这一步。GNU ar本身已经提供了在更新库的同时更新符号索引表的功能(这是默认行为,也可以通过命令行选项控制ar的具体行为。)
- 使用make更新静态库文件[转载]
- 使用make更新静态库文件
- 使用make更新静态库文件
- 第十一章:使用make更新静态库文件
- make(九)使用make更新函数库文件
- [转]使用makefile更新静态库文件
- Makefile之使用make更新函数库文件
- Makefile (十一) 使用make 更新函数库文件
- 10 使用make更新函数库文件
- Makefile详解-使用make更新函数库文件
- makefile高级用法--使用make更新函数库文件
- makefile详解 使用make更新函数库文件(结束) 二十六
- makefile详解 (十一) 使用make更新函数库文件
- Makefile (九)之 使用make更新函数库文件
- 如何将静态库文件Make到指定目录
- 关于linux下make文件连接静态库的问题
- 第四、静态库的使用 待更新
- 跟我一起写makefile-10(使用make更新函数库文件)
- 学会冒泡排序算法
- 程序调试中莫名其妙的bug
- 打印出系统上所有的字体名
- Oracle横表、纵表一点记录
- 别人的VC++笔记
- 使用make更新静态库文件
- 利用存储过程写入测试数据
- 10个工具让你的 shell 脚本更强大
- 第五周作业
- 2011年11月27日 学会使用循环控制语句解决实际问题
- PowerShell脚本从csv文件批量导入AD账户
- long way to go
- amCharts使用方式
- LD_LIBRARY_PATH