为什么我应该为了库更新而重新编译整个程序?

问题描述 投票:0回答:3

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

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

既然“主”文件根本没有改变,这有什么意义呢?

linux linker shared-libraries
3个回答
19
投票

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

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

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

另一方面,如果库中的数据结构发生了变化,并且库要求调用者管理内存(这是一种不好的做法,但不幸的是很常见),那么您需要重新编译代码,以便它可以考虑为了改变。 例如,如果您的代码使用

malloc(sizeof(dataStructure))
为大小加倍的库数据结构分配内存,则需要重新编译代码,因为
sizeof(dataStructure)
将具有更大的值。


7
投票

兼容性有两种:API 和 ABI。

API兼容性是指其他程序可能依赖的函数和数据结构。例如,如果 libfoo 0.1 版定义了一个名为“hello_world()”的 API 函数,而 0.2 版删除了它,则任何依赖“hello_world()”的程序都需要更新才能使用新版本的 libfoo。

ABI 兼容性是关于如何在二进制文件中表示函数(特别是数据结构)的假设。例如,如果 libfoo 0.1 还定义了一个包含两个字段的数据结构

recipe
:“指令”和“成分”,并且 libfoo 0.2 在“成分”字段之前引入了“测量”,则必须重新编译基于 libfoo 0.1 配方的程序,因为“在 0.2 版本的 libfoo.so 二进制文件中,“说明”和“成分”字段可能位于不同的位置。


2
投票

什么是“图书馆”?

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

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

© www.soinside.com 2019 - 2024. All rights reserved.