为什么我要为库更新重新编译整个程序?

时间:2012-04-22 14:37:15

标签: linux compiler-construction linker shared-libraries

关于以下链接: http://www.archlinux.org/news/libpnglibtiff-rebuilds-move-from-testing/

有人可以向我解释为什么在更新某个库之后应该重建一个程序吗?

这有什么意义,因为“主”文件根本没有改变?

3 个答案:

答案 0 :(得分:15)

如果所涉及的功能的签名没有改变,那么“重建”程序意味着目标文件必须再次链接。你不应该再次编译它们。

API是描述库中公共函数的接口的契约。当编译器生成代码时,它需要知道要传递给每个函数的变量类型,以及按什么顺序。它还需要知道返回类型,因此它知道将从函数返回的数据的大小和格式。编译代码时,库函数的地址可以表示为“库的开头加上140个字节”。编译器不知道绝对地址,因此它只是指定从库开头的偏移量。

库中,函数的内容(即实现)可能会发生变化。当发生这种情况时,代码的长度可能会改变,因此函数的地址可能会发生变化。链接器的工作是了解每个函数的入口点所在的位置,并将这些地址填充到目标代码中以创建可执行文件。

另一方面,如果库中的数据结构已更改且库需要调用者管理内存(这是一种不好的做法,但不幸的是常见),那么将< / em>需要重新编译代码,以便它可以解释更改。例如,如果您的代码使用malloc(sizeof(dataStructure))为大小加倍的库数据结构分配内存,则需要重新编译代码,因为sizeof(dataStructure)将具有更大的值。

答案 1 :(得分:5)

有两种兼容性:API和ABI。

API兼容性与其他程序可能依赖的功能和数据结构有关。例如,如果libfoo的0.1版本定义了一个名为“hello_world()”的API函数,并且版本0.2将其删除,那么任何依赖“hello_world()”的程序都需要更新才能使用新版本的libfoo。

ABI兼容性是关于如何在二进制文件中表示函数,特别是数据结构的假设。例如,如果libfoo 0.1还定义了一个数据结构recipe,其中包含两个字段:“instructions”和“ingredients”,libfoo 0.2在“ingredients”字段之前引入“测量”,那么基于libfoo 0.1配方的程序必须重新编译,因为“指令”和“成分”字段可能位于libfoo.so二进制文件的0.2版本中的不同位置。

答案 2 :(得分:1)

什么是“图书馆”?

如果“库”只是 二进制文件(例如动态链接库,又名“.dll”,“。dylib”或“.so”;或者是静态链接库,也就是“.lib” “或”.a“)那么就没有必要重新编译,重新连接应该足够了(甚至在某些特殊情况下也可以避免)

另一方面,库通常不仅仅包含二进制对象 - 例如头文件可能包含一些内联(或宏)逻辑。 如果是这样,重新链接是不够的,您可能必须重新编译才能使用最新版本的lib。