Introduction To Cross Compiling
A compiler is a program that converts human readable code into machine readable code or executable code. The computer the compiler runs on is called the host, and the computer the new programs run on is called the target. When the host and target have the same type of hardware, the compiler is a native compiler. When the host and target are different, the compiler is a cross compiler. In theory, a Windows user who wants to make programs for some some other hardware could get the target hardware, boot into Linux on that, and compile natively within that environment. While this is a good approach, you can't do that on say an iPod or router. Compiling uses a lot of resources and the target platform may not even have the resources to build hello world.
Native compiling isn't really a walk in the park. There are issues of word size where copying a pointer into an int may lose data on a 64 bit platform. Default signs is another issue where the char data type can default to signed or unsigned depending on the platform to platform, which can cause bugs. Different systems store binary data internally in different ways, which means that block-reading int or float data from disk or the network may need translation. Some platforms such as arm)can only read or write ints from addresses that are an even multiple of 4 bytes or they have an error. The compiler may have to pad structures to align variables. Treating structures as a lump of data that can be sent to disk or across the network which requires extra work.
Cross compiling has all the above issues and then some. When cross-compiling, configurations will differ between the host system and the target system, so running tests on the host is impossible. Configuration must also cross compile support libraries instead of linking to the libraries on the host when the target doesn't have that library or has an incompatible version. An improperly configured cross-compile toolchain may contain libraries on the host system into the compiled programs which results in failures which are difficult to correct. Dynamically linked programs must access the proper shared libraries at compile time. Shared libraries to the target system need to be added to the cross-compile toolchain so programs can link against them. When cross-compiling, testing a hello world program built successfully can require configuring (at least) a bootloader, kernel, root file system, and shared libraries.