Building GCC

来自osdev
跳到导航 跳到搜索
难度等级
Difficulty 1.png
初学者

在本教程中,我们将你的系统 GCC 升级到最新版本。(译者注:本文主要说明了从源代码构建GCC的过程,这个过程中通过现有GCC构建GCC,是一个Bootstrap自举过程。注意这里不是要构建交叉编译器,就是构建一个普通主机Host编译器) 这将帮助你构建GCC交叉编译器,在构建交叉编译器时更建议你使用相同版本的编译器。 其实只要稍加小心,你也许就不必自举(bootstrap)新的现有系统编译器,但这是有风险的,而且可能会带来麻烦。 想要使用最新版本的交叉编译器,你应该为系统编译器和交叉编译器使用相同的主要编译器版本。

另见关于建造GCC的官方指示

导言

编译器通过称为自举(bootstrap)的过程进行升级。 首先,也许你的旧系统编译器生成的代码较慢慢,并不支持所有的新语言特性。 所以你可以使用这个旧的系统编译器来构建(build)新版本的编译器,希望旧的编译器能够构建新的编译器 (它支持所有需要的功能)。 这将生成一个新的编译器,新编译器可以生成较快速的代码并支持所有新功能,但也许本身速度较慢,因为它是用一个生成较慢代码的旧编译器编译的。 此外,新的编译器可能有错误,因为你的旧编译器的编译功能有错误,或者新的编译器版本中可能有错误。

下一步是使用产生更好代码的新编译器,然后再次构建新的编译器。 这将生成一个快速编译器,生成快速代码。 然而,我们构建的第一个编译器可能有错误,而我们刚刚使用它构建的编译器可能也有缺陷。 最后我们需要验证产生快速代码的新快速编译器的正确性。

为了解决这个问题,我们“第三次”构建编译器。(译者注:第一个编译器是原来的旧编译器,第二个编译器是用旧编译器从源代码构建的新编译器,第三个编译器是用新编译从同样源代码构建的另一个新编译器) 一旦我们使用第二个编译器构建了第三个编译器,第二个编译器的第一个编译器它们产生的输出应该完全相同,因为我们两次都使用了生成快速代码并使用相同源代码的编译器。 然后,编译器构建系统将验证第二个和第三个编译器是否相同,这使你对自举过程充满信心。 如果第二个和第三个编译器不相同,则自举失败,你遇到了编译器错误。 自举所需的时间是仅构建常规编译器的三倍,但它可以确保你的工具链是稳定的。

最后要做的是运行编译器测试套件,以便你可以验证它是否正常工作。

请注意,如果使用GCC4.4构建GCC4.8交叉编译器,以上同样的问题也可能会发生。 因此,建议使用GCC 4.8构建GCC 4.8交叉编译器,这样你能明确不会出现新旧这样的问题。 你不能自举交叉编译器,因为它不会为本地操作系统生成程序。

我需要自举过程吗?

如果你的系统编译器是与你希望构建的编译器版本相同的主要版本 (例如,如果你有4.6.2并想要4.6.3),那么你也许不需要自举。 小版本通常非常兼容。 你也许也能在没有自举的情况下构建另一个主要版本(如4.6.3构建4.7.3),但它可能不会生成理想的编译器。 随着编译器版本之间的差距扩大,你很可能会遇到麻烦。 每个主要的编译器版本应该总是能够使用自举构建下一个版本。 如果你有耐心,有可能找到一个非常老的LINUX系统和一个非常老的GCC版本,然后引导到最新的GCC版本,只需几次迭代升级主要的编译器版本。

你也可以通过其他渠道升级系统编译器。

我需要哪个编译器版本?

推荐使用最新的 GCC,因为它是最新最好的版本。 目前,GCC 4.9.2是最新版本。 我们建议你使用交叉编译器的最新编译器版本。 你也可以使用较旧的版本,因为它们通常相当不错。 如果你的本地系统编译器不是太旧(至少GCC 4.6.0),你可能希望避免麻烦,只需为交叉编译器选择最新的次要版本(在你的系统编译器是4.6.1时,比如4.6.3)。 在这种情况下,你不需要自举,可以直接构建你的GCC交叉编译器

你可以这样查看你当前的编译器版本:

gcc --version

如果你有耐心并希望自己构建最新、最棒的交叉编译器,那么在构建GCC交叉编译器之前,你需要自举系统编译器。

我还需要新的Binutils吗?

如果你的Binutils不是太过时,当然也不会有什么大碍,对于你的新系统编译器来说应该足够好。 你可以通过调用以下命令查看当前的Binutils版本:

ld --version

你可能至少需要Binutils 2.22,或者最好是最新的2.25版本。

准备构建

难度等级
Difficulty 1.png
初学者


GNU编译器集合是一个具有依赖关系的高级软件。 为了构建GCC,你需要以下内容:

  • 类Unix的环境(Windows用户可以使用Linux或Cygwin的Windows子系统)
  • 足够的内存和硬盘空间 (视情况而定,256 MiB不够)。
  • GCC(有的待替换发行版)或其他system C编译器
  • G++(如果构建GCC的版本>=4.8.0),或其他system C++编译器
  • Make
  • Bison
  • Flex
  • GMP
  • MPFR
  • MPC
  • Texinfo
  • ISL (optional)
  • CLooG (optional)

安装依赖项

↓ Dependency / OS → 源代码 Debian (Ubuntu, Mint, WSL, ...) Gentoo Fedora Cygwin OpenBSD Arch
如何安装 Normally sudo apt install foo sudo emerge --ask foo sudo dnf install foo Cygwin GUI setup doas pkg_add foo pacman -Syu foo
Compiler N/A build-essential sys-devel/gcc gcc gcc-c++ mingw64-x86_64-gcc-g++ / mingw64-i686-gcc-g++ Preinstalled base-devel
Make N/A build-essential sys-devel/make make make Preinstalled base-devel
Bison [1] bison sys-devel/bison bison bison ? base-devel
Flex [2] flex sys-devel/flex flex flex ? base-devel
GMP [3] libgmp3-dev dev-libs/gmp gmp-devel libgmp-devel gmp gmp
MPC [4] libmpc-dev dev-libs/mpc libmpc-devel libmpc-devel libmpc libmpc
MPFR [5] libmpfr-dev dev-libs/mpfr mpfr-devel libmpfr-devel mpfr mpfr
Texinfo [6] texinfo sys-apps/texinfo texinfo texinfo texinfo base-devel
CLooG (Optional) CLooG libcloog-isl-dev dev-libs/cloog cloog-devel libcloog-isl-devel N/A N/A
ISL (Optional) [7] libisl-dev dev-libs/isl isl-devel libisl-devel N/A N/A

你需要安装Texinfo来构建Binutils。 你需要安装GMP、MPC和MPFR来构建GCC。 GCC可以选择使用ClooG和isl库。

例如,你可以通过运行shell命令在Debian上安装 libgmp3-dev: sudo apt install libgmp3-dev

注意:第5版。已知Texinfo的x(或更高版本)与当前的Binutils 2.23.2版本(及更早版本)不兼容。 你可以使用makeinfo--version检查当前版本。 如果你的版本太新,并且在构建过程中遇到问题,则需要使用Binutils 2.24版本 (或更新版本) 或安装旧版本的Texinfo - 也许是通过从源代码上构建 - 并在Binutils构建前后将其添加到PATH

注意: ISL的版本0.13 (或更高版本) 与当前的CLooG 0.18.1版本 (及更早版本) 不兼容。 使用ISL的0.12.2版本,否则生成肯定会失败。

下载源代码

将所需的源代码下载到合适的目录中,例如 $HOME/src:

注意: 使用的版本控制方案是每个句点分开一个完整的数字,即 Binutils 2.20.0比2.9.0更新。 如果查看按字母数字排序的tarball列表时,可能没有用此版本控制方案(相当常见的),这可能会让你感到困惑: 有时列表底部的文件不是最新版本! 获取最新版本的一个简单方法是按上次修改的日期排序并滚动到底部。

Linux用户构建系统编译器

你的发行版可能会发布自己补丁包的GCC和Binutils,这些修补的GCC和Binutils才可以在你的特定Linux发行版上工作。 你应该能够使用上述源代码构建一个工作的交叉编译器,但是你可能无法用源代码为当前的Linux发行版构建一个新的系统编译器。 在这种情况下,请尝试较新的GCC版本或获取打了补丁的源代码。

Gentoo用户

Gentoo提供crossdev来建立交叉开发工具链:

   emerge -av crossdev
   crossdev --help
   PORTDIR_OVERLAY="/usr/local/crossdev" crossdev --stage1 --binutils <binutils-version> --gcc <gcc-version> --target <target>

这将把GCC交叉编译器安装到一个"slot"中,即与现有的编译器版本一起安装。 你可以通过这种方式安装多个交叉编译器,只需更改目标名称即可。 它的缺点是,它还将引入gentoo补丁,并传递与官方GCC Cross-Compiler设置不同的额外配置选项,它们的行为可能会有所不同。

编译成功后,可以通过<target>-GCC调用你的交叉编译器。 如果需要,你还可以使用gcc-config在编译器版本之间切换。 不要用交叉编译器替换系统编译器。 包管理器还会在更新可用时立即提出建议。

你可以通过调用 “crossdev --clean <target>” 来卸载交叉编译器。 阅读交叉开发文档以获取更多信息。

请注意,binutils和GCC的版本号是Gentoo package versions, 即 "官方" (GNU) 版本可能有一个后缀,用于解决Gentoo维护者提供的其他补丁集。 (例如,--binutils 2.24-r3--gcc 4.8.3是撰写本文时最新的稳定包对。) 你可以省略版本号以使用可用的最新软件包。

Portage使用Overlay来存储不属于原始软件包管理的软件包。 Crossdev需要一个Overlay,在构建它们之前可以在其中存储其binutils和gcc包。 你可以正确配置一个,也可以使用PORTDIR_OVERLAY指向它应该保存其包管理器文件的位置。 使用PORTDIR_OVERLAY现有的overlay不是一个好主意,但是到那时你应该知道你是曾经是如何亲自设置它们的,以及如何正确地进行设置。 参考 [8].

MacOS用户

macOS用户需要替换libiconv,因为系统libiconv已经严重过时。 macOS用户可以通过访问网站或直接访问主FTP镜像。 否则,在OS X 10.4和10.5上编译GCC 4.3或更高版本时,可能会出现与libiconv相关的未解决符号错误。

安装新版本(自己编译或使用MacPorts)并添加 --with-libiconv-prefix=/opt/local (如果你自己编译,则为 /usr/local) 到GCC的 ./configure 行。 或者,你可以将libiconv源代码放置到GCC-x.y.z/libiconv,它将作为GCC编译过程的一部分进行编译。 (此技巧也适用于MPFR,GMP和MPC)。

Binutils和GCC的makefile使用$(CC)变量来调用编译器。 在OS X上,默认解析为gcc,实际是 clang. 在OSX10.8之前,Xcode的命令行工具包附带的Clang无法构建一个正常工作的GCC。 运行OS X 10.7或以下版本的用户可能需要从 Homebrew 或从Apple网站上的某个地方查找并安装GCC。 你可以尝试使用预装在某些macOS版本上的旧GCC。

# This is only necessary for OS X users running 10.7 or below.
export CC=/usr/bin/gcc-4.2
export CXX=/usr/bin/g++-4.2
export CPP=/usr/bin/cpp-4.2
export LD=/usr/bin/gcc-4.2

一旦编译并安装了交叉编译器,你就需要取消设置这些导出。

Lion用户注意: 如果你在Lion(或更高版本)上,很可能你没有“真正的”GCC,因为苹果从Xcode软件包中删除了它,但你仍然可以安装它。 你可以通过Homebrew或通过从源代码编译来实现,a StackExchange Answer对这两种方法都有很好的描述。

Maverick用户注意: 可以使用Xcode 5.1.1构建binutils-2.24和gcc-4.8.3(可能的其他版本)。 请注意,使用LLVM构建GCC不是官方支持的,可能会导致有趣的错误,如果你愿意冒这个风险并想节省时间构建出host-gcc只是为了编译一个cross-gcc,请遵循以下内容。 用 MacPorts 安装GMP、MPFR、Mpc。

sudo port install gmp mpfr libmpc
../binutils-2.24/configure --prefix=$PREFIX \
--target=$TARGET \
--enable-interwork --enable-multilib \
--disable-nls --disable-werror
../gcc-4.8.3/configure --prefix=$PREFIX \
--target=$TARGET \
--disable-nls \
--enable-languages=c,c++ --without-headers \
--enable-interwork --enable-multilib \
--with-gmp=/usr --with-mpc=/opt/local --with-mpfr=/opt/local

注意: port的GMP存在问题,因此使用来自/usr的OS X版本。

Windows用户

Windows用户需要设置类Unix的环境,如MinGWCygwin。 也许值得先研究研究Linux等系统,看看它们是否符合你的需求,因为你通常在操作系统开发中使用许多类Unix的工具,而从类Unix的操作系统来看,这要容易得多。 如果你刚刚安装了基本的Cygwin软件包,你必须再次执行setup.exe并安装以下软件包: GCC, G++, Make, Flex, Bison, Diffutils, libintl-devel, libgmp-devel, libmpfr-devel, libmpc-devel, Texinfo

MinGW MSYS是一种选择,由于它解决了本机Windows API而不是POSIX仿真层,因此工具链速度稍快。 一些软件包无法在MSYS下正确构建,因为它们不是为Windows设计的。 就本教程而言,除非另有说明,否则适用于Cygwin的所有内容也适用于MSYS。 确保安装C和C++编译器以及MSYS基本系统。

与Windows 10周年更新一起发布的“Windows Linux子系统(Beta版)”也是使用交叉编译器的一个选项。(使用GCC 6.1.0和Binutils 2.27于2016年8月8日进行测试)尽管处于测试状态,该交叉编译器运行速度相当快,但可能不是理想的永久性开发平台。

Cygwin注意: Cygwin在其bash %PATH%中包含你的Windows %PATH% 如果你以前使用过DJGPP,这可能会导致混淆,例如在Cygwin bash命令行上调用GCC仍会调用DJGPP编译器。 卸载DJGPP后,应删除DJGPP环境变量,并从 %PATH%中清除C:\djgpp条目(或其安装位置)。 同样,在系统路径变量中混淆构建环境可能是一个坏主意。

MinGW 注意: 有关构建跨工具链的一些特定于MinGW的信息可以在MinGW主页上的托管的交叉编译器操作页面上找到

Windows Subsystem for Linux (Beta) 注意: 你不能让交叉编译器位于/mnt/c/(或/mnt/“x”)区域,因为尝试在那里编译交叉编译器会产生错误,而构建到$HOME/opt/cross则可以完美地工作。 此问题已使用Windows Update KB3176929修复

OpenBSD用户

OpenBSD用户可能需要从port安装“gcc”包,因为基本系统的gcc非常过时。 如果你想构建GCC,请尝试使用port对应的版本,而不是最新可用的版本,并将所有来自port的补丁应用到你的版本中。 另外,如果在编译LT0插件期间构建失败,则临时解决方案是在构建GCC的配置阶段通过添加 --disable-lto 来完全禁用LTO

构建

你需要决定在哪里安装新编译器。 替换你当前的系统编译器和安装到系统目录可能是一个非常糟糕的主意。 你还需要决定新的编译器是应该全局安装还是只为你安装。 如果你想只为你自己安装(推荐),安装到 $HOME/opt/gcc-x.y.z通常是一个好主意。 如果要全局安装它,通常将其安装到 /usr/local/gcc-x.y.z 中是一个好主意。

请注意,我们应该在源目录树外部构建所有内容,这被认为是良好的实践。 有些软件包只支持外部构建,有些只支持内部,有些两者都支持(但可能不会使用make提供广泛的检查)。 在源目录树内构建GCC会失败,至少对于较旧的版本是如此。

由于构建可能需要很长时间,因此建议使用 “-jN” 选项。 这将允许make使用多个线程来编译程序,这将大大加快速度。 将N替换为一个数字;一个好的指导原则是你的中央处理器的核心数量加1。 因此,对于4核CPU,你需要使用 :

make -j5

准备

export PREFIX="$HOME/opt/gcc-x.y.z"

Binutils

cd $HOME/src
mkdir build-binutils
cd build-binutils
../binutils-x.y.z/configure --prefix="$PREFIX" --disable-nls --disable-werror
make
make install

--disable-nls告诉Binutils不要包含本机语言支持。 这基本上是可选的,但可以减少依赖项和编译时间。 它还将导致只有英语诊断,当你提出问题时,可以让论坛上的人都能理解。

GCC

:‘’另请参阅配置GCC的官方说明。‘’

cd $HOME/src


# 如果您希望构建这些包作为GCC的一部分:
mv libiconv-x.y.z gcc-x.y.z/libiconv # Mac OS X users
mv gmp-x.y.z gcc-x.y.z/gmp
mv mpfr-x.y.z gcc-x.y.z/mpfr
mv mpc-x.y.z gcc-x.y.z/mpc

# 或在新的GCC版本中,你可以要求gcc下载先决条件
cd gcc-x.y.z
./contrib/download_prerequisites
cd $HOME/src # Returning the main src folder

mkdir build-gcc
cd build-gcc
../gcc-x.y.z/configure --prefix="$PREFIX" --disable-nls --enable-languages=c,c++
make
make install

--disable-nls 与上面的Binutils相同。

--enable-languages告诉GCC不要编译它支持的所有其他语言前端,只编译C和C++。 即使你不打算使用C++制作操作系统,以后移植GCC时也将需要它。

--disable-bootstrap告诉编译器不要针对当前系统编译器自举自身。 这会导致更快的编译速度,但是如果当前编译器和新编译器在版本上差别太大,你将会得到不太健壮的编译器或奇怪的错误。

构建和自举GCC可能需要相当长的时间,所以坐下来放松,享受你即将使用GNU编译器套件的最新和最好的版本。

在运行make install并安装新编译器之前,如果你有额外的耐心,请阅读官方测试说明并测试编译器的缺陷。

使用新的编译器

你现在可以通过调用以下类似的东西来运行你的新编译器:

$HOME/opt/gcc-x.y.z/bin/gcc --version

要简单地通过调用gcc来使用新编译器,请键入以下命令将$HOME/opt/gcc-x.y.z/bin添加到$PATH

export PATH="$HOME/opt/gcc-x.y.z/bin:$PATH"

此命令会将你的新编译器添加到此shell会话的路径中。 如果希望永久使用,请将PATH命令添加到~/.profile配置shell脚本或类似文件。 有关详细信息,请参阅你的Shell文档。

构建交叉编译器

正文: GCC Cross-Compiler

现在你有了一个最新的系统编译器,你可以为新的操作系统构建交叉编译器。 这样可以安全地使用GCC的最新和最好的版本作为交叉编译器,因为你使用了相同的版本来构建它。 一旦构建了实际的交叉编译器,就可以通过删除安装目录来卸载我们在本教程中构建的编译器。(译者注:真是过河拆桥啊,感觉留着自用不也挺好嘛) 交叉编译器将不依赖于构建它的编译器,就像我们的新编译器不依赖于它替换的旧系统编译器一样。