英文原文出现在
http://www.ibm.com/developerworks/linux/tutorials/l-embedded-distro/section3.html
Cross-compilation
What is cross-compiling?
Cross-compiling is using a compiler on one system to develop code to run on another. Cross-compilation is relatively rare among casual UNIX users, as the default is to have a compiler installed on the system for use on that system. However, cross-compilation becomes quite common (and relevant) when targeting embedded systems. Even when host and target are the same architecture, it is necessary to distinguish between their compilers; they may have different versions of libraries, or libraries built with different compiler options, so that something compiled with the host compiler could fail to run, or could behave unexpectedly, on the target.
什么是交叉编译?
交叉编译就是在一个系统上,使用编译器开发可以在另一个系统上运行的代码。在比较随意的UNIX用户中,交叉编译相对而言是比较少见的,因为默认的情况是安装的编译器都是用在它所在的系统上的。然而,当面对嵌入式系统的时候,交叉编译就变得很常见。即使是在主机和目标机是相同架构的时候,对它们的编译器进行区分也是必要的;它们可能有不同版本的库文件,或者由不同的编译器选项构建得来的库文件,因此,使用主机编译器编译的东西可能不能在目标机上运行,或者其行为在目标机上是不可预期的。
Obtaining cross-compilation tools
It is, in theory, quite possible to build a cross-compiler yourself, but it is rarely practical. The series of bootstrap stages needed can be difficult and time-consuming, and it is often necessary to build a very minimal compiler, which is used to partially configure and build libraries, the headers of which are then used to rebuild the compiler so it can use them, and so on. A number of commercial sources for working cross-compilers for various architecture combinations are available, as well as several free cross-compilation toolkits.
获取交叉编译工具
理论上,自己构建一个交叉编译器是可能的,但是却不是很实际。需要的启动阶段的序列是比较困难的部分,并且比较消耗时间,构建一个小型的编译器也是很必要的,可以用其部分地配置和构建库文件,而在那之后库文件的头文件用来重新构建编译器,因此,编译器可以使用那些库文件,如此往复。各种架构和各种编译器组合的商业的源有很多可用的,也有一些免费的交叉编译工具箱。
Introducing crosstool-ng
Dan Kegel's crosstool (see Resources for details) collects a variety of expertise and a few specialized patches to automatically build toolchains for a number of systems. Crosstool has not been updated in a while, but the new crosstool-ng project builds on this work. For this tutorial, I used crosstool-ng version 1.1.0, released in May of 2008. Download it from the distribution site (seeResources).
介绍crosstool-ng
Dan Kegel的crosstool可以收集很多专家的意见以及特定的补丁以自动地为很多的系统构建工具链。Crosstool已经有一段时间没有更新了,但是新的crosstool-ng项目在从事这个工作。对于本教程而言,为使用crosstool-ng 1.1.0版本,2008年5月份发布。
Installing crosstool-ng
Crosstool-ng has a configure
script. To configure it, just run the script using--prefix
to set a location. For instance:
安装crosstool-ng
Crosstool-ng 有一个configure脚本。为了配置croostool-ng,运行该脚本,使用--prefix选项以设置存放的位置。例如:
$ ./configure --prefix=$HOME/7800/ctng
Once you have configured it, build it using make
and then make install
. The build process creates actng
directory in the 7800 working directory that holds the crosstool-ng build scripts. Add thectng/bin
subdirectory to your path:
一旦配置完毕,使用make构建crosstool-ng,之后运行make install。构建过程在7800工作目录中创建了一个ctng目录,用于保存croostool-ng的构建脚本。将ctng/bin子目录加入到PATH环境变量中:
$ PATH=$PATH:$HOME/7800/ctng/bin
话外音,在configure过程中,翻译者另外还使用sudo apt-get install 命令安装了mawk,gawk,bison,flex, texinfo for makeinfo, automake, libtool, curl, patch, libncurses5-dev。
Configuring crosstool-ng
Crosstool-ng uses a .config
file similar to those used by the Linux kernel. You need to create a configuration file matching your target to use crosstool-ng. Make a working directory for a crosstool-ng build:
配置crosstool-ng
Crosstool-ng 使用的是与Linux kernel使用的 .config 文件相似的 .config 文件。为了使用crosstool-ng,你需要创建一个与你的目标对象匹配的配置文件。为crosstool-ng构建创建一个工作目录:
$ mkdir toolchain-build
$ cd toolchain-build
Now, copy in a default configuration. It's possible to manually configure crosstool-ng, but one of the sample configurations happens to fit the target perfectly:
现在拷贝默认的配置。也可能是手动配置crosstool-ng,但是,例子配置中的某一个或许会较好的匹配你的目标对象:
$ cp ../ctng/lib/ct-ng-1.1.0/samples/arm-unknown-linux-uclibc/* .
Finally, rename the crosstool.config
file:
最后,改crosstool-ng.config文件名为.config
$ mv crosstool.config .config
This copies in a configuration file that targets an armv5te processor, the model used on the TS-7800. It builds with uClibc, a libc variant intended for embedded systems. However, the configuration file does need one modification.
这拷贝了一个面向armv5te处理器的配置文件,也就是TS-7800使用的模型。它与uClibc一起构建,uClibc是libc的一个变种,应用于嵌入式系统。然而,配置文件还需要做一处改动。
话外音,翻译者使用的crosstool-ng是1.13.3版本的,所以对应的是 arm-unknown-linux-uclibcgnueabi/ 。并且,利用mv修改名字之后,.config 文件使用 ls -l 查看不到的。
Fixing the configuration path
The default target directory for a crosstool-ng build is$HOME/x-tools/$TARGET
. For instance, on this build, it would come out asx-tools/arm-unknown-linux-uclibc
. This is very useful if you are building for a lot of targets, but not so useful if you are building for only one. Edit the.config
file and changeCT_PREFIX_DIR
to${HOME}/7800/toolchain
.
调整配置路径
x-tools/arm-unknown-linux-uclibc 。如果你在构建很多的对象,这会显得很有用,但是,如果仅仅构建一个对象的话,就不是那么有用了。编辑 .config 文件,改变 CT_PREFIX_DIR为 ${HOME}/7800/toolchain 。
Building the toolchain
To build the toolchain, run the ct-ng
script with thebuild
argument. To improve performance, especially on a multi-core system, you may want to run with multiple jobs, specified asbuild.#
. For example, this command builds with four jobs:
$ ct-ng build.4
This may take quite a while, depending on your host system. When it's done, the toolchain is installed in$HOME/7800/toolchain
. The directory and its contents are marked read-only; if you need to delete or move them, usechmod u+w
The ct-ng
script takes other arguments, such ashelp
. Note thatct-ng
is a script for the standardmake
utility, and as a result, the output from--help
is just the standardmake
help; usect-ng help
to get the help for crosstool-ng.
If you haven't seen this trick before, it's a neat one. Modern UNIX systems interpret an executable file in which the first line starts with#!
as a script, specifically, a script for the program named on the rest of the line. For instance, many shell scripts start with#!/bin/sh
. The name of the file is passed to the program. For programs that treat their first argument as a script to run, this is sufficient. Whilemake
does not do that automatically, you can give it a file to run with using the-f
flag. The first line ofct-ng
is#!/usr/bin/make -rf
. The-r
flag suppresses the built-in default construction rules ofmake
, and the-f
flag tells it that the following word (which is the script's file name) is the name of a file to use instead of one namedMakefile
. The result is an executable script that usesmake
syntax instead of shell syntax.
为了构建工具链,以build为参数运行ct-ng脚本。为了提高性能,特别是在多核的系统上,你可能想要运行多个任务,以build.#来指定。例如,下面的命令以4个任务来构建:
$ ct-ng build.4
这可能要花一些时间,依赖于你的主机系统。当该命令结束后,工具链安装在了 $HOME/7800/toolchain目录下 。这个目录和其中的内容是只读的;如果你需要删除或者移动它们,使用 chmod u+w。ct-ng脚本也有其他的参数,例如help。注意到,ct-ng是标准的make工具的脚本,结果就是,--help的输出就是标准的make的help;使用ct-ng help可以得到crosstool-ng的help。
如果你以前没有看到过这个小技巧,它其实是较简洁的一个。若可执行文件的第一行以 #! 开头,现代的UNIX系统会将其翻译为一个脚本,特别地,是以该行的其他内容所命名的程序的一个脚本。例如,许多shell脚本以#!/bin/sh开头。文件的名字会传递给这个程序。对于那些将其第一个参数视作要运行的脚本的程序而言,这就足够了。而make不会自动地做这件事,可以使用 -f 标志告诉它运行那个文件。ct-ng的第一行是 #! /usr/bin/make -rf 。-r标志废止了make内嵌的默认的构建规则,而 -f 标志告诉make接下来的字(脚本的文件名)是它要使用的文件,而不是使用名为Makefile的文件。这样做的结果就是,使用make语法的可执行脚本代替了shell语法。
Using the toolchain
For starters, add the directory containing the compiler to your path:
$ PATH=~/7800/toolchain/bin:$PATH
With that in your path, you can now compile programs:
$ arm-unknown-linux-uclibc-gcc -o hello hello.c $file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for
GNU/Linux 2.4.17, dynamically linked (uses shared libs), not stripped
对于初学者而言,将包含编译器的目录添加到你的路径中:
$ PATH=~/7800/toolchain/bin:$PATH
将该目录加入到路径中,现在,你就可以编译程序了:
$ arm-unknown-linux-uclibc-gcc -o hello hello.c
$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for
GNU/Linux 2.4.17, dynamically linked (uses shared libs), not stripped
Where are the libraries?
The libraries used by the toolchain to link binaries are stored inarm-unknown-linux-uclibc/sys-root
, under thetoolchain
directory. This directory forms the basis of an eventual root file system, a topic we'll cover underFilesystems, once the kernel is built.
工具链链接二进制文件所使用的库文件存储在arm-unknown-linux-uclibc/sys-root中,该目录在toolchain目录中。该路径是root file system的基础,一旦kernel构建完毕,我们会在Filesystems下对其进行讨论。
Kernel setup
The kernel distribution tree provided by the vendor is already configured for cross compilation. In the simplest case (which this is), the only thing you have to do to cross compile a Linux kernel is to set theCROSS_COMPILE
variable in the top-level Makefile. This is a prefix that is prepended to the names of the various programs (gcc, as, ld) used during the build. For instance, if you set CROSS_COMPILE
toarm-
, the compile will try to find a program named arm-gcc
in your path. For this build, then, the correct value isarm-unknown-linux-uclibc
. Or, if you don't want to rely on path settings, you can specify the whole path, as in this example:
CROSS_COMPILE ?= $(HOME)/7800/toolchain/bin/arm-unknown-linux-uclibc-
供应商提供的kernel发布包已经为交叉编译进行了配置。最简单的情况是,为交叉编译Linux kernel你需要做的唯一一件事情是,在顶层的Makefile中,设置CROSS_COMPILE变量。它是一个前缀,会添加到构建期间所使用的各种程序(gcc, as, ld)的名字的前面。例如,如果你设置CROSS_COMPILE为 arm-,编译会尝试在你的路径中查找名为 arm-gcc的程序。对于当前的构建而言,正确的值是 arm-unknown-linux-uclibc 。或者,如果你不打算依赖路径的设置,你可以像下面的例子那样,定义整个完整的路径:
CROSS_COMPILE ?= $(HOME)/7800/toolchain/bin/arm-unknown-linux-uclibc-
话外音:
在译者使用ct-ng build.4命令后,出现下面的信息:
[INFO ] Performing some trivial sanity checks
[INFO ] Build started 20120202.201249
[INFO ] Building environment variables
[EXTRA] Preparing working directories
[EXTRA] Installing user-supplied crosstool-NG configuration
[EXTRA] =================================================================
[EXTRA] Dumping internal crosstool-NG configuration
[EXTRA] Building a toolchain for:
[EXTRA] build = i686-pc-linux-gnu
[EXTRA] host = i686-pc-linux-gnu
[EXTRA] target = arm-unknown-linux-uclibcgnueabi
[EXTRA] Dumping internal crosstool-NG configuration: done in 0.17s (at 00:02)
[INFO ] =================================================================
[INFO ] Retrieving needed toolchain components' tarballs
[EXTRA] Retrieving 'linux-2.6.33.19'
[EXTRA] Saving 'linux-2.6.33.19.tar.xz' to local storage
[EXTRA] Retrieving 'gmp-4.3.2'
[EXTRA] Saving 'gmp-4.3.2.tar.bz2' to local storage
[EXTRA] Retrieving 'mpfr-2.4.2'
[EXTRA] Saving 'mpfr-2.4.2.tar.xz' to local storage
[EXTRA] Retrieving 'ppl-0.10.2'
[EXTRA] Saving 'ppl-0.10.2.tar.bz2' to local storage
[EXTRA] Retrieving 'cloog-ppl-0.15.9'
[EXTRA] Saving 'cloog-ppl-0.15.9.tar.gz' to local storage
[EXTRA] Retrieving 'libelf-0.8.13'
[EXTRA] Saving 'libelf-0.8.13.tar.gz' to local storage
其实,需要下载的packages是:
shawn@shawn-ThinkPad-T410:~/src$ ls -al
total 168192
drwxrwxr-x 2 shawn shawn 4096 2012-02-03 20:05 .
drwxr-xr-x 32 shawn shawn 4096 2012-02-03 21:36 ..
-rw-rw-r-- 1 shawn shawn 16306586 2012-02-02 22:31 binutils-2.19.1a.tar.bz2
-rw-rw-r-- 1 shawn shawn 767694 2012-02-02 20:47 cloog-ppl-0.15.9.tar.gz
-rw-rw-r-- 1 shawn shawn 666608 2012-02-03 18:36 dmalloc-5.5.2.tgz
-rw-rw-r-- 1 shawn shawn 240479 2012-02-03 18:47 duma_2_5_15.tar.gz
-rw-rw-r-- 1 shawn shawn 446456 2012-02-03 19:21 expat-2.0.1.tar.gz
-rw-r--r-- 1 shawn shawn 62944934 2012-02-03 16:28 gcc-4.4.3.tar.bz2
-rw-rw-r-- 1 shawn shawn 18386633 2012-02-03 18:55 gdb-7.1a.tar.bz2
-rw-rw-r-- 1 shawn shawn 1897483 2012-02-02 20:39 gmp-4.3.2.tar.bz2
-rw-rw-r-- 1 shawn shawn 148529 2012-02-02 20:47 libelf-0.8.13.tar.gz
-rw-rw-r-- 1 shawn shawn 54336376 2012-02-02 20:38 linux-2.6.33.19.tar.xz
-rw-rw-r-- 1 shawn shawn 147198 2012-02-03 19:26 ltrace_0.5.3.orig.tar.gz
-rw-rw-r-- 1 shawn shawn 951620 2012-02-02 20:40 mpfr-2.4.2.tar.xz
-rw-rw-r-- 1 shawn shawn 2826473 2012-02-03 18:56 ncurses-5.9.tar.gz
-rw-rw-r-- 1 shawn shawn 9820135 2012-02-02 20:44 ppl-0.10.2.tar.bz2
-rw-rw-r-- 1 shawn shawn 499565 2012-02-03 20:03 strace-4.5.19.tar.bz2
-rw-rw-r-- 1 shawn shawn 1804960 2012-02-03 18:36 uClibc-0.9.30.2.tar.xz
shawn@shawn-ThinkPad-T410:~/src$
另外,还需要安装 libexpat1-dev
sudo apt-get install libexpat1-dev.
这样,[INFO ] Installing cross-gdb 这一步才能通过
ct-ng运行信息:
shawn@shawn-ThinkPad-T410:~/linux-from-scratch/crosstool-ng-build$ ct-ng build.4
[INFO ] Performing some trivial sanity checks
[INFO ] Build started 20120203.213704
[INFO ] Building environment variables
[EXTRA] Preparing working directories
[EXTRA] Installing user-supplied crosstool-NG configuration
[EXTRA] =================================================================
[EXTRA] Dumping internal crosstool-NG configuration
[EXTRA] Building a toolchain for:
[EXTRA] build = i686-pc-linux-gnu
[EXTRA] host = i686-pc-linux-gnu
[EXTRA] target = arm-unknown-linux-uclibcgnueabi
[EXTRA] Dumping internal crosstool-NG configuration: done in 0.18s (at 00:03)
[INFO ] =================================================================
[INFO ] Retrieving needed toolchain components' tarballs
[INFO ] Retrieving needed toolchain components' tarballs: done in 0.15s (at 00:03)
[INFO ] =================================================================
[INFO ] Extracting and patching toolchain components
[INFO ] Extracting and patching toolchain components: done in 0.17s (at 00:03)
[INFO ] =================================================================
[INFO ] Checking C library configuration
[EXTRA] Munging uClibc configuration
[INFO ] Checking C library configuration: done in 0.08s (at 00:03)
[INFO ] =================================================================
[INFO ] Installing GMP
[EXTRA] Configuring GMP
[EXTRA] Building GMP
[EXTRA] Installing GMP
[INFO ] Installing GMP: done in 89.98s (at 01:33)
[INFO ] =================================================================
[INFO ] Installing MPFR
[EXTRA] Configuring MPFR
[EXTRA] Building MPFR
[EXTRA] Installing MPFR
[INFO ] Installing MPFR: done in 25.25s (at 01:59)
[INFO ] =================================================================
[INFO ] Installing PPL
[EXTRA] Configuring PPL
[EXTRA] Building PPL
[EXTRA] Installing PPL
[INFO ] Installing PPL: done in 260.42s (at 06:19)
[INFO ] =================================================================
[INFO ] Installing CLooG/ppl
[EXTRA] Configuring CLooG/ppl
[EXTRA] Building CLooG/ppl
[EXTRA] Installing CLooG/ppl
[INFO ] Installing CLooG/ppl: done in 8.57s (at 06:28)
[INFO ] =================================================================
[INFO ] Installing binutils
[EXTRA] Configuring binutils
[EXTRA] Building binutils
[EXTRA] Installing binutils
[INFO ] Installing binutils: done in 64.41s (at 07:32)
[INFO ] =================================================================
[INFO ] Installing kernel headers
[EXTRA] Installing kernel headers
[EXTRA] Checking installed headers
[INFO ] Installing kernel headers: done in 7.20s (at 07:39)
[INFO ] =================================================================
[INFO ] Installing C library headers
[EXTRA] Copying sources to build dir
[EXTRA] Applying configuration
[EXTRA] Building headers
[EXTRA] Installing headers
[INFO ] Installing C library headers: done in 8.82s (at 07:48)
[INFO ] =================================================================
[INFO ] Installing static core C compiler
[EXTRA] Configuring static core C compiler
[EXTRA] Building static core C compiler
[EXTRA] Installing static core C compiler
[INFO ] Installing static core C compiler: done in 199.19s (at 11:07)
[INFO ] =================================================================
[INFO ] Installing C library
[EXTRA] Copying sources to build dir
[EXTRA] Applying configuration
[EXTRA] Building C library
[EXTRA] Installing C library
[INFO ] Installing C library: done in 67.64s (at 12:15)
[INFO ] =================================================================
[INFO ] Installing final compiler
[EXTRA] Configuring final compiler
[EXTRA] Building final compiler
[EXTRA] Installing final compiler
[INFO ] Installing final compiler: done in 328.90s (at 17:44)
[INFO ] =================================================================
[INFO ] Installing libelf for the target
[EXTRA] Configuring libelf
[EXTRA] Building libelf
[EXTRA] Installing libelf
[INFO ] Installing libelf for the target: done in 9.58s (at 17:53)
[INFO ] =================================================================
[INFO ] Installing binutils for target
[EXTRA] Configuring binutils for target
[EXTRA] Building binutils' libraries (libiberty bfd) for target
[EXTRA] Installing binutils' libraries (libiberty bfd) for target
[INFO ] Installing binutils for target: done in 106.62s (at 19:40)
[INFO ] =================================================================
[INFO ] Installing dmalloc
[EXTRA] Configuring dmalloc
[EXTRA] Building dmalloc
[EXTRA] Installing dmalloc
[INFO ] Installing dmalloc: done in 13.40s (at 19:54)
[INFO ] =================================================================
[INFO ] Installing D.U.M.A.
[EXTRA] Copying sources
[EXTRA] Building libraries 'libduma.a libduma.so.0.0.0'
[EXTRA] Installing libraries 'libduma.a libduma.so.0.0.0'
[EXTRA] Installing shared library link
[EXTRA] Installing wrapper script
[INFO ] Installing D.U.M.A.: done in 2.28s (at 19:56)
[INFO ] =================================================================
[INFO ] Installing cross-gdb
[EXTRA] Configuring cross-gdb
[EXTRA] Building cross-gdb
[EXTRA] Installing cross-gdb
[EXTRA] Install '.gdbinit' template
[INFO ] Installing cross-gdb: done in 196.42s (at 23:12)
[INFO ] =================================================================
[INFO ] Installing native gdb
[EXTRA] Building static target ncurses
[EXTRA] Building static target expat
[EXTRA] Configuring native gdb
[EXTRA] Building native gdb
[EXTRA] Installing native gdb
[EXTRA] Cleaning up ncurses
[INFO ] Installing native gdb: done in 321.68s (at 28:34)
[INFO ] =================================================================
[INFO ] Installing gdbserver
[EXTRA] Configuring gdbserver
[EXTRA] Building gdbserver
[EXTRA] Installing gdbserver
[INFO ] Installing gdbserver: done in 12.79s (at 28:47)
[INFO ] =================================================================
[INFO ] Installing ltrace
[EXTRA] Copying sources to build dir
[EXTRA] Configuring ltrace
[EXTRA] Building ltrace
[EXTRA] Installing ltrace
[INFO ] Installing ltrace: done in 8.41s (at 28:55)
[INFO ] =================================================================
[INFO ] Installing strace
[EXTRA] Configuring strace
[EXTRA] Building strace
[EXTRA] Installing strace
[INFO ] Installing strace: done in 29.53s (at 29:25)
[INFO ] =================================================================
[INFO ] Cleaning-up the toolchain's directory
[INFO ] Stripping all toolchain executables
[EXTRA] Installing the populate helper
[EXTRA] Installing a cross-ldd helper
[EXTRA] Creating toolchain aliases
[EXTRA] Removing access to the build system tools
[EXTRA] Removing installed documentation
[INFO ] Cleaning-up the toolchain's directory: done in 1.65s (at 29:26)
[INFO ] Build completed at 20120203.220630
[INFO ] (elapsed: 29:26.65)
[INFO ] Finishing installation (may take a few seconds)...
[29:26] / shawn@shawn-ThinkPad-T410:~/linux-from-scratch/crosstool-ng-build$