“GCC Cross-Compiler”的版本间差异

来自osdev
跳到导航 跳到搜索
(创建页面,内容为“{{FirstPerson}} {{rating|1}} 本教程重点介绍为您自己的操作系统创建GCC交叉编译器。 我们在这里构建的编译器将有一个通用目标(i686 elf),它允许您将当前操作系统留在后面,这意味着不会使用主机操作系统的头或库。 在操作系统开发中,您“需要”一个交叉编译器,否则会发生很多意想不到的事情,因为编译器假定您的代码正在主机操作系统上运行。…”)
 
第87行: 第87行:
'''--with-sysroot''' tells binutils to enable sysroot support in the cross-compiler by pointing it to a default empty directory. By default, the linker refuses to use sysroots for no good technical reason, while gcc is able to handle both cases at runtime. This will be useful later on.
'''--with-sysroot''' tells binutils to enable sysroot support in the cross-compiler by pointing it to a default empty directory. By default, the linker refuses to use sysroots for no good technical reason, while gcc is able to handle both cases at runtime. This will be useful later on.


=== 海湾合作委员会 ===
=== GCC ===
:''See also the [http://gcc.gnu.org/install/configure.html offical instructions for configuring gcc].''
:''See also the [http://gcc.gnu.org/install/configure.html offical instructions for configuring gcc].''



2021年12月16日 (四) 03:23的版本

本页面或章节指其读者或编者使用人称 , 我的, 我们 或者 我们的。 用encyclopedic百科全书式的语言风格进行编辑

难度等级
Difficulty 1.png
初学者

本教程重点介绍为您自己的操作系统创建GCC交叉编译器。 我们在这里构建的编译器将有一个通用目标(i686 elf),它允许您将当前操作系统留在后面,这意味着不会使用主机操作系统的头或库。 在操作系统开发中,您“需要”一个交叉编译器,否则会发生很多意想不到的事情,因为编译器假定您的代码正在主机操作系统上运行。

介绍

一般来说,交叉编译器是在平台a(“主机”)上运行,但为平台B(“目标”)生成可执行文件的编译器。这两个平台在CPU、操作系统和/或[:类别:可执行格式|可执行格式]]方面可能(但不需要)有所不同。 在我们的例子中,主机平台是您当前的操作系统,目标平台是您将要制作的操作系统。 重要的是要认识到这两个平台是不同的;您正在开发的操作系统总是与您当前使用的操作系统不同。 这就是为什么我们需要首先构建一个交叉编译器,否则您肯定会遇到麻烦。

为什么需要交叉编译器

正文: Why do I need a Cross Compiler?

您需要使用交叉编译器“”,除非您在自己的操作系统上开发“”。 编译器必须知道正确的目标平台(CPU、操作系统),否则您将遇到麻烦。 如果您使用系统附带的编译器,那么编译器不会知道它正在编译其他的东西。 一些教程建议使用系统编译器,并向编译器传递许多有问题的选项。 这在将来肯定会给您带来很多问题,解决方案是构建一个交叉编译器。 如果您已经尝试在不使用交叉编译器的情况下创建操作系统,请阅读文章为什么我需要交叉编译器?

选择哪个编译器版本

正文: Building GCC

建议使用最新的GCC,因为它是最新和最棒的版本。 例如,如果使用GCC4.6,您可能会遇到麻烦。3构建GCC4.8。0交叉编译器。 如果您的系统编译器没有使用最新的主要GCC版本,我们建议您构建最新的GCC作为系统编译器

您也可以使用较旧的版本,因为它们通常相当好。 如果您的本地系统编译器不是太旧(至少GCC4.6.0),您可能希望省去麻烦,只需为交叉编译器选择最新的次要版本(如4.6.3,如果您的系统编译器是4.6.1)。

您可以通过调用以下命令查看当前编译器版本:

gcc--version</source lang=“bash”>

您可以使用较旧的主要GCC版本来构建较新的主要GCC版本的交叉编译器。 例如,GCC4.7。3可能能够构建GCC4.8。0交叉编译器。 但是,如果您想在交叉编译器中使用最新和最好的GCC版本,我们建议您首先引导最新的GCC作为系统编译器。 使用OS X 10.7或更早版本的个人可能希望投资构建系统GCC(输出本机Mach-O),或者升级本地LLVM/Clang安装。 10.8及以上版本的用户应该从苹果开发者网站安装命令行工具,并使用Clang交叉编译GCC。

要选择哪个binutils版本

正文: Cross-Compiler Successful Builds

我们建议您使用最新和最好的Binutils版本。但是,请注意,并非所有GCC和Binutils的组合都有效。如果遇到问题,请使用与所需编译器版本大致同时发布的Binutils。您可能至少需要Binutils 2.22,或者最好是最新的2.23。2释放。在当前操作系统上安装的Binutils版本并不重要。例如,您可以通过以下命令找到binutils版本:

ld --version

确定目标平台

正文: Target Triplet

你应该已经知道了。 如果您正在学习Bare Bones教程,则希望为i686 elf构建交叉编译器。

关于arm none eabi gcc的注释

apt get for Debiab/Ubuntu上有一个预构建的包gcc arm none eabi,但您不应该使用它,因为它既不包含libgcc,也不包含libgcc。也不是像stdint这样的独立C头文件。h、
相反,您应该使用arm none eabi作为$TARGET自己构建它。

为构建做准备

难度等级
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/cross通常是个好主意。 如果您想在全球范围内安装它,将其安装到/usr/local/cross通常是个好主意。

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

准备

export PREFIX="$HOME/opt/cross"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"

我们将安装前缀添加到当前shell会话的路径中。 这确保编译器构建能够在构建新的binutil之后检测它们。

前缀将配置构建过程,以便交叉编译器环境中的所有文件最终都位于$HOME/opt/cross中。 您可以将该前缀更改为您喜欢的任何前缀(例如,/opt/cross或$HOME/cross将是选项)。 如果您具有管理员访问权限并希望使交叉编译器工具链可供所有用户使用,则可以将其安装到/usr/local prefix中,或者如果您愿意更改系统配置,使此目录位于所有用户的搜索路径中,则可以将其安装到/usr/local/cross prefix中。从技术上讲,您甚至可以直接安装到/usr,这样您的交叉编译器将与系统编译器一起驻留,但由于以下几个原因,不建议这样做(例如,如果目标错误,可能会覆盖系统编译器,或者与系统的包管理发生冲突)。

比努蒂尔斯

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

这将编译binutils(汇编程序、反汇编程序和各种其他有用的东西),可以在系统上运行,但可以以$TARGET指定的格式处理代码。

--disable-nls tells binutils not to include native language support. This is basically optional, but reduces dependencies and compile time. It will also result in English-language diagnostics, which the people on the Forum understand when you ask your questions. ;-)

--with-sysroot tells binutils to enable sysroot support in the cross-compiler by pointing it to a default empty directory. By default, the linker refuses to use sysroots for no good technical reason, while gcc is able to handle both cases at runtime. This will be useful later on.

GCC

See also the offical instructions for configuring gcc.

现在,您可以构建GCC

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

We build libgcc, a low-level support library that the compiler expects available at compile time. Linking against libgcc provides integer, floating point, decimal, stack unwinding (useful for exception handling) and other support functions. Note how we are not simply running make && make install as that would build way too much, not all components of gcc are ready to target your unfinished operating system.

--disable-nls is the same as for binutils above.

--without-headers tells GCC not to rely on any C library (standard or runtime) being present for the target.

--enable-languages tells GCC not to compile all the other language frontends it supports, but only C (and optionally C++).

It will take a while to build your cross-compiler.

If you are building a cross compiler for x86-64, you may want to consider building Libgcc without the "red zone": Libgcc_without_red_zone

使用新编译器

现在您有了一个“裸”交叉编译器。它还没有访问C库或C运行时的权限,因此您不能使用任何标准包含或创建可运行的二进制文件。但是编译不久将要制作的内核就足够了。您的工具集驻留在$HOME/opt/cross(或您设置的$PREFIX中)。例如,您有一个GCC可执行文件,安装为$HOME/opt/cross/bin/$TARGET GCC,它为您的目标创建程序。

现在,您可以通过调用以下命令来运行新编译器:

$HOME/opt/cross/bin/$TARGET-gcc --version

请注意此编译器如何“无法”编译普通C程序。只要你想包含任何标准头,交叉编译器就会抛出错误(除了少数几个真正独立于平台的、由编译器自己生成的头)。这是非常正确的-您还没有针对目标系统的标准库!

C标准定义了两种不同的执行环境——“独立”和“托管”。虽然对于一般的应用程序程序员来说,这个定义可能相当模糊,但在进行操作系统开发时却非常明确:内核是“独立的”,在用户空间中所做的一切都是“托管的”。“独立”环境只需要提供C库的一个子集:float。h、 iso646。h、 限制。h、 stdalign。h、 斯塔格。h、 stdbool。h、 stddef。h、 斯特丁。h和stdnoreturn。h(从C11开始)。所有这些都由typedef s和#define s“only”组成,因此您可以在不使用单个函数的情况下实现它们。看到c文件了。

要通过调用$TARGET gcc使用新编译器,请通过键入以下内容将$HOME/opt/cross/bin添加到$PATH

export PATH="$HOME/opt/cross/bin:$PATH"

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

现在,您可以继续完成Bare Bones教程变体,并使用新的交叉编译器完成它。 如果您构建了一个新的GCC版本作为系统编译器,并使用它来构建交叉编译器,那么您现在可以安全地卸载它,除非您希望继续使用它。

故障排除

通常,“验证”您是否仔细阅读了说明并准确键入了命令。 不要跳过说明。 如果您使用一个新的shell实例,如果您没有通过将其添加到shell概要文件中使其永久化,那么您必须再次设置PATH变量。 如果编译似乎真的搞砸了,请键入make distclean,然后重新开始make过程。 确保您的un archiever不会更改换行符。

ld: cannot find -lgcc

您指定要通过-lgcc'开关将GCC低级运行库链接到可执行文件中,但忘记构建并正确安装库
如果在安装libgcc时没有收到警告或错误,但仍然存在问题,则可以在项目中复制库并将其链接到-L.-lgcc
libgcc位于$PREFIX/lib/gcc/$TARGET/<gcc version>/libgcc。A.

Binutils 2.9

按字母顺序排列在顶部或底部的内容不一定是最新版本。 在2.9之后是2.10、2.11、2.12,然后是更多更新的版本,并且越来越有可能构建或支持您选择的GCC版本。

Building GCC: 应该包含系统头的目录不存在

You might encounter this error when building mingw32 targets, for example x86_64-w64-mingw32. The offending directory that can't be found is $SYSROOT/mingw/include. 如果查看sysroot,您当然会意识到不存在这样的文件夹。

The solution is simply to create the empty folders:

mkdir -p $SYSROOT/mingw/include
mkdir -p $SYSROOT/mingw/lib

这将允许构建继续进行。 发生这种情况的原因是mingw32(以及mingw本身)将包含路径和库路径配置为/mingw/INCLUDE/mingw/lib,而不是默认的/usr/INCLUDE/usr/lib。 我无法理解为什么即使这些文件夹中不需要任何东西,构建也会失败,为什么不只是创建它们。

GCC libsanitizer未能生成

有时GCC无法构建libsanitizer,如果发生这种情况,请在configure命令中追加--disable libsanitizer
这仅适用于构建托管编译器。

更高级

在相当长的一段时间内,使用这个简单的交叉编译器就足够了,但在某些时候,您会希望编译器自动包含您自己的系统头和库。为您自己的操作系统构建 OS-Specific Toolchain就是一条出路。

另见

文章

外部链接

de:Cross-Compiler

Prebuilt Toolchains

These were built by people in the OSdev community for their own building needs and shared at will, without guaranteeing any support or that it will even work on your setup. YMMV.

Latests versions for Linux (many arch)

For Linux i686 host

For Linux x86_64 host

The packages from phillid.tk below have been shrunk to about 10 MiB for each pair of packages (GCC & Binutils). Please note that this has been achieved by enabling only the C front-end for GCC. If you're going to write your OS in any language but C or Assembly, these packages aren't for you. These are actually Pacman packages, but untarring them to / and rm-ing /.MTREE and other clutter dotfiles contained in the package will work the same.

For Windows host

For Windows Subsystem for Linux (Beta) host

  • 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)

For macOS host

x86_64-elf binutils and gcc (canonical target name x86_64-pc-elf) can be installed from homebrew:

$ brew install x86_64-elf-gcc

i686-elf toolchain is also available in homebrew.

ARM prebuilt toolchains for multiple host platforms

ARM provides it's own prebuilt toolchain based upon GNU utilities for development targeting ARM systems.

Docker image