Why the need for native compiler? Plain and simple. Many software packages are never designed with cross-compiling in mind, and will not build with a cross-compiler (unless you spend inordinate amount of time to fix it...).
Even those that do, aren't always compiled correctly with a cross-compiler. In fact, we're quite fortunate enough that the basic tools are all cross-compiler ready (stuff like util-linux, coreutils, toolchains etc).
Native compiling on ARM is a relatively new development: previously it isn't possible to do so since most ARM platform are low-power systems (as in, doesn't have much CPU power and only very little memory) incapable of hosting a native compiler.
Another intriguing way of doing a native compiling is through Qemu - without any need for a board at all. Qemu is slow, doing compilation in Qemu is even slower - yet it may beat the native compiling on the real ARM machine! Surprised? This interesting idea is treated in great length at Rob Landley's Aboriginal Linux - I'm not going to spoil the fun for you. In fact, the first native compiler I use (in order to short-circuit the process) is the one from Aboriginal Linux.
The proper way of bootstrapping a native compiler is like this:
Like what we did in FirstBoot, we are going to short-circuit this.
What we will do is to use Aboriginals native compiler (not the cross-compiler we used in FirstBoot) to re-build another native compiler, following the guide from Linux From Scratch (LFS) method (version 7.1).
The reasons why I wanted to create my own native compiler instead of using Aboriginal's one are:
As it turns out, libc --- which is part of the toolchain --- is intricately linked with the rest of the tools, like the compiler, linker, etc. Using Aboriginal's compiler means I'm stuck with the libc built into it (uClibc) and I don't have control over how that libc was configured.
My development board and all the interesting boards I'm looking at are ARMv7, many of which come with hardware floating point unit (FPU). Properly compiled, a software that uses FPU can be up to 40% faster than those using soft-float (=sofware floating point emulation).
While I don't need the latest toolchain (which frequently comes with bugs), I do need something newer as Aboriginal's one doesn't understand ARMv7 architecture (and thus failed to compile linux-sunxi kernel and u-boot - that's why we need the Linaro's cross compiler in FirstBoot).
My setup:
setenv bootargs console=${console} ${audio} root=${root} ${rootwait} ${panicargs} loglevel=${loglevel} ${basesfs} ${savefile} ${coldplug} ${extras} fatload mmc 0 0x43000000 script.bin fatload mmc 0 0x48000000 ${kernel} if fatload mmc 0 0x43100000 ${initrd}; then bootm 0x48000000 0x43100000; else bootm 0x48000000; fi
console=tty0 kernel=uImage initrd=uInitrd loglevel=3 audio=hdmi.audio=EDID:0 video=disp.screen0_output_mode=EDID:1280x720p60 #root=/dev/mmcblk0p2 #rootwait=rootwait rootwait=waitdev=3 panicargs=panic=10 #basesfs=basesfs=local savefile=savefile=direct:device:sda3:/ #coldplug= extras=sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=16
Important note before you start building
The Mele doesn't have battery-backup for its RTC, which means that as soon as
I powered it off it the time will be reset to 2010. This isn't good for
building process, as the make
program relies heavily on file timestamps
to determine whether a file is up-to-date and whether it needs re-building.
The system time must be correct (or not too far off) for that to work.
One of the way to do it to enter date-time every time the system boots-up (remember IBM PC? :) ). It gets boring pretty quickly. A better way is to save the current time before shutting down, and use this last shutdown as the system time upon restart. The places to edit is /etc/rc.d/rcS (startup) and /etc/rc.d/rcK (shutdown). Alternatively, you can setup a script which connects to the network and sync the time using NTP.
bash
from aboriginal toolchain to /bin. You don't need
to symlink it to 'sh', but it has to be in /bin because many of the
autotools build system will look for it there.
cd /path/to/linux-sunxi/kernel make ARCH=arm headers_install INSTALL_HDR_PATH=headers
/path/to/linux-sunxi/kernel/headers/include
to /tools/include
.
glibc-ports-2.14.1
in this case) from GCC website.
Expand this tarball inside glibc-2.14.1 directory and rename the extracted
directory to "ports". This tarball contains the support to build glibc
for ARM platform.
Then you create the following configparms
before you run configure
step:
CFLAGS += "-mfloat-abi=hard -mfpu=vfpv3"
Reason? The build process of binutils is smart enough to detect that (naked-)gcc generates hardfloat by default and change the arch-tripled to "gnueabihf". Unfortunately, the build-system of GCC doesn't recognise "gnueabihf" and will get utterly confused (generating OABI instead of EABI altogether) and will stop the build process later (when compiling libgcc).
There is a way of fixing this, which we will apply for the final compiler (gcc pass #3), which we will build in Chapter 6.
CFLAGS_FOR_TARGET="-mfloat-abi=hard -mfpu=vfpv3" \ ../configure ... \ # from LFS --with-arch=armv7-a --with-cpu=cortex-a8 --with-tune=cortex-a8 --with-float=hard --with-fpu=vfpv3
/tools
) which you can use to build stuff. The toolchain you have
in /tools is now comparable in power to aboriginal native compiler which
you used to bootstrap the process.
Don't delete that one yet, though, because aboriginal compiler also provides other build tools like "make" and friends that you haven't built yet (you will, soon enough).
Building the test packages (Tcl, Expect, DejaGNU, and Check) is optional although it is recommended.
ext/Errno/Errno_pm.PL
to make it find errno.h in /tools/include
.
Before you build, read the initial sections of Chapter 6 - that of package management. How do you plan to do it?
As for me, I use paco to log the packages
that I will install in Chapter 6 (which will reside in the final
root filesystem instead of in /tools
). This tool also enables me to
create a binary tarball which I can re-use later. At the time of writing,
I have not yet decided what package manager I will use (although slapt-get
and gslapt sounds nice) --- the most important thing is I have the binary
tarball snapshots of the new installation which I can convert into any
other package format in the future. Paco comes handy for that.
Once that step is cleared, we can continue to build. The most critical here are the steps until you can build the final compiler (step 6.17 - GCC pass 3).
CFLAGS += -mfloat-abi=hard -mfpu=vfpv3 -march=armv7-a -mcpu=cortex-a8 -mtune=cortex-a8 -pipe -O3
Use the configure line from LFS, just need to add this at the end so that it will use hard-float as the default:
--with-arch=armv7-a --with-cpu=cortex-a8 --with-tune=cortex-a8 \ --with-fpu=vfpv3 --with-float=hard
You can continue to choose to build the rest of the tools: autoconf, automake, make, patch, perl, m4, etc are needed to build other packages, the rest is really up to you - again you can build busybox and use its tools, or you can build and use the full coreutils, diffutils, etc.
I don't use the rest of LFS, e.g. Chapter 7 (bootscripts and booting process) - because my system is already bootable using busybox and Fatdog initrd. Instead, I will build more packages and get them to run inside chroot. Once this is working, I will compress the root filesystem and turn it into an SFS - the basesfs SFS of FatdogArm.
Next: BuildingApplications