如何根据主机系统上存在的内容为 binutils、gcc 和其他链接到不同库的包创建二进制包(rpm、deb 等)?
在 LFS 项目中,为了将新系统与主机隔离,交叉编译是通过为新系统使用不同的目标三元组来伪造的(此处)。这可以防止包链接到仅存在于主机系统上的库。但是,如果使用类似的方法来构建二进制包,那么这些包肯定会有与构建它们的系统不同的目标三元组。
我阅读了这封电子邮件,其中讨论了构建主机隔离的 gcc。但得出的结论是,像 LFS 那样伪造交叉编译是构建与主机系统隔离的 gcc 的唯一合理方法。
我尝试构建带有 --prefix 和 --with-sysroot 设置为空目录的 binutils,但生成的二进制文件链接到我的主机系统上的 libfl。
编辑:
我认为我最初的解释并不清楚。请允许我举一个更具体的例子:
GNU 的 binutils不依赖于 GNU flex,我可以通过在我的 arch 系统上运行来验证这一点,ldd /usr/bin/ar
我发现它没有链接到libfl.so
. 尽管如此,我仍然在我的主机系统上安装了 flex。现在,我想编译一个 binutils 二进制文件,并将其复制到另一个具有相同架构的系统中。这个新系统没有安装 GNU flex,但这应该无关紧要,因为 binutils 不依赖于 GNU flex。问题是当我在我的主机系统上编译 binutils 时,它链接到libfl.so.2
!我认为这是因为当我构建 binuitls 时,它“注意到”我安装了 flex,所以决定链接到它。我想知道如何编译软件(如 binutils)而不链接到我的主机系统上存在的可选依赖项(如 flex)。二进制包维护者在尝试编译他们的软件时肯定会遇到同样的问题吗?
Binutils 只是这种情况下的一个例子,我真的在寻找一种更通用的方法,包维护者可以使用它来阻止他们的软件链接到主机系统中的可选依赖项。
我可能弄错了,但我认为答案(通常)是它们没有与主机系统隔离。
他们没有。rpm、deb 等指定依赖关系,包括版本,并且针对不同的架构具有不同的 RPM。换句话说,rpms 和 debs 是基于目标系统看起来都一样的想法。
目标系统和构建系统看起来一样吗?我不是包维护者,所以可能有一些我不知道的魔法。我的理解是,这是通过构建与目标系统相同类型的系统来实现的。至少构建环境将是一些chroot布局,就像目标环境一样。
LFS 有一个微妙之处,我认为当我读到它时(15 年前)他们并没有说出来。在 LFS 中,您从没有系统开始,因此您获得了一些工具并开始构建系统的基本块。但是你必须从外面向内看,否则你就有鸡和蛋的问题。最初没有系统,您无法在系统内部构建。
我不认为他们在 LFS 中真正呼吁的是,一旦您安装了系统,就不需要从外部编译包。您可以使用该系统来构建自己的包。如果您打算使用它们来替换该系统本身的位,或者如果您打算使用它们分发到其他类似系统,这两种方法都有效。
最初这是一个令人抓狂的概念。就像用 C 编写 C 编译器一样。首先用别人的 C 编译器编译你的 C 编译器,然后用你的 C 编译器重新编译你的 C 编译器。然后你可以扔掉你从别人那里得到的。
在基于 rpm 的世界中,我们使用Mock构建工具。Mock 使用 systemd-nspawn 容器创建一个隔离的环境。它仅安装最小的依赖项集,并且构建是在容器中完成的。因此它与宿主环境完全隔离。事实上,构建环境甚至可以有不同的架构。