makefile 学习笔记 十:使用 make 更新库文件

详细内容见 《GNU make》 11 Using make to Update Archive Files 章节。

库文件是包含称为成员的命名子文件的文件;它们与程序ar一起维护,它们的主要用途是作为链接的子例程库。

一、存档成员作为目标

存档文件的单个成员可以在 make 中用作目标或先决条件。您可以在归档文件archive中指定名为member的成员,如下所示:

archive(member)

此构造只在目标和先决条件中可用,在配方中不可用!在配方中可能使用的大多数程序不支持此语法,并且不能直接对归档成员执行操作。只有ar和其他专门设计用于操作档案的程序才能做到这一点。因此,更新存档成员目标的有效配方可能必须使用ar。例如,此规则表示通过复制文件 hack.o 在存档中创建成员 hack.o:

foolib(hack.o) : hack.o
        ar cr foolib hack.o

实际上,几乎所有的存档成员目标都以这种方式更新,并且有一个隐式规则可以为您做这件事。请注意:如果归档文件不存在,则需要 ar 的 ‘c’ 标志。

要在同一个归档文件中指定多个成员,可以将所有成员名写在括号之间。例如:

foolib(hack.o kludge.o)

相当于:

foolib(hack.o) foolib(kludge.o)

您还可以在归档成员引用中使用shell风格的通配符。例如,‘foolib(*.o)’ 扩展到名称以 ‘.o’ 结尾的 foolib 存档的所有现有成员;也许是 ‘foolib(hack.o) foolib(kludge.o)’。

二、存档成员目标的隐式规则

回想一下,看起来像 a(m) 的目标代表存档文件 a 中名为 m 的成员。

当 make 为这样的目标寻找隐式规则时,作为一个特殊特性,它考虑匹配 (m) 的隐式规则,以及匹配实际目标 a(m) 的隐式规则。

这导致匹配一个特殊的规则,其目标是 (%)。该规则通过将文件m复制到归档文件中来更新目标 a(m)。例如,它将通过将文件 bar.o 作为名为 bar.o 的成员复制到存档 foo.a 中来更新存档成员目标 foo.a(bar.o)。

当这个规则与其他规则捆绑在一起时,结果是非常强大的。因此,当文件 bar.c 存在时,‘make “foo.a(bar.o)”’(需要引号来保护 ‘(’ 和 ‘)’ 不被shell特别解释)就足以运行下面的配方,即使没有 makefile:

cc -c bar.c -o bar.o
ar r foo.a bar.o
rm -f bar.o

这里 bar.o 将文件 make 想象成一个中间文件。

像这样的隐式规则是使用自动变量 ‘$%’ 编写的。

归档文件中的归档成员名不能包含目录名,但在makefile中假装包含目录名可能很有用。如果编写存档成员目标 foo.a(dir/file.o),则 make 将使用此配方执行自动更新:

ar r foo.a dir/file.o

它的作用是将文件 file dir/file.o 复制到名为 file.o 的成员中。在这种用法中,自动变量 %D 和 %F 可能是有用的。

1、更新档案符号目录

作为库使用的归档文件通常包含一个名为 __.SYMDEF 的特殊成员,该成员包含由所有其他成员定义的外部符号名的目录。在您更新任何其他成员之后,您需要更新 __.SYMDEF,以便它能够正确地总结其他成员。这是通过运行ranlib程序来完成的:

ranlib archivefile

通常,您将把这个命令放在存档文件的规则中,并使存档文件的所有成员成为该规则的先决条件。例如,

libfoo.a: libfoo.a(x.o) libfoo.a(y.o) …
        ranlib libfoo.a

这样做的效果是更新存档成员 x.o、y.o 等,然后通过运行ranlib更新符号目录成员 __.SYMDEF。这里没有显示更新成员的规则;最可能的情况是,您可以省略它们,并使用隐式规则将文件复制到存档中,如前一节所述。

这在使用 GNU ar 程序时是不必要的,它会自动更新 __.SYMDEF 成员。

三、使用档案的危险

在使用并行执行(-j 开关)和归档时要小心,这是很重要的。如果多个ar命令同时在同一个归档文件上运行,它们将不会知道彼此,并可能破坏文件。

将来的 make 版本可能会提供一种机制,通过序列化在同一存档文件上操作的所有菜谱来避免这个问题。但就目前而言,您必须编写makefile以以其他方式避免这个问题,或者不使用 -j。

四、存档文件的后缀规则

您可以编写一种特殊的后缀规则来处理存档文件。存档后缀规则在 GNU make 中已经过时,因为存档的模式规则是一种更通用的机制。但它们被保留是为了与其他 make 相容。

要为归档文件编写后缀规则,只需使用目标后缀 ‘.a’(存档文件通常使用的后缀)编写后缀规则。例如,下面是从C源文件更新库存档的老式后缀规则:

.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

实际上,这正是 make 在看到以 ‘.a’ 为目标后缀的后缀规则时所执行的操作。任何双后缀规则 ‘.x.a’ 都被转换为具有目标模式 ‘(%.o)’ 和先决模式 ‘%.x’ 的模式规则。

由于您可能希望使用 ‘.a’ 作为某种其他类型的文件的后缀,因此 make 也要以正常方式将存档后缀规则转换为模式规则。因此,双后缀规则 ‘.x.a’ 产生两个模式规则:‘(%.o): %.x’ 和 ‘%.a: %.x’。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值