【发布时间】:2010-09-21 01:08:26
【问题描述】:
使用 distcc 构建项目时的链接阶段是在本地完成的,而不是像编译那样发送到其他计算机来完成,有什么特别的原因吗?阅读 distcc 白页并没有给出明确的答案,但我猜与编译相比,链接目标文件所花费的时间并不是很重要。有什么想法吗?
【问题讨论】:
标签: c++ c gcc compiler-construction build-process
使用 distcc 构建项目时的链接阶段是在本地完成的,而不是像编译那样发送到其他计算机来完成,有什么特别的原因吗?阅读 distcc 白页并没有给出明确的答案,但我猜与编译相比,链接目标文件所花费的时间并不是很重要。有什么想法吗?
【问题讨论】:
标签: c++ c gcc compiler-construction build-process
distcc 的工作方式是在本地预处理输入文件,直到创建单个文件翻译单元。然后该文件通过网络发送并编译。在那个阶段,远程 distcc 服务器只需要一个编译器,它甚至不需要项目的头文件。然后将编译的输出移回客户端并作为目标文件在本地存储。请注意,这意味着不仅链接,而且预处理都在本地执行。这种工作分工对于其他构建工具很常见,例如 ccache(始终执行预处理,然后尝试使用先前缓存的结果解析输入,如果成功则返回二进制文件而不重新编译)。
如果您要实现分布式链接器,则必须确保网络中的所有主机都具有完全相同的配置,否则您必须一次性发送操作所需的所有输入。这意味着分布式编译将产生一组目标文件,并且所有这些目标文件都必须通过网络推送,以便远程系统链接并返回链接的文件。请注意,这可能需要引用并存在于链接器路径中但不存在于链接器命令行中的系统库,因此“预链接”必须确定实际需要发送哪些库集。即使可能,这也需要本地系统猜测/计算所有真正的依赖关系并将它们发送给网络流量,并且实际上可能会减慢进程,因为发送的成本可能大于链接的成本 --if获取依赖项的成本本身并不像链接那么昂贵。
我目前正在处理的项目有一个超过 100M 的静态链接可执行文件。静态库大小不一,但如果分布式系统认为最终的可执行文件是远程链接的,那么它需要的网络流量可能是最终可执行文件的三到五倍(模板,内联......所有这些都出现在所有包含它们的翻译单元,因此会有多个副本在网络中传播)。
【讨论】:
几乎按照定义,链接要求您将所有目标文件放在一个位置。由于 distcc 首先将对象文件放在调用 distcc 的计算机上,因此本地计算机是执行链接的最佳位置,因为对象已经存在。
此外,一旦您开始将库混入其中,远程链接就会变得特别麻烦。如果远程计算机将您的程序与其本地版本的库链接起来,那么当链接的二进制文件返回到本地计算机时,您就会发现潜在的问题。
【讨论】:
编译可以发送到其他机器的原因是每个源文件都是独立编译的。简单来说,对于每个.c 输入文件,都有一个来自编译步骤的.o 输出文件。这可以在任意多台不同的机器上完成。
另一方面,链接收集所有.o 文件并创建一个 输出二进制文件。那里真的没有什么可以分发的。
【讨论】: