<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
  <!ENTITY % general-entities SYSTEM "../general.ent">
  %general-entities;
]>

<sect1 id="ch-tools-gcc-pass2" role="wrap">
  <?dbhtml filename="gcc-pass2.html"?>

  <sect1info condition="script">
    <productname>gcc</productname>
    <productnumber>&gcc-version;</productnumber>
    <address>&gcc-url;</address>
  </sect1info>

  <title>GCC-&gcc-version; - 第二遍</title>

  <indexterm zone="ch-tools-gcc-pass2">
    <primary sortas="a-GCC">GCC</primary>
    <secondary>tools, pass 2</secondary>
  </indexterm>

  <sect2 role="package">
    <title/>

    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
    href="../chapter06/gcc.xml"
    xpointer="xpointer(/sect1/sect2[1]/para[1])"/>

    <segmentedlist>
      <segtitle>&buildtime;</segtitle>
      <segtitle>&diskspace;</segtitle>

      <seglistitem>
        <seg>&gcc-ch5p2-sbu;</seg>
        <seg>&gcc-ch5p2-du;</seg>
      </seglistitem>
    </segmentedlist>

  </sect2>

  <sect2 role="installation">
    <title>安装 GCC</title>

    <!--para>Our first build of GCC has installed a couple of internal system
    headers.  Normally one of them, <filename>limits.h</filename>, will in turn
    include the corresponding system <filename>limits.h</filename> header, in
    this case, <filename>/tools/include/limits.h</filename>. However, at the
    time of the first build of gcc <filename>/tools/include/limits.h</filename>
    did not exist, so the internal header that GCC installed is a partial,
    self-contained file and does not include the extended features of the
    system header. This was adequate for building the temporary libc, but this
    build of GCC now requires the full internal header.  Create a full version
    of the internal header using a command that is identical to what the GCC
    build system does in normal circumstances:</para-->
    <para>第一次构建的 GCC 安装了若干内部系统头文件，其中有一个
		<filename>limits.h</filename>。一般来说，
		它应该包含对应的系统头文件，对于我们的特例而言，就是
		<filename>/tools/include/limits.h</filename>。
		然而，在第一次构建 GCC 的时候，它还不存在，
		因此 GCC 安装的内部头文件是一个不完整的、自给自足的文件，
		不包含系统头文件提供的扩展特性。这对于构建临时的 libc 已经足够了，
		但构建 GCC 需要完整的内部头文件。
		使用以下命令创建一个完整版本的内部头文件，
		该命令与 GCC 构建系统在一般情况下生成头文件的命令一模一样：</para>

<screen><userinput remap="pre">cat gcc/limitx.h gcc/glimits.h gcc/limity.h &gt; \
  `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include-fixed/limits.h</userinput></screen>
<!--
    <para>For x86 machines, the limited number of registers is a bottleneck
    for the system.  Free one up by not using a frame pointer that is not
    needed:</para>

<screen><userinput remap="pre">case `uname -m` in
  i?86) sed -i 's/^T_CFLAGS =$/&amp; -fomit-frame-pointer/' gcc/Makefile.in ;;
esac</userinput></screen>
-->
    <!--para>Once again, change the location of GCC's default dynamic linker to
    use the one installed in <filename
    class="directory">/tools</filename>.</para-->
	<para>再一次地，改变 GCC 的默认动态链接器，使其使用
		<filename class="directory">/tools</filename> 中的动态链接器：
	</para>

<screen><userinput remap="pre">for file in gcc/config/{linux,i386/linux{,64}}.h
do
  cp -uv $file{,.orig}
  sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&amp;@g' \
      -e 's@/usr@/tools@g' $file.orig &gt; $file
  echo '
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"
#define STANDARD_STARTFILE_PREFIX_2 ""' &gt;&gt; $file
  touch $file.orig
done</userinput></screen>

    <!--para>If building on x86_64, change the default directory name for 64-bit
    libraries to <quote>lib</quote>:</para-->
    <para>如果是在 x86_64 上构建，修改 64 位库文件的默认目录名为
		<quote>lib</quote>：</para>

<screen><userinput remap="pre">case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
  ;;
esac</userinput></screen>

    <!--para>As in the first build of GCC it requires the GMP, MPFR and MPC
    packages. Unpack the tarballs and move them into the required directory
    names:</para-->
    <para>就像第一次构建 GCC 时一样，它需要 GMP、MPFR 和 MPC 三个包。
		解压它们的源码包，并将它们移动到 GCC 要求的目录名：</para>

<screen><userinput remap="pre">tar -xf ../mpfr-&mpfr-version;.tar.xz
mv -v mpfr-&mpfr-version; mpfr
tar -xf ../gmp-&gmp-version;.tar.xz
mv -v gmp-&gmp-version; gmp
tar -xf ../mpc-&mpc-version;.tar.gz
mv -v mpc-&mpc-version; mpc</userinput></screen>
<!--
    <para>As in the first build of GCC, fix a problem identified upstream:</para>

<screen><userinput remap="pre">sed -i 's/if \((code.*))\)/if (\1 \&amp;\&amp; \!DEBUG_INSN_P (insn))/' gcc/sched-deps.c</userinput></screen>
-->
    <para>再次创建一个独立的构建目录：</para>

<screen><userinput remap="pre">mkdir -v build
cd       build</userinput></screen>

    <!--para>Before starting to build GCC, remember to unset any environment
    variables that override the default optimization flags.</para-->
    <para>在开始构建 GCC 前，记得清除所有覆盖默认优化开关的环境变量。
    </para>

	<para>现在准备编译 GCC：</para>

<screen><userinput remap="configure">CC=$LFS_TGT-gcc                                    \
CXX=$LFS_TGT-g++                                   \
AR=$LFS_TGT-ar                                     \
RANLIB=$LFS_TGT-ranlib                             \
../configure                                       \
    --prefix=/tools                                \
    --with-local-prefix=/tools                     \
    --with-native-system-header-dir=/tools/include \
    --enable-languages=c,c++                       \
    --disable-libstdcxx-pch                        \
    --disable-multilib                             \
    --disable-bootstrap                            \
    --disable-libgomp</userinput></screen>

    <variablelist>
      <title>配置选项的含义：</title>

      <varlistentry>
        <term><parameter>--enable-languages=c,c++</parameter></term>
        <listitem>
          <!--para>This option ensures that both the C and C++ compilers are
          built.</para-->
          <para>该选项保证只构建 C 和 C++ 编译器。</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term><parameter>--disable-libstdcxx-pch</parameter></term>
        <listitem>
          <!--para>Do not build the pre-compiled header (PCH) for
          <filename class="libraryfile">libstdc++</filename>. It takes up a
          lot of space, and we have no use for it.</para-->
          <para>不构建 <filename class="libraryfile">libstdc++</filename>
			  的预编译头文件，它占据大量空间，而且我们用不到它。</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term><parameter>--disable-bootstrap</parameter></term>
        <listitem>
          <!--para>For native builds of GCC, the default is to do a "bootstrap"
          build. This does not just compile GCC, but compiles it several times.
          It uses the programs compiled in a first round to compile itself a
          second time, and then again a third time.  The second and third
          iterations are compared to make sure it can reproduce itself
          flawlessly. This also implies that it was compiled correctly.
          However, the LFS build method should provide a solid compiler
          without the need to bootstrap each time.</para-->
          <para>对于 GCC 的本地构建，默认会进行自举 (bootstrap) 构建。
			  这种构建方式不仅编译 GCC ，还会将它编译多次。
			  它使用第一轮编译得到的程序，将自身再编译一次，
			  然后再用第二轮编译得到的程序将自身编译第三次。
			  第二次和第三次的结果被比较，
			  从而确认 GCC 可以没有缺陷地重新编译它自己，
			  这就表明编译过程准确无误。然而， LFS
			  的构建方法能够提供一个坚实的编译器，而不需要每次都进行自举。
		  </para>
        </listitem>
      </varlistentry>

    </variablelist>

    <para>编译该软件包：</para>

<screen><userinput remap="make">make</userinput></screen>

    <para>安装该软件包：</para>

<screen><userinput remap="install">make install</userinput></screen>

    <!--para>As a finishing touch, create a symlink. Many programs and scripts
    run <command>cc</command> instead of <command>gcc</command>, which is
    used to keep programs generic and therefore usable on all kinds of UNIX
    systems where the GNU C compiler is not always installed. Running
    <command>cc</command> leaves the system administrator free to decide
    which C compiler to install:</para-->
    <para>最后，还需要创建一个符号链接。许多程序和脚本运行
		<command>cc</command> 而不是 <command>gcc</command>，
		因为前者能够保证程序的通用性，使它可以在所有 UNIX 系统上使用，
		无论是否安装了 GNU C 编译器。运行 <command>cc</command>
		可以将安装哪种 C 编译器的选择权留给系统管理员。</para>

<screen><userinput remap="install">ln -sv gcc /tools/bin/cc</userinput></screen>

  <caution>
    <!--para>At this point, it is imperative to stop and ensure that the basic
    functions (compiling and linking) of the new toolchain are working as
    expected. To perform a sanity check, run the following commands:</para-->
    <para>在此时，很有必要暂停构建过程，确认新工具链的基本功能
		（编译和链接）能够如同我们期望的那样工作。
		执行以下命令，进行完整性检查：</para>

<screen><userinput>echo 'int main(){}' &gt; dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'</userinput></screen>

    <!--para>If everything is working correctly, there should be no errors,
    and the output of the last command will be of the form:</para-->
    <para>如果一切正常，这些命令应该不产生错误，
		且最后一行命令的输出格式应该和下面相同：</para>

<screen><computeroutput>[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]</computeroutput></screen>

    <!--para>Note that <filename class="directory">/tools/lib</filename> wiil
    be the prefix of the dynamic linker for 32-bit machines.</para-->
    <para>注意，在 32 位机器上，动态链接器为
		<filename class="directory">/tools/lib/ld-linux-so.2</filename>。
	</para>

    <!--para>If the output is not shown as above or there was no output at all,
    then something is wrong. Investigate and retrace the steps to find out
    where the problem is and correct it. This issue must be resolved before
    continuing on. First, perform the sanity check again, using
    <command>gcc</command> instead of <command>cc</command>. If this works,
    then the <filename class="symlink">/tools/bin/cc</filename> symlink is
    missing. Install the symlink as per above.
    Next, ensure that the <envar>PATH</envar> is correct. This
    can be checked by running <command>echo $PATH</command> and verifying that
    <filename class="directory">/tools/bin</filename> is at the head of the
    list. If the <envar>PATH</envar> is wrong it could mean that you are not
    logged in as user <systemitem class="username">lfs</systemitem> or that
    something went wrong back in <xref linkend="ch-tools-settingenviron"
    role="."/></para-->
	<para>如果输出并不像上面展示的那样，或者根本没有输出，
		则表明出现了问题。检查并重新跟踪各个步骤，找到问题的原因并纠正它。
		这个问题在继续构建前必须解决。首先，使用 <command>gcc</command>
		命令代替 <command>cc</command>，再次进行完整性检查。
		如果这次编译器正常工作，则说明
		<filename class="symlink">cc</filename> 符号链接不存在，
		按照之前的说明安装该符号链接。另外，还要确认 <envar>PATH</envar>
		环境变量正确。运行 <command>echo $PATH</command> 命令，
		确认 <filename class="directory">/tools/bin</filename>
		出现在列表的开头。如果 <envar>PATH</envar> 是错的，
		表明你很可能没有以用户
		<systemitem class="username">lfs</systemitem> 的身份登录，
		或者在 <xref linkend="ch-tools-settingenviron"/>
		的过程中出现了问题。</para>

    <para>在一切检查顺利后，即可删除测试文件：</para>

<screen><userinput>rm -v dummy.c a.out</userinput></screen>

  </caution>

  </sect2>

  <sect2 role="content">
    <title/>

    <para>关于本软件包的更多信息可以在
    <xref linkend="contents-gcc"/> 中找到。</para>

  </sect2>

</sect1>
