GCC Cross-Compiler: Difference between revisions
[unchecked revision] | [unchecked revision] |
Content deleted Content added
add maintenance template |
|||
(42 intermediate revisions by 18 users not shown) | |||
Line 1:
{{FirstPerson}}{{You}}
{{rating|1}}
== Introduction ==
Generally speaking, a cross-compiler is a compiler that runs on platform A (the '''host'''), but generates executables for platform B (the '''target'''). These two platforms may (but do not need to) differ in CPU, operating system, and/or [[:Category:Executable Formats|executable format]]. In our case, the host platform is your current operating system
=== Why
{{Main|Why do I need a Cross Compiler?}}
=== Which compiler version
{{Main|Building GCC}}
The newest [[GCC]] is recommended as it is the latest and greatest release. For instance,
You can also use older releases as they are usually reasonably good. If your local system compiler isn't too terribly old (at least GCC 4.6.0), you may wish to save yourself the trouble and just pick the latest minor release (such as 4.6.3 if your system compiler is 4.6.1) for your cross-compiler.
<
gcc --version
</syntaxhighlight>
You may be able to use an older major GCC release to build a cross-compiler of a newer major GCC release. For instance, GCC 4.7.3 may be able to build a GCC 4.8.0 cross-compiler. However, if you want to use the latest and greatest GCC version for your cross-compiler, we recommend that you [[Building GCC|bootstrap the newest GCC]] as your system compiler first. Individuals using OS X 10.7 or earlier might want to invest in either building a system GCC (that outputs native Mach-O), or upgrading the local LLVM/Clang installation. Users with 10.8 and above should install the Command Line Tools from Apple's developer website and use Clang to cross-compile GCC.
=== Which
{{Main|Cross-Compiler Successful Builds}}
<syntaxhighlight lang="bash">
ld --version
</syntaxhighlight>
=== Deciding on the target platform ===
Line 33 ⟶ 38:
You should already know this. If you are following the [[Bare Bones]] tutorial, you wish to build a cross-compiler for <tt>i686-elf</tt>.
=== Note on arm-none-eabi-gcc ===
There is the prebuilt package gcc-arm-none-eabi on apt-get for Debian/Ubuntu, but you shouldn't use it because it neither contains a libgcc.a nor freestanding C header files like stdint.h.<br>
Instead you should build it yourself with <tt>arm-none-eabi</tt> being the $TARGET.
== Preparing for the build ==
Line 48 ⟶ 57:
=== Preparation ===
<
export PREFIX="$HOME/opt/cross"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"
</syntaxhighlight>
We add the installation prefix to the <tt>PATH</tt> of the current shell session. This ensures that the compiler build is able to detect our new binutils once we have built them.
Line 66 ⟶ 75:
# But reconsider: You should just get the development packages from your OS.
-->
<
cd $HOME/src
Line 74 ⟶ 83:
make
make install
</syntaxhighlight>
This compiles the binutils (assembler, disassembler, and various other useful stuff), runnable on your system but handling code in the format specified by $TARGET.
Line 81 ⟶ 90:
'''--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.
=== GDB ===
It may be worth noting that if you wish to use '''GDB''', and you are running on a different computer architecture than your OS (most common case is developing for ARM on x86_64 or x86_64 on ARM), you need to cross-compile GDB separately. While technically a part of Binutils, it resides in a separate repository.
The protocol for building GDB to target a different architecture is very similar to that of regular Binutils:
<syntaxhighlight lang="bash">
../gdb.x.y.z/configure --target=$TARGET --prefix="$PREFIX" --disable-werror
make all-gdb
make install-gdb
</syntaxhighlight>
The <tt>'''--disable-nls'''</tt> and <tt>'''--with-sysroot'''</tt> options don't seem to have any effect.
=== GCC ===
Line 98 ⟶ 121:
-->
<
cd $HOME/src
Line 111 ⟶ 134:
make install-gcc
make install-target-libgcc
</syntaxhighlight>
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 <tt>make && make install</tt> as that would build way too much, not all components of gcc are ready to target your unfinished operating system.
Line 121 ⟶ 144:
'''--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. On a multi-core machine, speed up the build by parallelizing it, e.g. <tt>make -j 8 all-gcc</tt>, if 8 is the number of jobs to run simultaneously.
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]]
Line 127 ⟶ 150:
== Using the new Compiler ==
Now you have a "naked" cross-compiler. It does not have access to a C library or C runtime yet, so you cannot use
You can now run your new compiler by invoking something like:
<syntaxhighlight lang="bash">
</syntaxhighlight>
Note how this compiler is ''not'' able to compile normal C programs. The cross-compiler will spit errors whenever you want to #include any of the standard headers (except for a select few that actually are platform-independent, and generated by the compiler itself). This is quite correct - you don't have a standard library for the target system yet!
The C standard defines two different kinds of executing environments - "freestanding" and "hosted". While the definition might be rather fuzzy for the average application programmer, it is pretty clear-cut when you're doing OS development: A kernel is "freestanding", everything you do in user space is "hosted". A "freestanding" environment needs to provide only a subset of the C library: <tt>float.h</tt>, <tt>iso646.h</tt>, <tt>limits.h</tt>, <tt>stdalign.h</tt>, <tt>stdarg.h</tt>, <tt>stdbool.h</tt>, <tt>stddef.h</tt>, <tt>stdint.h</tt> and <tt>stdnoreturn.h</tt> (as of C11). All of these consist of typedef s and #define s "only", so you can implement them without a single .c file in sight.
Note that to have these compiler-provided includes work properly, you need to build your kernel with the <tt>-ffreestanding</tt> flag. Otherwise, they might attempt including your standard library's copy of the headers, which isn't gonna work if you don't have a standard library.
To use your new compiler simply by invoking <tt>$TARGET-gcc</tt>, add <tt>$HOME/opt/cross/bin</tt> to your <tt>$PATH</tt> by typing:
<syntaxhighlight lang="bash">
</syntaxhighlight>
This command will add your new compiler to your PATH for this shell session. If you wish to use it permanently, add the PATH command to your <tt>~/.profile</tt> configuration shell script or similar. Consult your shell documentation for more information.
Line 151 ⟶ 180:
==== ld: cannot find -lgcc ====
You specified that you want to link the GCC low-level runtime library into your executable through the <tt>-lgcc</tt>' switch, but forgot to build and properly install the library.<br>
If you got no warnings or errors while installing libgcc and you still have problems you can copy the library in your project and link it with <tt>-L. -lgcc</tt><br>
The libgcc is at $PREFIX/lib/gcc/$TARGET/<gcc-version>/libgcc.a .
==== Binutils 2.9 ====
What's alphabetically on the top or bottom is not necessarily the latest version. After 2.9 comes 2.10, 2.11, 2.12 and then there are
==== Building GCC: the directory that should contain system headers does not exist ====
Line 162 ⟶ 193:
The solution is simply to create the empty folders:
<
mkdir -p $SYSROOT/mingw/include
mkdir -p $SYSROOT/mingw/lib
</syntaxhighlight>
This will allow the build to proceed. The reason this happens is that the <tt>mingw32</tt> (and mingw itself) configures <tt>INCLUDE_PATH</tt> and <tt>LIBRARY_PATH</tt> to be, as can be guessed, <tt>/mingw/include</tt> and <tt>/mingw/lib</tt>, instead of the defaults <tt>/usr/include</tt> and <tt>/usr/lib</tt>. Why the build fails even though nothing is required in those folders, and why it doesn't just make them, is beyond me.
=== GCC libsanitizer failing to build ===
Sometimes GCC can't build libsanitizer, if that happens append <tt>--disable-libsanitizer</tt> to the configure command.<br>
This only applies for building a hosted compiler.
== More advanced ==
Using this simple cross compiler will be sufficient for quite some time, but at some point you will want the compiler to automatically include your own system headers and libraries. Building an [[OS Specific Toolchain|OS-specific toolchain]] for your own operating system is the way to go from here.
== See Also ==
Line 196 ⟶ 234:
* [https://www.kernel.org/pub/tools/crosstool/ kernel.org various hosts/targets]
'''For Linux i686 host'''
* [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]
'''For Linux x86_64 host'''
Line 201 ⟶ 255:
* [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/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]
The packages from phillid.tk below have been shrunk to about 10 MiB for each pair of packages (GCC & Binutils).
Line 219 ⟶ 277:
* [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
'''For Windows Subsystem for Linux (Beta) host'''
* [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)
'''For
* [https://drive.google.com/file/d/1zn37YmyVrtsPOfe88jZRZ_-_3_jzpXBP/view?usp=sharing i686-elf 13.1.0 target] ('''Important: extracts to a directory called "cross-tk"''')
'''For macOS host'''
x86_64-elf [https://formulae.brew.sh/formula/x86_64-elf-binutils binutils] and [https://formulae.brew.sh/formula/x86_64-elf-gcc gcc] (canonical target name x86_64-pc-elf) can be installed from [https://brew.sh homebrew]:
<pre>
$ brew install x86_64-elf-gcc
</pre>
i686-elf toolchain is also [https://formulae.brew.sh/formula/i686-elf-gcc available] in homebrew.
'''ARM prebuilt toolchains for multiple host platforms'''
|