Linux ARM Cross Compile On Intel x86
Linux ARM Cross Compile On Intel x86
For the complete list of my articles on Android devices and software, including analysis of devices and system firmware, lists of external resources and tools, and How-To instructions, check the front page of this wiki under the Android heading.
Most pocket Android devices currently utilise an ARM processor implementation. The ARM microprocessor instruction set and operation codes (op-codes) are not compatible with the typical Intel or AMD based PC workstation that derives from the 80x86 range of Intel Architecture (IA) microprocessors (known as x86 for IA32 32-bit CPUs and x64 or amd64 for IA64 64-bit CPUs). Therefore, in order to compile, assemble and link program code for an ARM target device on an x86 host PC a cross-compiler tool-chain is required that runs on x86 but creates executable code for ARM.
Tool-chain¶
The GNU/Linux kernel is so-called because the Linux kernel depends upon the GNU compiler collection (gcc) and binary utilities (binutils) to build the executable vmlinux and it's supporting kernel modules (.ko files). Without the comprehensive set of tools provided by gcc and binutils the Linux kernel cannot be built (there are various projects aimed at substituting them but all serious kernel developers I know will only use the GNU tools).
When building GNU/Linux on an x86-based host for the same x86-based target the regular x86 gcc and binutils are sufficient. However, when the target is a different architecture as in this case (ARM) a version of the tool-chain capable of emitting ARM-compatible executable code is required.
Many GNU/Linux distributions do not pre-package the full set of multi-arch tools required to successfully cross-build (e.g. the Debian/Ubuntu binutils-multiarch package is missing gas, the GNU assembler). Building the tool-chain can be quite a tortuous and time-consuming experience so the pragmatic solution is to install pre-built packages.
Code Sourcery is a company that is licensed and supported by ARM to maintain the GNU ARM tools. They provide several subscription-based pre-built packages for developers (Sourcery G++) that contain a multitude of additional time-saving tools, but they also provide a free-of-cost pre-packaged IA32 set of tools: Sourcery G++ Lite (Note that at this time Code Sourcery do not provide pre-built IA64 packages).
There are three package options provided by Code Sourcery: a GUI-based self-extracting installer, a compressed archive (known as a tar-ball), and the source-code. The GUI (Graphical User Interface) installer is bundled with a Java engine for running the installer and runs a series of 'wizard' dialogs before installing and configuring the package.
I prefer using the tar-ball installation since I can be sure where tools are and control what environment files are changed. Also, the tar-ball can be installed from a text terminal session whereas the GUI cannot.
Installing Multiple Versions¶
Most often it is required that existing versions remain installed and accessible for building existing projects and for specific devices to ensure API/ABI matches. There are three steps to achieve this:
1.Install new tool-chain version in modified location
2.If necessary, modify the locations of the currently installed version(s)
3.Create symbolic links to the preferred version and a simple shell script to easily switch the default tool-chain version
This requires installation to slightly modified locations so that newer installs do not over-write prior installations.
Choose an installation location¶
The convention from the FSH ( File System Hierarchy standard ) is for user-installed binaries and libraries to be placed under /usr/local/ so they do not over-write or otherwise interfere with the system-installed binaries and libraries installed under /usr/ . I chose to install under /usr/local/ but you could choose another location such as /opt/ . The reason for installing under /usr/local/ is that the environment's executable search path variable PATH usually already contains directories in this hierarchy (/usr/local/bin ). Installation to a system location does require super-user privileges.
Some of the paths in the tool-chain archive are already GCC version-specific. I.e. the 2010q1 archives contains GCC v4.4.1 whereas the 2010.09 archive contains GCC v4.5.1. Other paths such as the documentation, the common executables, and the internal executables are the same in each archive so these need modifying to appear in expected FSH locations.
Previously I provided manual instructions for installing and configuring the installation. After I met a requirement to have multiple versions of the ARM GCC installed in parallel I worked up a couple of shell scripts that do all the work. They create and switch symbolic links from standard locations to the currently active GCC version tools. They are attached to this article. Install them in /usr/local/bin/ so they are always available. Don't forget to make them executable:
sudo wget -O /usr/local/bin/arm-install-parallel http://tjworld.net/raw-attachment/wiki/Android/Linux/ARMCrossCompileOnIntel/arm-install-parallel
sudo wget -O /usr/local/bin/arm-gcc-switch http://tjworld.net/raw-attachment/wiki/Android/Linux/ARMCrossCompileOnIntel/arm-gcc-switch
sudo chmod a+x /usr/local/bin/arm-*
Download the latest version of Sourcery G++ Lite for GNU/Linux (or any other version you require). As of this writing it is the 2010.09 version GCC 4.5.1:
wget http://www.codesourcery.com/sgpp/lite/arm/portal/package7851/public/arm-none-linux-gnueabi/arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
Use arm-install-parallel:
$ arm-install-parallel arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
arm-install-parallel version 1.0
Copyright 2010 TJ <linux@tjworld.net>
Licensed on the terms of the GNU GPL version 3
Extracting files from archive, this may take a while...done.
Configuring GCC version 4.5.1 located in /usr/local/arm-2010.09
Here's the same operation for the 2010q1 ARM GCC release:
$ arm-install-parallel arm-2010q1-202-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
arm-install-parallel version 1.0
Copyright 2010 TJ <linux@tjworld.net>
Licensed on the terms of the GNU GPL version 3
Extracting files from archive, this may take a while...done.
Configuring GCC version 4.4.1 located in /usr/local/arm-2010q1
Decide which will be the default version: check what versions are installed:
$ arm-gcc-switch
arm-gcc-switch version 1.0
Copyright 2010 TJ <linux@tjworld.net>
Licensed on the terms of the GNU GPL version 3
Usage: arm-gcc-switch [-f] <version>
-f force removal of existing executables in common bin/ directory
Versions available (default*): 4.4.1 4.5.1
Now configure the preferred default GCC version that will be used when calling arm-none-linux-gnueabi-* tools:
$ arm-gcc-switch 4.5.1
arm-gcc-switch version 1.0
Copyright 2010 TJ <linux@tjworld.net>
Licensed on the terms of the GNU GPL version 3
Default version is not currently configured
Default version now 4.5.1
Done
Check the installation is where we expect and was successful:
which arm-none-linux-gnueabi-gcc
/usr/local/bin/arm-none-linux-gnueabi-gcc
arm-none-linux-gnueabi-gcc --version
arm-none-linux-gnueabi-gcc (Sourcery G++ Lite 2010.09-50) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Switching Between GCC Versions¶
As well as manually controlling a project's build settings by specifying the absolute location of the GCC version required, it is possible to leave the project configuration alone and quickly switch the symbolic links before running a configure or make operation.
Now arm-gcc-switch can be used to easily change all the symbolic links to tools in /usr/local/bin/, for example to check the current default version look for the asterisk (*):
$ arm-gcc-switch
arm-gcc-switch version 1.0
Copyright 2010 TJ <linux@tjworld.net>
Licensed on the terms of the GNU GPL version 3
Usage: arm-gcc-switch [-f] <version>
-f force removal of existing executables in common bin/ directory
Versions available (default*): 4.4.1 4.5.1*
To change the version:
$ arm-gcc-switch 4.4.1
arm-gcc-switch version 1.0
Copyright 2010 TJ <linux@tjworld.net>
Licensed on the terms of the GNU GPL version 3
Replacing existing default version 4.5.1
[sudo] password for tj:
Default version now 4.4.1
Done