改变CHOST变量

From Gentoo Wiki
Jump to:navigation Jump to:search
This page is a translated version of the page Changing the CHOST variable and the translation is 73% complete.
Outdated translations are marked like this.
Other languages:
English • ‎español • ‎français • ‎русский • ‎中文(中国大陆)‎ • ‎日本語 • ‎한국어

本文档解释了如何更改现有系统的 CHOST 变量。

介绍

更改 CHOST 是一个大问题,可能会严重搞砸系统——那么,如果它会造成如此大的破坏,为什么会有此指南?

在某些情况下,更改 CHOST 变量是不可避免的,例如当升级到仅支持 NTPL 的 glibc 2.4 时,用户发现当前的 CHOST 是 i386,导致无法使用 NTPL。在这种情况下,没有很多选择,更改 CHOST 就是其中之一。

即使按照这些说明进行操作,也可能会出现问题,因此请务必仔细阅读并执行这些说明。在本例中,CHOST 变量将从 i386 更改为 i686。请根据具体情况更改命令。

改变CHOST变量

更新 make.conf

要开始更改 CHOST 变量,请编辑 /etc/portage/make.conf 文件并添加/更改 CHOST 值以适应要求。

FILE /etc/portage/make.conf
CHOST="i686-pc-linux-gnu"

请注意,如果你计划使用其它 CHOST 值而不是特定配置文件默认值,你可能还需要更新 CHOST_${ABI} 变量。你可以通过“portageq”工具查询这些变量的当前值:

user $portageq envvar ABI
x86
user $portageq envvar CHOST_x86
i686-pc-linux-gnu

如果相应值等于你的 CHOST,那没问题。否则你应该覆盖它,例如:

FILE /etc/portage/make.conf
CHOST_x86="i686-pc-linux-gnu"

构建包

Important
It is generally a good idea to rebuild the packages to the same versions as before the CHOST switch, i.e. avoiding combining upgrades with it. If you have multiple slots installed, either uninstall extraneous slots or rebuild all of them. If you can't do that, please upgrade the packages first (with old CHOST). While it may not be impossible to do so, it is hard to predict which potential problems may arise and almost impossible to document them in this guide.
Tip
On a system with CHOST set to an i386 value, mask glibc 2.4 (or newer) during the gcc upgrade as it cannot be used with i386. Unmask it once the change has been performed completely.

按此顺序重建以下包:

root #emerge --ask --oneshot sys-devel/binutils
附注
在编译 gcc 之前可能需要运行 binutils-config
root #emerge --ask --oneshot sys-devel/gcc
root #emerge --ask --oneshot sys-libs/glibc

配置验证

Now it is time to make sure that the gcc-config and binutils-config settings are sane and that there are no leftovers in /etc/env.d/.

The output of gcc-config and binutils-config should look like the following:

附注
输出可能,甚至会根据 gcc 版本和 CHOST 设置而有所不同。以下示例为在 i686 上使用 gcc 4.1.1。
root #gcc-config -l
 [1] i686-pc-linux-gnu-4.1.1 *
root #gcc-config -c
i686-pc-linux-gnu-4.1.1
root #binutils-config -l
 [1] i686-pc-linux-gnu-2.16.1 *
# binutils-config -c
i686-pc-linux-gnu-2.16.1

接下来,检查 /etc/env.d/ 中是否存在对旧的 CHOST 变量的引用:

root #cd /etc/env.d/
root #grep 386 *
05gcc-i386-pc-linux-gnu:PATH="/usr/i386-pc-linux-gnu/gcc-bin/4.1.1"
05gcc-i386-pc-linux-gnu:ROOTPATH="/usr/i386-pc-linux-gnu/gcc-bin/4.1.1"
Note
This may not happen in every case, but in this case 05gcc-i386-pc-linux-gnu contains references to the old CHOST value. Things may look differently on each system depending on which CHOST value the system is changing to/from. In some cases, no references are left at all. The name may also be 05gcc-new_CHOST-pc-linux-gnu.

在删除文件之前,让我们检查已更新 CHOST 值的文件:

root #grep 686 *
05binutils:MANPATH=/usr/share/binutils-data/i686-pc-linux-gnu/2.16.1/man
05binutils:INFOPATH=/usr/share/binutils-data/i686-pc-linux-gnu/2.16.1/info
05binutils:LDPATH=/usr/i686-pc-linux-gnu/lib
05gcc:PATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
05gcc:ROOTPATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
05gcc:MANPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/man"
05gcc:INFOPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/info"
05gcc:LDPATH="/usr/lib/gcc/i686-pc-linux-gnu/4.1.1"

This one looks good as there should always be only one file for gcc in /etc/env.d/ (05gcc in this example), so delete the one with the wrong references:

root #rm 05gcc-i386-pc-linux-gnu

The same also applies to binutils - if there's an extra one, see which is the outdated one and delete it. Next, check the contents of /etc/env.d/binutils/:

root #cd /etc/env.d/binutils/
root #ls -la
total 8
-rw-r--r-- 1 root root  15 Sep  3 13:48 config-i686-pc-linux-gnu
-rw-r--r-- 1 root root 126 Sep  3 13:48 i686-pc-linux-gnu-2.16.1
root #cat config-i686-pc-linux-gnu
CURRENT=2.16.1
root #cat i686-pc-linux-gnu-2.16.1
TARGET="i686-pc-linux-gnu"
VER="2.16.1"
LIBPATH="/usr/lib/binutils/i686-pc-linux-gnu/2.16.1"
FAKE_TARGETS="i686-pc-linux-gnu"

那个看起来不错,那两个文件应该在那里。是时候进入 gcc/ 目录了。

root #cd /etc/env.d/gcc
# ls -la
total 12
-rw-r--r-- 1 root root  32 Sep  3 16:43 config
-rw-r--r-- 1 root root  32 Aug  3 14:25 config-i386-pc-linux-gnu
-rw-r--r-- 1 root root 292 Sep  3 16:43 i686-pc-linux-gnu-4.1.1
root #cat config
CURRENT=i686-pc-linux-gnu-4.1.1
root #cat config-i386-pc-linux-gnu
CURRENT=i386-pc-linux-gnu-4.1.1
root #cat i686-pc-linux-gnu-4.1.1
PATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
ROOTPATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
LDPATH="/usr/lib/gcc/i686-pc-linux-gnu/4.1.1"
GCCBITS="32"
MANPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/man"
INFOPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/info"
STDCXX_INCDIR="g++-v4"

config and i686-pc-linux-gnu-4.1.1 are fine, but config-i386-pc-linux-gnu is another leftover that needs removal.

Note
Again, the name of the file containing references to an outdated gcc version may have a different name, e.g. config-i686-pc-linux-gnu even though the system is being changed to (in this case) i686. It is important to identify the file on its content, not only the name.
root #rm config-i386-pc-linux-gnu

现在运行以下命令来更新环境:

root #env-update && source /etc/profile

接下来,验证一切都已修复:

root #grep -r 386 /etc/env.d/

如果仍然能找到相关文件,请在继续之前尝试对其进行追踪。

完成更改

Now it is necessary to re-emerge sys-devel/libtool and run fix_libtool_files.sh which can be found in /usr/share/gcc-data/$CHOST/<gcc-version>/. Make sure to use the correct gcc version (the current one, 4.1.1 here) and pass the old architecture (i386 here) as argument. Replace $CHOST with the new CHOST value, and <gcc-version> with the gcc version. This example assumes a CHOST value applicable to i686.

root #emerge --ask --oneshot libtool
root #/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/fix_libtool_files.sh 4.1.1 --oldarch i386-pc-linux-gnu

现在可以重建所有包:

root #emerge --ask --emptytree @world

In theory, it should not be necessary to do so, but it cannot be 100% guaranteed that this is actually the case. Alternatively, you can manually rebuild all the known problematic packages:

  • multilib packages using CHOST prefixing or header wrapping,
  • Perl, Python and other tools that store configured compiler path.
root #emerge --ask --oneshot /usr/bin/i386-pc-linux-gnu-* /usr/include/i386-pc-linux-gnu /usr/lib/llvm/*/bin/i386-pc-linux-gnu-* dev-lang/perl dev-lang/python

请注意,你可能需要从上述调用中删除不适用于系统的路径。

When encountering other packages that need recompiling, please let us know through the discussion page of this guide.

常见问题

When upgrading from gcc 3.3 to 4.1 at the same time as changing the CHOST variable (please don't do that anyway), a couple of users reported broken packages that need recompiling, such as sys-apps/groff and mail-mta/courier:

CODE 错误信息
error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory

This happens because during the upgrade, the CHOST variable doesn't exactly match the CTARGET variable value, making the compiler assume that the system is using cross-compiling. As a consequence, LDPATH isn't inserted into ld.so.conf, resulting in this error.

Please see the GCC upgrade guide for what needs to be rebuilt after a GCC upgrade.

In some rare cases, this can break old versions of python, too. This may be fixed by adding /usr/lib/gcc-lib/i386-pc-linux-gnu/3.3.6 (change accordingly to the old CHOST and gcc version) to /etc/ld.so.conf, running ldconfig and then emerge libstdc++-v3. However, as can be seen, this situation needs to be avoided - don't change CHOST and gcc at the same time.

反馈

That should be all, feedback (both if it worked, failed or other problems were encountered) is welcome, please use the discussion page or post to this forum thread. Much in this guide comes from vapier, thanks for your help!


This page is based on a document formerly found on our main website gentoo.org.
The following people contributed to the original document: Wernfried Haas, Mike Frysinger (vapier) , Chris White
They are listed here because wiki history does not allow for any external attribution. If you edit the wiki article, please do not add yourself here; your contributions are recorded on each article's associated history page.