Why do I need a Cross Compiler?: Difference between revisions

m
→‎Articles: add zig cc
[unchecked revision][unchecked revision]
No edit summary
m (→‎Articles: add zig cc)
 
(10 intermediate revisions by 6 users not shown)
Line 1:
::''Notice: ''This page is specific to GCC. If you use another compiler, you should research how cross-compilation is normally done with that compiler and do it that way. GCC is quite tightly bound to its native target system, many other compilers are not. Some compilers don't even have a native target, they are always cross-compilers.
You need to use a [[GCC_Cross-Compiler|cross-compiler]] ''unless'' you are developing on your own operating system. The compiler ''must'' know the correct [[Target Triplet|target platform]] (CPU, operating system), otherwise you will run into trouble. You may be able to use the compiler that comes with your system if you pass a number of options to beat it into submission, but this will create a lot of completely imaginary problems.
 
You need to use a [[GCC_Cross-Compiler|cross-compiler]] ''unless'' you are developing on your own operating system. The compiler ''must'' know the correct [[Target Triplet|target platform]] (CPU, operating system), otherwise you will run into trouble. You may be able to use the compiler that comes with your system if you pass a number of options to beat it into submission, but this will create a lot of completely imaginaryunnecessary problems.
 
It is possible ask your compiler what target platform it is currently using by calling the command:
 
<sourcesyntaxhighlight lang="bash">
gcc -dumpmachine
</syntaxhighlight>
</source>
 
If you are developing on 64-bit Linux, then you will get a response such as 'x86_64-unknown-linux-gnu'. This means that the compiler thinks it is creating code for Linux. If you use this GCC to build your kernel, it will use your system libraries, headers, the Linux [[libgcc]], and it will make a lot of problematic Linux assumptions. If you use a [[GCC_Cross-Compiler|cross-compiler]] such as i686-elf-gcc, then you get a response back such as 'i686-elf' that means the compiler knows it is doing something else and you can avoid a lot of problems easily and properly.
Line 12 ⟶ 14:
{{Main|GCC Cross Compiler}}
 
It is easy and takes a few moments to [[GCC_Cross-Compiler|build a cross-compiler]] that targets your operating system. It may take a while to build it on slower computers, but you only need to do it once, and you save all the time you would otherwise spend on "fixing" the completely imaginaryunnecessary problems you would encounter otherwise. Later on, when you start building a user-space for your operating system, it is worth creating an [[OS_Specific_Toolchain|OS Specific Toolchain]] for absolute control of the compiler and to easy compiling user-space programs.
 
== Transitioning to a Cross-Compiler ==
Line 21 ⟶ 23:
 
=== Using cross-tools ===
You get a lot of useful programs when you build your cross-binutils. For instance, you get i686-elf-readelf, i686-elf-as, i686-elf-objdump, i686-elf-objcopy, and more. These programs know about your operating system and handle everything correctly. You can use some of the programs that come with your local operating system instead (readelf, objcopy, objdump) if they know about the file format of your operating system, but it is in general best to use your cross tools instead. These tools all consistently have the prefix 'i686-elf-' if the platform of your OS is i686-elf.
 
=== Options that you should pass to your Compiler ===
Line 33 ⟶ 35:
 
==== -fno-exceptions, -fno-rtti (C++) ====
It is wise to disableddisable C++ features that doesndon't work out-of-the-box in kernels. You need to supply a C++ support library to the kernel (in addition to libgcc) to make all C++ features work. If you don't use these C++ features, it should be sufficient to pass these options.
 
=== Options you should link with ===
These options only make sense when linking (not when compiling) and you should use them. You should pass the compilation options as well when linking, as some compilation options (such as <tt>-mno-red-zone</tt>) control the ABI and this needs to be known at link time as well).
 
==== -nostdlib (same as both -nostartfiles -nodefaultlibs) ====
Line 42 ⟶ 44:
 
==== -lgcc ====
You disable the important [[libgcc]] library when you pass -nodefaultlibs (implied by -nostdlib). The compiler needs this library for many operations that it cannot do itself or that is more efficient to put into a shared function. You must pass this library at the end of the link line, after all the other object files and libraries, or the linker won't use it and you get strange linker errors. This is due to the classic static linking model where aan object filesfile from a static library is only pulled in if it is used by ana previous object file so far. Linking with [[libgcc]] must come after all the object files that might use it.
 
=== Options that you shouldn't pass to your Compiler ===
Line 68 ⟶ 70:
 
== Problems that occur without a Cross-Compiler ==
You need to overcome a lot of imaginary problems to use your system gcc to build your kernel. You don't need to deal with these problems if you use a cross-compiler.
 
=== More complicated compilation commands ===
The compiler assumes it is targetting your local system, so you need a lot of options to make it behave. A trimmed down command sequence for compiling a kernel without a cross-compiler could look like this:
 
<sourcesyntaxhighlight lang="bash">
as -32 boot.s -o boot.o
gcc -m32 kernel.c -o kernel.o -ffreestanding -nostdinc
gcc -m32 my-libgcc-reimplemenation.c -o my-libgcc-reimplemenation.o -ffreestanding
gcc -m32 -T link.ld boot.o kernel.o my-libgcc-reimplemenation.o -o kernel.bin -nostdlib -ffreestanding
</syntaxhighlight>
</source>
 
Actually, the average case is worse. People tend to add many more problematic or redundant options. With a real cross-compiler, the command sequence could look this this:
 
<sourcesyntaxhighlight lang="bash">
i686-elf-as boot.s -o boot.o
i686-elf-gcc kernel.c -o kernel.o -ffreestanding
i686-elf-gcc -T link.ld boot.o kernel.o -o kernel.bin -nostdlib -ffreestanding -lgcc
</syntaxhighlight>
</source>
 
=== Reimplementing libgcc ===
Line 97 ⟶ 99:
You need to pass even more options to the command lines that build programs for your operating systems. You need a -Ipath/to/myos/include and -Lpath/to/myos/lib to use the C library, and more. If you set up an [[OS Specific Toolchain]], you just need
 
<sourcesyntaxhighlight lang="bash">
i686-myos-gcc hello.c -o hello
</syntaxhighlight>
</source>
 
to cross-compile the hello world program to your operating system.
Line 120 ⟶ 122:
=== What are the basics of cross compiling? ===
 
The "build" machine is the machine you're compiling the software on. This software being compiled may be compiled to run on some other type of machine. See, you may be building on an x86-based machine, and wishing for the software to run on a SPARC based machine. The build machine is implicit and will usually be auto-detected by the configure script for the software. Its only real purpose is so that, if the software being compiled chooses to keep the configure arguments used to configure it somewhere in the built package, the people to whom the package is distributed will know what machine the package was built on. The name of the build machine may be used to configure tothe package to use workarounds as well if the build machine is universally known to have certain problems building that software.
 
The "host" machine is the machine on which the software must run. So in the previous example, the "build" machine is an i686-elf-yourBuildOs machine, and the host is a sparc32-elf-unix4 machine.
Line 171 ⟶ 173:
* [[GCC Cross-Compiler]]
* [[Cross-Porting Software]]
* [["zig cc" Cross-Compiler]]
 
[[Category:Compilers]]
[[Category:FAQ]]
[[Category:OS_Development]]