查看“GCC Cross-Compiler”的源代码
←
GCC Cross-Compiler
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
{{FirstPerson}} {{rating|1}} 本教程重点介绍为开发自制操作系统创建所需的GCC交叉编译器。(译者注:本文中“自己的、自制的”都是说目标操作操作) 我们在这里构建的编译器有一个一般目标(i686-ELF),交叉编译器允许你的编译结果脱离当前操作系统,这意味着不会使用主机操作系统(Host OS)的引用头或库。 你 ''需要''使用交叉编译器来进行操作系统开发,否则可能会发生很多意想不到的事情,因为一般编译器默认会假设你的代码应该在你的当前主机操作系统上运行。 ==导言== 简单来说,交叉编译器是指在平台A('''Host主机''')上运行,但为平台B('''Traget目标''')生成可执行文件的编译器。 这两个平台可能 (但不一定) 在CPU、操作系统以及[[:Category:Executable Formats|可执行格式]]方面有所不同。 在我们的例子中,主机平台是你当前的操作系统,目标平台是你即将制作的操作系统。 重要的是要认识到,这两个平台是不同的;你正在开发的操作系统总是不同于你当前使用的操作系统。 这就是为什么我们需要首先构建一个交叉编译器,否则你肯定会遇到麻烦。 ===为什么需要交叉编译器=== {{Main|Why do I need a Cross Compiler?}} ''除非''是在自制的操作系统上进行开发,否则你需要使用交叉编译器。 编译器必须知道正确的目标平台 (CPU,操作系统),否则你将遇到麻烦。 如果你使用系统附带的编译器,那么编译器将不会知道它正在完全编译其他平台的内容。 一些其它教程会建议使用你的系统已有编译器,并将许多特殊的选项传递给编译器。 这肯定会在将来给你带来很多问题,正确的解决方案应该是构建一个交叉编译器。 如果你已经尝试在不使用交叉编译器的情况下创建操作系统,请阅读文章[[Why do I need a Cross Compiler?|为什么我需要交叉编译器?]]。 ===选择哪个编译器版本=== {{Main|构建GCC}} 推荐使用最新的[[GCC]],因为它是最新和最好的版本。(译者注:这里指的是用什么编译器和源代码编译出新的‘交叉编译器’) 例如,使用GCC 4.6.3构建GCC 4.8.0交叉编译器可能会遇到麻烦。 如果你的系统编译器没有使用最新的主要GCC版本,我们建议你 [[Building GCC| 构建最新的GCC作为你的系统编译器]]。 你也可以使用旧版本,因为它们通常相当好。 如果你的本地系统编译器不是太旧(至少是GCC 4.6.0),你可能希望省去麻烦,只为你的交叉编译器选择非最新的版本(例如,如果你的系统编译器是4.6.1,则为选4.6.3为交叉编译器源代码版本)。 你可以通过调用以下代码查看你当前的编译器版本: <source lang="bash">gcc --version</source> 你可以使用较旧的GCC主版本来构建较新的GCC主版本的交叉编译器。 例如,GCC 4.7.3也许能够构建GCC 4.8.0版的交叉编译器。 但是,如果你想为交叉编译器使用最新最好的GCC版本,我们建议你首先将 [[Building GCC |启动最新GCC]] 作为系统编译器。 使用OS X 10.7或更早版本的个人可能需要即构建系统GCC(输出本机Mach-O),也要升级本地LLVM/Clang安装。 10.8及以上版本的用户应从苹果开发者网站安装命令行工具,并使用Clang交叉编译GCC。 === 选择哪个binutils版本 === {{Main|Cross-Compiler Successful Builds}} 我们建议你使用最新最好的[[Binutils]]发行版。 然而,请注意,并不是所有GCC和Binutils的组合都有效。 如果遇到麻烦,请使用与所需编译器版本大致同时发布的Binutils。 你可能至少需要Binutils 2.22,或者最好是最新的2.23.2版本。 你在当前操作系统上安装的Binutils版本并不重要。 你可以通过以下命令找到binutils版本: <source lang="bash">ld --version</source> ===决定目标平台=== {{Main|Target Triplet}} 你应该已经明确知道自己的目标平台了。 如果你正在学习[[Bare Bones]]教程,那么你应该是希望为<tt>i686 elf</tt>构建一个交叉编译器。 === 注意arm-none-eabi-gcc === 在Debiab/Ubuntu上的apt-get中有预构建的包gcc-arm-none-eabi,但是你不应该使用它,因为它既不包含libgcc.a,也不包含像stdint.h这样的独立的C头文件。<br> 相反,你应该自己用<tt>arm-none-eabi</tt>作为$TARGET来构建它。 ==为构建做准备== <!-- Note how this section ([[Preparing GCC Build]]) is shared by [[Building GCC]] and [[GCC Cross-Compiler]]. --> {{:Preparing GCC Build}} ==构建== 我们计划构建一个在你的主机上运行的工具集,可以将源代码转换为目标系统的目标文件。 你需要决定在哪里安装你的新编译器。 将其安装到系统目录中的做法既危险又糟糕。 你还需要决定是应该全局安装新编译器,还是只为个人单用户安装新编译器。 如果你只想为自己安装 (推荐),则通常比较好的主意将其安装到 <tt>$ HOME/opt/cross</tt> 中。 如果你想在全局安装它,则最好通常将其安装到<tt>/usr/local/cross</tt>。 请注意,我们最好在源代码目录树之外构建所有内容。 有些软件包仅支持外部构建,有些仅支持内部建筑,有些则两者兼而有之 (但可能无法对构建过程进行广泛的检查)。 在源目录树中构建GCC会失败得很惨,至少对于旧版本来说是如此。 ===准备=== <source lang="bash"> export PREFIX="$HOME/opt/cross" export TARGET=i686-elf export PATH="$PREFIX/bin:$PATH" </source> 我们将安装前缀(PREFIX)添加到当前shell会话的 <tt>PATH</tt> 中。 这确保了一旦我们构建了新的binutil,编译器构建就能够检测它们。 前缀将配置构建过程,以便你的交叉编译器环境的所有文件都以$HOME/opt/cross开头。 你可以将该前缀更改为你喜欢的任何内容 (例如,/opt/cross或 $HOME/cross 都可以)。 如果你具有管理员权限,并且希望所有用户都可以使用交叉编译器工具链,则可以将其安装到/usr/local前缀中 - 或者,如果你愿意更改系统配置,使此目录位于所有用户的搜索路径中,也可以使用/usr/local/cross前缀。 从技术上讲,你甚至可以直接安装到/usr,这样你的交叉编译器将与你的系统编译器一起驻留,但由于各种原因,不建议你这样做 (例如,如果目标错误,可能会覆盖系统编译器,或者与系统的包管理发生冲突)。 ===Binutils=== <!-- This confuses some people a bit too much and they should just get it through package management and follow the above instructions. # If you wish to build these packages as part of binutils: mv isl-x.y.z binutils-x.y.z/isl mv cloog-x.y.z binutils-x.y.z/cloog # But reconsider: You should just get the development packages from your OS. --> <source lang="bash"> cd $HOME/src mkdir build-binutils cd build-binutils ../binutils-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror make make install </source> 这将编译binutils (汇编程序,反汇编程序和其他各种有用的东西),它们可在你的系统上运行,但以$TARGET指定的格式处理代码。 '''--disable-nls'''告诉binutils不要包含本机语言支持。 这基本上是可选的,但可以减少依赖性和编译时间。 这也会影响诊断结果的英文,当你提出问题时,[http://forum.osdev.org/ 论坛] 上的人们会理解。;-) (译者注:没有作者Get意思) '''--with-sysroot'''告诉binutils在交叉编译器中启用sysroot支持,方法是将其指向默认的空目录。 默认情况下,因为没有很好的技术原因,链接器拒绝使用sysroot,而GCC能够在运行时处理这两种情况。 这将在以后有用。 ===GCC=== :''另请参阅[http://gcc.gnu.org/install/configure.html 配置GCC的官方说明]。'' 现在,你可以开始构建 [[GCC]]了。 <!-- This confuses some people a bit too much and they should just get it through package management and follow the above instructions. # If you wish to build these packages as part of 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 mv isl-x.y.z gcc-x.y.z/isl mv cloog-x.y.z gcc-x.y.z/cloog # But reconsider: You should just get the development packages from your OS. --> <source lang="bash"> cd $HOME/src # The $PREFIX/bin dir _must_ be in the PATH. We did that above. which -- $TARGET-as || echo $TARGET-as is not in the PATH mkdir build-gcc cd build-gcc ../gcc-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers make all-gcc make all-target-libgcc make install-gcc make install-target-libgcc </source> 我们构建[[libgcc]],这是一个低级支持库,编译器希望它在编译时可用。 针对[[libgcc]]的链接提供整数、浮点、小数、堆栈展开(用于异常处理)和其他支持功能。 请注意,我们这里''没有''简单地运行 <tt>make && make install</tt>,因为这会构建太多的方式,并不是gcc的所有组件都针对你未完成的操作系统已准备好。 '''--disable-nls''' 与上面的binutils相同。 '''--without-headers'''告诉[[GCC]]不要为目标依赖任何存在的C库(标准库或运行时库)。 '''--enable-languages''' 告诉 [[GCC]] 不要编译它支持的所有其他语言前端,而只能编译C (以及可选的C++)。 构建交叉编译器需要一段时间。 如果你正在构建x86-64的交叉编译器,则可能需要考虑构建不带“red zone”的Libgcc:[[Libgcc_Without_red_zone]] == 使用新的编译器 == 现在你有了一个“裸”交叉编译器。 它还不能访问C库或C运行时,因此你不能使用任何标准的包含语句或创建可运行的二进制文件。 但是编译你将马上要制作的内核已经足够了。 你的工具集位于$HOME/opt/cross(或你设置的<tt>$PREFIX</tt>中)。 例如,你将GCC可执行文件安装为<tt>$HOME/opt/cross/bin/$TARGET-gcc</tt>,它将为你的目标创建程序。 你现在可以通过调用类似的东西来运行你的新编译器: <source lang="bash">$HOME/opt/cross/bin/$TARGET-gcc --version</source> 请注意,此编译器“无法”编译普通C程序。 每当你想要#include包含任何标准标头时,交叉编译器都会产生错误(除了少数实际上独立于平台并由编译器本身生成的标头)。 这是对于操作系统开发是非常必要的-你还没有目标系统的标准库! C标准定义了两种不同的执行环境——“独立freestanding”和“托管hosted”。 虽然对于普通的应用程序程序员来说,这个定义可能相当模糊,但是当你进行操作系统开发时,它是相当清晰的: 内核执行是 “独立的”,你在用户空间中做的一切都是 “托管的”。 “独立”环境只需要提供C库的一个子集:float.h、 iso646.h、 limits.h、 stdalign.h、 stdarg.h、 stdbool.h、 stddef.h, stdint.h和stdnoreturn.h(从C11开始)。 所有这些文件都“仅仅”由typedef s和#define s 组成,因此你可以在看不到一个.c文件的情况下使用它们。 要简单地通过调用 <tt>$TARGET-gcc</tt> 来使用你的新编译器,请通过键入将 <tt>$ HOME/opt/cross/bin</tt> 添加到你的 <tt>$PATH</tt> 中: <source lang="bash">export PATH="$HOME/opt/cross/bin:$PATH"</source> 此命令将把新编译器添加到此shell会话的路径中。 如果你希望永久使用它,请将path命令添加到你的<tt>~/.profile</tt>配置shell脚本或类似脚本中。 有关更多信息,请参阅你的shell文档。 如果是你是从[[Bare Bones]]教程来到这里,那么现在你可以再使用新的交叉编译器来完成它,实现一个新的变体。 如果你开始是构建了一个新的GCC版本作为系统编译器,并使用它来构建出了交叉编译器,那么你现在可以安全地卸载那个系统编译器,除非你希望继续使用它。 == 故障排除 == 一般来说,这里要'''验证'''的仅是你仔细阅读了说明,并准确键入了命令。 不要跳过说明。 如果你使用新的shell实例,如果你没有将其添加到shell配置文件中,则必须再次设置PATH变量。 如果编译过程似乎真的搞砸了,请键入<tt>make distclean</tt>,然后重新开始make过程。 确保你的解压软件不会更改换行符。 ==== ld: 找不到 -lgcc ==== 你通过<tt>-lgcc</tt>开关将GCC低级运行库链接到可执行文件中,但忘记了构建和正确安装库<br> 如果在安装libgcc时没有收到任何警告或错误,但仍然存在问题,则可以将库复制到项目中并将其用<tt>-L. -lgcc</tt><br>链接 libgcc位于 $PREFIX/lib/gcc/$TARGET/<gcc-version>/libgcc.a。 ==== Binutils2.9 ==== 顶部或底部的字母顺序不一定是最新版本。 2.9之后,2.10,2.11,2.12,然后有更多的版本,这些版本都是更新的,并且越来越有可能构建或支持你选择的GCC版本。 ====构建GCC:应该包含系统头的目录不存在==== 在构建<tt>mingw32</tt>目标时可能会遇到此错误,例如<tt>x86_64-w64-mingw32</tt>。 找不到的违规目录是 <tt>$SYSROOT/mingw/include</tt>。 如果查看sysroot,你当然会意识到不存在这样的文件夹。 解决方案只需创建空文件夹: <source lang="bash"> mkdir -p $SYSROOT/mingw/include mkdir -p $SYSROOT/mingw/lib </source> 这将允许构建继续进行。 发生这种情况的原因是<tt>mingw32</tt>(以及mingw本身)将<tt>包含路径和<tt>库路径配置为<tt>/mingw/INCLUDE</tt>和<tt>/mingw/lib</tt>,而不是默认的<tt>/usr/INCLUDE</tt>和<tt>/usr/lib</tt>。 即使这些文件夹中不需要任何东西,为什么还会构建失败,为什么不只是创建它们就可以了,我也不明白。 === GCC libsanitizer无法构建 === 有时,GCC无法构建libsanitizer,如果发生这种情况,请在configure命令中附加<tt>--disable-libsanitizer</tt><br> 这仅用于构建托管编译器。 == 更进一步 == 在相当长的一段时间内,使用这个简单的交叉编译器就足够了,但在某些时候,你会希望编译器自动包含你自制系统头和库。 为你自制操作系统构建[[OS Specific Toolchain|特定于操作系统的工具链]]是从这里开始的。 == 另见 == === 文章 === *[[Cross-Compiler Successful Builds]] - Ossev.org成员已证明可以与本教程一起使用的GCC和Binutils的组合。 *[[Target Triplet]] - Target Triplet及其应用 *[[OS Specific Toolchain]] - 更进一步,添加你自己的目标。 *[[LLVM Cross-Compiler]] - 一些编译器使事情变得容易得多。 *[[Canadian Cross]] - 让事情变得更加复杂。 ===外部链接=== *http://kegel.com/crosstool 有一个很流行的脚本示例,可以为已知平台自动下载、打补丁和构建binutil、GCC和glibc。 *http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html - 与libgcc链接时获得的支持功能摘要 *http://forums.gentoo.org/viewtopic.php?t=66125 - 在Linux下编译Windows应用程序 *http://www.libsdl.org/extras/win32/cross/README.txt - Dito *https://github.com/travisg/toolchains - 另一个用于构建简单交叉编译器的脚本 *https://www.youtube.com/watch?v=aESwsmnA7Ec - 介绍如何在Windows上使用Cygwin构建交叉编译器的演练。 *https://github.com/Cheapskate01/Cross-Compiler-Build-Script - 一个非常简单的Binutils和GCC脚本。 [[Category:Compilers]] [[Category:Tutorials]] [[de:Cross-Compiler]] === 预先构建的工具链 === 这些都是由OSdev社区中的人根据自己的构建需求构建的,并且可以随意共享,而不保证任何支持,或者它甚至可以在你的工作直接使用。因个人而异请自行考虑使用。 '''Linux的最新版本(许多是ARCH的)''' * [https://www.kernel.org/pub/tools/crosstool/ kernel.org中的各种主机/目标] “适用于Linux i686主机” * [https://drive.google.com/open?id=1zcFAmxi7mtOwhMaKE36IsjLRB0uEv17p aarch64-elf 9.3.0 target] * [https://drive.google.com/open?id=1uEFrOJPxy13vxWCy-5IbxCJAs5TRdtTE arm-eabi 9.3.0 target] * [https://drive.google.com/open?id=13Kg6Xd8acUnwUoZQBTOjwAQQeGOeYzVz i386-elf 9.3.0 target] * [https://drive.google.com/open?id=1F5RsfIEfcpRYAqu5UuGTKgkMa3eBsXnP i486-elf 9.3.0 target] * [https://drive.google.com/open?id=1PdEFqMEJf_Vuf0drO1m8bjlrsudAmI5k i586-elf 9.3.0 target] * [https://drive.google.com/open?id=1g9jzEIn8CB6ZiVrc0uxbZprepcX4gYex i686-elf 9.3.0 target] * [https://drive.google.com/open?id=1xIeNJwD0Do-REFxzCLOkMIVYI3HGJUTX mips-elf 9.3.0 target] * [https://drive.google.com/open?id=10UuOf9LW4y9WEJcTWrMZW0GAlOWh9KG7 mips64-elf 9.3.0 target] * [https://drive.google.com/open?id=1oW6UWr-OY22EgtyuXovORUtHeVLkL-Tw m64k-elf 9.3.0 target] * [https://drive.google.com/open?id=1H3Cbq4D_kjROB-7Otiisa-mac_9FYUM- powerpc-elf 9.3.0 target] * [https://drive.google.com/open?id=1kFGNHWhcBD9cf8X2y-BW49Su04lMa1ev sh-elf 9.3.0 target] * [https://drive.google.com/open?id=1XzQDKTK35EX8b380bPRbuhX1GPKrtI77 sparc-elf 9.3.0 target] * [https://drive.google.com/open?id=1pU8bS0McTyRUTHb1b_c8ZVa2Ka_XeeEp x86_64-elf 9.3.0 target] * [https://drive.google.com/open?id=1cqk9RzY3QXQuaS-YdIWtCECKL81pcsv- xtensa-elf 9.3.0 target] '''对于Linux x86_64主机''' * [https://drive.google.com/file/d/0Bw6lG3Ej2746STJaM2dNbC05elE/view?usp=sharing i386-elf & i686-elf 7.1.0 target uploaded by TheAlmostGenius] * [https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz i386-elf 7.5.0 target] * [https://newos.org/toolchains/x86_64-elf-7.5.0-Linux-x86_64.tar.xz x86_64-elf 7.5.0 target] * [https://newos.org/toolchains/aarch64-elf-7.5.0-Linux-x86_64.tar.xz aarch64-elf 7.5.0 target] * [https://newos.org/toolchains/arm-eabi-7.5.0-Linux-x86_64.tar.xz arm-eabi 7.5.0 target] * [https://newos.org/toolchains/m68k-elf-7.5.0-Linux-x86_64.tar.xz m68k-elf 7.5.0 target] * [https://newos.org/toolchains/microblaze-elf-7.5.0-Linux-x86_64.tar.xz microblaze-elf 7.5.0 target] * [https://newos.org/toolchains/mips-elf-7.5.0-Linux-x86_64.tar.xz mips-elf 7.5.0 target] * [https://newos.org/toolchains/nios2-elf-7.5.0-Linux-x86_64.tar.xz nios2-elf 7.5.0 target] * [https://newos.org/toolchains/powerpc-elf-7.5.0-Linux-x86_64.tar.xz powerpc-elf 7.5.0 target] * [https://newos.org/toolchains/riscv32-elf-7.5.0-Linux-x86_64.tar.xz riscv32-elf 7.5.0 target] * [https://newos.org/toolchains/riscv64-elf-7.5.0-Linux-x86_64.tar.xz riscv64-elf 7.5.0 target] * [https://newos.org/toolchains/sh-elf-7.5.0-Linux-x86_64.tar.xz sh-elf 7.5.0 target] * [https://newos.org/toolchains/sparc-elf-7.5.0-Linux-x86_64.tar.xz sparc-elf 7.5.0 target] 下面来自phillid.tk的软件包已缩小到每对GCC和Binutils软件包约10 MiB。 请注意,这是通过只为GCC启用C前端实现的。 如果你打算用C或汇编语言以外的任何语言来编写操作系统,这些软件包不适合你。 这些实际上是Pacman包,但是将它们不加任何限制到 / 和 /rm-ing /.MTREE和包中包含的其他杂乱无章的“.”文件将工作相同。 '''适用于Windows主机''' * [https://drive.google.com/file/d/0B85K_c7mx3QjUnZuaFRPWlBIcXM/edit?usp=sharing i686-elf 4.8.2 target] * [https://mega.co.nz/#F!bBxA3SKJ!TDL4i1NjaZKd4YMo9p2U7g x86_64-elf 5.1.0 target] * [https://github.com/lordmilko/i686-elf-tools i686-/x86_64-elf 7.1.0 target + GDB] '''适用于Windows Subsystem for Linux(Beta)主机''' * [http://www.bin-os.com/i686-elf-6.1.0.tar.gz i686-elf 6.1.0 target] (extracts to a directory called "cross", don't forget to install 'make' - I would recommend "apt-get install build-essential" to also add additional useful tools) '''适用于macOS主机''' x86_64-ELF[https://formulae.brew.sh/formula/x86_64-elf-binutils binutils]和[https://formulae.brew.sh/formula/x86_64-elf-gcc GCC](规范目标名称x86_64-PC-ELF)可以从[https://brew.sh HOMEBREW]安装: <pre> $ brew install x86_64-elf-gcc </pre> i686-elf工具链也在homebrew[https://formulae.brew.sh/formula/i686-elf-gcc 可用]。 '''针对多主机平台的ARM预构建工具链''' ARM提供了它自制的基于GNU实用程序的预构建工具链,用于针对ARM系统进行开发。 * [https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads GNU ARM Embedded Toolchain] '''Docker映像''' * [https://hub.docker.com/r/joshwyant/gcc-cross/ i686-elf 8.1.0 target]
本页使用的模板:
Preparing GCC Build
(
查看源代码
)
模板:Eq
(
查看源代码
)
模板:Eq1
(
查看源代码
)
模板:FirstPerson
(
查看源代码
)
模板:If
(
查看源代码
)
模板:Main
(
查看源代码
)
模板:NoteBox
(
查看源代码
)
模板:Rating
(
查看源代码
)
模板:Show1
(
查看源代码
)
模板:Wikitable
(
查看源代码
)
返回至“
GCC Cross-Compiler
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
变体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息