Buildroot
Buildroot的用法和文档由Thomas Petazzoni提供,文稿由Karsten Kruse、Ned Ludd、Martin Herren等整理。
最后修改时间:2007-09-19 02:08:10 -0700 (Wed, 19 Sep 2007)
l 关于Buildroot
l 获取Buildroot
l 使用Buildroot
l 定制目标文件系统
l 定制Busybox的配置
l 定制uClibc的配置
l Buildroot运行方式
l 使用uClibc 工具链
l 在Buildroot外部使用 uClibc 工具链
l 被下载包的存放位置
l 使用其他软件来扩展Buildroot
l 资源
关于Buildroot
Buildroot是一个Makefiles和patches的命令集,它可以非常简单的为你的目标系统产生一个交叉编译工具链和根文件系统 。这个交叉编译工具使用uClibc (http://www.uclibc.org/),uClibc是一个很小的标准库。
Buildroot那些从事于嵌入式系统的人来说是很有用处的。嵌入式系统经常使用的处理器都不是平常用于普通电脑的x86处理器它可能是PowerPC、 MIPS、ARM等处理器.
一个编译工具链就是一些工具的的命令集,这些工具允许你为你的目标系统编译源代码。它主要由编译器(在我们的例子中为gcc),二进制的工具集,如汇编程序和连接器(在我们的例子中为binutils),还有就是C的标准库(如GNU Libc、uClibc或者是dietlibc)。在你的开发平台上安装的系统里面要包含一个编译工具链,这个编译工具链是你可以在你的系统上编译应用程序。如果你使用的是一台PC机,你的编译工具链运行在x86处理器上,或者生成x86处理器可以运行的代码。在大多数的Linux系统里面,这个编译工具链使用的是GNU libc作为C的标准库。这个编译工具链被称之为“主机编译工具链”,而且通常来说,这台你在上面工作的电脑被称之为“主机系统”。这个编译工具链由你的系统提供,与Buildroot无关。
如同上面所说的一样,这个编译工具链随着你操作系统一起为你的主机系统上的处理器运行或者生成源代码。就像你的嵌入式系统拥有一个不同的处理器一样,你需要一个交叉编译工具链:它是一个运行在你的主机系统上但是为你的目标系统(和处理器)生成代码的工具链。举例来说,如果你的主机系统用的是x86处理器,你的目标系统用的是ARM处理器,你主机上的这个普通的编译工具链运行在你的x86处理器上并且为x86生成代码,但是交叉编译工具运行在你的x86处理器上但是为ARM生成代码
及时你的嵌入式系统用的是一个x86处理器,你也可能对Buildroot产生情趣,主要原因有以下两点:
· 显然,你的主机系统上的编译工具集用的是GNU Libc,GNU Libc是一个完整的标准库,但是它体积庞大。与你在你的目标系统上使用GNU Libc相比,你可以使用uClibc,uClibc是一个很微小的标准C库。如果你想使用这个C库,你需要一个编译工具集来生成二进制工具去链接它。Buldroot能够替你完成这些事。
· Buildroot 自动地使用工具如busybox来建立一个根文件系统。它比手工完成一个根文件系统的制作更简单。
你可能很好奇了,为什么这样一个工具在你手工编译gcc、binutils、uClibc和其他所有的工具的时候是必须的。当然,手工完成它也是可能的。但是在处理所有的配置选项的时候,由于所有的问题如每一个gcc或者binutls版本都是耗费时间和令人厌倦的Buildroot通过使用Makefiles文件来自动操作这个过程,并且收集了每一个gcc和binutils版本的补丁,使他们能应用于更过的体系架构上面。
获取 Buildroot
Buildroot通过每天的SVN镜像文件或者直接使用SVN就可以得到。最新的镜像文件一直都放置在 http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2,并且之前的镜像也是放置在 http://buildroot.uclibc.org/downloads/snapshots/.
使用SVN来下载Buildroot,你可以简单的使用uClibc buildroot 网站(http://buildroot.uclibc.org)下面的“Accessing SVN”页面(http://buildroot.uclibc.org/subversion.html)里描述的规则,并且下载SVN的各个模块。为了不让你着急,下面是一个简介的方法:
$ svn co svn://uclibc.org/trunk/buildroot
使用 Buildroot
Buildroot有一个较好的配置工具,就像你在Linux(http://www.kernel.org/)内核和Busybox(http://www.busybox.org/)里面看到的类似。 注意的是你作为一个普通用户,你可以在里面构造任何东西。这里不需要你是一个超级用户来配置和是用Buildroot。第一步是运行配置助手:
$ make menuconfig
对于配置的每个条目来说,你都可以找到相关联的帮助,帮助信息描述了该条目的用途。
一个关键的配置项目是PROFECT,它决定了在构建这些包的位置,以及结果安装的位置。
一旦所有的都配置完成了,配置工具将产生一个.config文件,里面包含了了你的配置信息,它将会被Makefile使用,来决定需要哪些文件。
让我们继续:
$ make
这个命令将下载、配置并且编译所有被选择的工具,并且最后产生一个目标文件系统。这个目标文件系统被命名为root_fs_ARCH.EXT,ARCH是你的处理器架构类型,EXT依赖于你在配置工具中选择的目标文件系统。这个文件存放在“binaries/$(PROJECT)/”目录里面。
创建你自己的目标板支持
一旦一个包被打开了,就可以手动的升级配置文。Buildroot能自动的保存buildroot、linux、busybox、uclibc和u-boot的配置文件,存放在 “local/$(PROJECT) ”中,使用的命令如下:
$ make saveconfig
一旦一个buildroot的配置文件同过saveconfig被创建了,缺省的“$(TOPDIR)/.config” 文件就可以通过下面的方式被覆盖了:
$ make BOARD=<project>
Buildroot以后会使用 “local/<project>/<project>.config”而不是“.config”。
如果你想修改你的目标板,你可以使用下面的命令来复制该工程的配置文件到“.config”:
$ make BOARD=<project> getconfig
你可以设置环境变量BUILDROOT_LOCAL使它指向这个目录来在多个buildroot树中共享你定制的目标板支持的文件夹。
离线构建
如果你想离线构建,并且仅仅是想下载之前在“make menuconfig”中选择了的所有的源代码,执行如下:
$ make source
你现在可以断开连接,复制你的dl目录中的内容到你的build-host。
环境变量
Buildroot可以选择的遵循了部分已经通过的环境变量:
· HOSTCXX
· HOSTCC
· UCLIBC_CONFIG_FILE=<path/to/.config>
· BUSYBOX_CONFIG_FILE=<path/to/.config>
一个例子,使用config文件来定位顶级目录文件夹和你的$HOME:
$ make UCLIBC_CONFIG_FILE=uClibc.config BUSYBOX_CONFIG_FILE=$HOME/bb.config
如果你想在你的主机上使用一个编译器而不是缺省的gcc或者是g++来构建helper-binaries,执行如下:
$ make HOSTCXX=g++-4.3-HEAD HOSTCC=gcc-4.3-HEAD
使用自动完成
如果你很懒散,你不想打字打出make menuconfigminglingh,你可以在你的shell中使用自动完成。这里是怎么样你才可以使用你的bash:
$ complete -W menuconfig make
然后只是打出一行开头的字符,通过按TAB键来调用bash去完成它:
$ make me<TAB>
这样bash就会为你附加上nuconfig!
作为选择,有些发行版(其中Debian和Mandriva就是一个例子)可以更好的补充。根据你的发行版本,你可能必须安装一些软件包以便完成. 在Mandriva上,这个包为bash-completion, 而Debian把它作为了bash软件包的一部分。
其他的shells,比如zsh, 也有完成这个任务的措施。具体的查看你的shell的文档。
定制目标文件系统
这里有一些定制最终目标文件系统的方法:
· 直接定制目标文件系统,并且重建映像文件。目标文件系统存放在project_build_ARCH/root/ 目录下面,这里的ARCH就是你选择的目标架构。你可以很简单的在这里修改,并且重新编译来重建目标文件系统。这个方法允许你在目标文件系统上进行任何的改变,但是如果你决定完全重新构建你的工具链和工具集,这些修改都会被被丢失。
· 定制目标文件系统框架,存放在target/generic/target_skeleton/目录下面,你可以在这里自定义配置文件或者其他东西。但是,完整的目录层次还没有实现,它是在编译的过程中创建的。所以你不能在这个文件系统框架上做任何事情,即使你完全重建了交叉编译工具链和工具集,但是这种改变依然被存在。
你也可以自定义target/generic/device_table.txt 文件,它是被工具集用来创建目标文件系统的权限设置和设备节点。target/generic/skel.tar.gz 文件包含了根文件系统的主要文件夹,而且我们没有要去改变它。在这个压缩包里面的主要文件目录都在框架里面,因为它包含了指向框架的符号链接,以防被损坏。
这些自定义配置在真正的映像产生之前将被展开到project_build_ARCH/root/ 目录里面。所以通过运行make来重建映像会把所有的修改都传递到映像里面。
· 当使用make menuconfig来配置要建立的系统时,你可以指定在PROJECT 中的/etc/hostname和/etc/issue (欢迎条)的内容。
定制Busybox的配置
Busybox是完全可以配置的,而且你也想定制它。你可以遵循下面的简单步骤来配置它,它不是最佳的方式,但是它最简单额日期额可以正常工作。
1. 首先使用buildroot运行一次busybox,在这一次里面不需要进行任何的配置。
2. 调用make busybox-menuconfig。这个配置工具使你可以电脑告知所有的东西。
3. 再一此运行编译buildroot的编译。
另外,如果你知道你想要的修改的选项而不需要配置工具的话,你也可以修改package/busybox/busybox-<version>.config 文件 。
如果你想使用busybox的已经存在的配置文件,请参照后面的环境变量。
定制uClibc的配置
就像BusyBox一样,uClibc提供了许多配置选项。 他们允许你根据你不同的需求和局限性选择不同的功能。
最简单的修改uClibc配置的步骤如下:
1. 首先不定制uClibc来编译运行一次buildroot。
2. 调用make uclibc-menuconfig。这是一个很好的配置工具,它与曾在Linux内核和Buildroot里面所使用的类似。然后进行你的正确配置。
3. 拷贝.config到toolchain/uClibc/uClibc.config或者是到 toolchain/uClibc/uClibc.config-locale。如果你没有在Buildroot里面选择本地支持的话就使用前者,相反就用后者。
4. 再一此运行编译buildroot的编译。
另外,你也可以直接修改toolchain/uClibc/uClibc.config或者 toolchain/uClibc/uClibc.config-locale而不需要使用上面的配置工具。
如果你想使用一个已经存在uclibc配置文件,I请参照后面的环境变量。
Buildroot的运行方式
如上面所说的一样, Buildroot是一个基本的并使用恰当的选项去下载、配置、编译软件的命令集。它还包括了一些软件的补丁,主要的都是与交叉编译工具链有关 (gcc,binutils 和uClibc)。
主要的是每一个软件都有一个Makefile文件,他们都被命名为以.mk为扩展名。Makefiles主要分成以下四部分:
· 工程 (在 project/ 目录) 包含了在这个相同buildroot目录树里面涉及到构建根文件系统Makefiles和相关联的文件。
· 工具链 (在toolchain/ 目录) 包含了所有的设计到交叉工具链(binutils,ccache, gcc,gdb,kernel-headers and uClibc)的Makefiles和相关联的文件。
· 包 (在package/ 目录) 包含了Buildroot编译并要加载到目标系统上的用户空间的工具的Makefiles和相关联的文件。对于每一个工具都有想对应的子目录。.
· 目标 (在target/目录) 包含了用于生成一目标文件系统映像的软的Makefiles和相关文件。有四种类型的文件系统被支持:ext2,jffs2,cramfs和squashfs。他们中的每一个,都有一个子目录来存放需要的文件。这里也有一个缺省的default/ 目录,里面包含了目标文件系统的框架。
每个文件夹至少包含两个文件:
· something.mk 是一个用于下载、配置、编译和安装的Makefile。
· Config.in是配置工具描述文件的一部分,它描述了当前软件的相关选项。
核心的Makefile文件通过下面的步骤来完成任务(在配置完成以后):
1. 创建下载目录(缺省的为dl/)。该目录就是被下载的压缩包存放的地方。非常有必要去了解该目录下的压缩包,我们可以将它保存到其他地方以免将来使用的时候再去下载。
2. 创建共享的构建目录(缺省的为build_ARCH/ ,ARCH是目标系统的体系架构)。在这个目录里面存放的是已经被编译了的不需要配置的用户空间的工具。当使用同一架构构建多个目标系统的时候,首先构建的会完全的通过下载、配置、编译等步骤,但是第二个或者以后的就只需要拷贝第一次的结果,主要可以加速构建的进度。
3. 创建工程的详细目录 (缺省的为project_build_ARCH/$(PROJECT), ARCH是目标系统的体系架构)。这里是所有的可配置的用户空间工具的被编译的目录。这个特殊的构建目录是必须的, 如果两个不用的目标体系架构都需要使用一个特殊的软件包,这样这个软件包就根据目标体系架构有不同的配置,busybox和linux就是其中的例子。
4. 创建工程的结果目录(缺省的为binaries/$(PROJECT),ARCH是目标系统的体系架构)。这个目录是根文件系统映像存放的地方,也是存放目标系统的Linux内核映像和其他工具集、boot-loaders 等的地方。
5. 创建工具链目录(缺省的为toolchain_build_ARCH/,ARCH是目标系统的体系架构)。在这里交叉工具链被编译。
6. 设置平台目录(缺省的为build_ARCH/staging_dir/)。这里是交叉编译工具链安装的地方。如果你想使用相同的交叉编译工具链来作为其他的用途,比如说编译第三方的应用软件,你可以添加build_ARCH/staging_dir/usr/b路径到PATH中,只有你就可以使用arch-linux-gcc来编译你的程序了。为了设置这个目录,首先应该移除这个它,然后它在该目录里面创建子目录和符号连接。
7. 创建目标文件系统 (缺省的为project_build_ARCH/root/) 和目标文件系统框架。这个目录将包含最终的根文件系统。要使它更新,首先应该删除它,然后解压 target/generic/skel.tar.gz 文件来创建主要的子目录文件夹和符号链接,并拷贝在target/generic/target_skeleton中可用的框架,然后删除没有用的.svn/目录。
8. 添加TARGETS的依赖关系。一般将会检查这些包的配置选项是否可用,然后通过把它添加到TARGETS全局变量中来定制要被编译的软件包。
在相同的buildroot源代码目录树构建几个不同的工程
背景知识
如果每个工程都是为不同的体系架构构建的话,buildroot支持在同一个源代码目录树中构建若干不同的工程。
根文件系统被创建在“build_<ARCH>/root”文件夹中,对于每一个体系架构来说,它都是唯一的。交叉工具链被建立在“toolchain_build_<ARCH>”目录。
如果用户希望为相同的体系架构构建若干个根文件系统,就应该在配置中加上前缀或者后缀,这样的话,建立的根文件系统就被放置在“<PREFIX>_build_<ARCH>_<SUFFIX>/root”。通过设置唯一的前缀和后缀,使每一个工程都有一个唯一的根文件系统树。
这个方法的缺点就是为同一个芯片建立两个工程,每一个工程都要建立一个新的工具链,这个构建过程将耗费更多的时间。
如果使用的是gcc-4.x.y 的话,这个缺点就不是那么的明显了,因为gcc-4.x.y 允许使用外部工具链。由于某些软件包需要一些特殊功能,如果使用的一个外部的工具链,这可能就缺少一些必要的功能,来构建一个根文件系统。
一个更大的问题是build_<ARCH>目录树也是拷贝的,这样的话,每个软件包也都为每一个工程重建一次,导致花费更长的时间。
共享工程的工具链和构建的软件包
当工作在一个工程的时候,允许用户在同一个目录树为同一个体系架构构建多个根目录树。工具链个软件包的构建目录将会被共享,但是每一个具体的工程都有一个专门的目录。
在使用的这个方法的时候,更多的是,如果在第一个工程建立时,所有的软件包都没有被编译。这个过程就几乎同原来的过程一样了,所有下载的软件包被下载然后提取到共享目录“build_<ARCH>/<package>”中,然后配置、编译。
二进制软件包和头文件被安装到共享目录$(STAGING_DIR)中,然后这个工程专门的根文件系统被设置到“$(TARGET_DIR)”。
在构建结束的时候,还要通过这个根文件系统来生成一个最后的二进制根文件系统。
一旦第一个工程构建结束,在构建其他工程的时候就只是调用已经共享在“build_<ARCH>/<>”目录下的内容来生成新的文件系统。
如果一些软件包没有用于第一个工程,就只能通过提取-配置-编译的步骤了。
执行
核心是要建立两个新的目录:
· project_build_<ARCH>
· binaries;
每个目录里面都包含了每个工程的子目录。子目录的名字是用户在配置buildroot的时候配置的,它由下面的内容组成:
Project Options ---> Project name
这里定义$(PROJECT)变量。
缺省的名字(project name)为“uclibc”。
"package/Makefile.in"定义为:
PROJECT_BUILD_DIR:=project_build_$(ARCH)/$(PROJECT)
BINARIES_DIR:=binaries/$(PROJECT)
它也定义了目标根文件系统的本地路径:
TARGET_DIR:=$(PROJECT_BUILD_DIR)/$(PROJECT)/root
也就是说:如果用户使用“myproject”作为$(PROJECT) 名称:
· "project_build_<ARCH>/myproject"
· "binaries/myproject"
就会被创建。
现在,根文件系统,busybox和AtmelU-Boot版本,还有Atmel专门的一些bootloader像阿通1-bootstrap和dataflashboot.bin都被构建在“$(PROJECT_BUILD_DIR)”中。
所有体系架构最后的二进制文件都存放在“$(BINARIES_DIR)”目录中。
总结
工程将会共享不会引起冲突的文件夹,但是使用唯一的构建目录,在该目录中,用户可以配置自己的配置。
该做的事情
1. Linux
当前的Linux版本总是有缺陷的, 它仅仅工作在用户选择使用较少额选项作为内核基本的头文件。它仅服务于用户选择的少量的内核作为主要内核的基础。虽然Makefle有一些关联,允许开发者在target/device/*/* Makefiles中指定内核的版本,但是如果选择了其他的版本,构建将会失败的。
原因是内核的补丁没有被"target/linux/linux.mk"用来编译脚本片段。他们仅用于"toolchain/kernel-headers/*.makefile"去编译脚本片段。
如果内核头文件和Linux版本不一样的话,在“build_<ARCH>/<>”将会有两个“linux-2.6.X.Y”文件夹,每一个都自己的补丁命令。
在这个方案中的解决办法是,将Linux的构建目录移动到“project_build_<ARCH>/<project name>/linux-2.6.X.Y”,结合这个方法把可以应用的补丁进行配置。用于产生头文件的Linux的源代码目录树很可能会被移动到“toolchain_build_<ARCH>”目录中去。
用户可以选择下面三种不同的策略:
o 保守策略: 仅仅使用内核头文件支持的版本
o 稳定Linux的策略: 允许任何的2.6.X.Y 的组合体(最小为 2.6.19 )
o 激进用户策略: 允许“-git”或者是“-mm”,或者是用户下载内核
The current kernel patches can be configured to be applied to the linux source tree even if the version differs from the kernel header version.
Since the user can select any kernel-patch he/she will be able to select a non-working combination. If the patch fails, the user will have to generate a new proprietary kernel-patch or decide to not apply the kernel patches
Other optional patches will be board specific or architecture specific patches.
There will also be a way for the user to supply absolute or relative paths to patches, possibly outside the main tree. This can be used to apply custom kernel-header-patches, if the versions available in buildroot cannot be applied to the specific linux version used
Maybe, there will also be a possibility to supply an "URL" to a patch available on Internet.
2. Configurable packages
Many packages can, on top of the simple "enable/disable build", be further configured using Kconfig. Currently these packages will be compiled using the configuration specified in the ".config" file of the first project demanding the build of the package.
If another project uses the same packages, but with a different configuration,these packages will not be rebuilt, and the root file system for the new project will be populated with files from the build of the first project
If multiple project are built, and a specific package needs two different configuration, then the user must delete the package from the "build_<ARCH>" directory before rebuilding the new project.
A long term solution is to edit the package makefile and move the build of the configurable packages from "build_<ARCH>" to "project_build_<ARCH>/<project name>" and send a patch to the buildroot mailing list.
3. Naming conventions
Names of resulting binaries should reflect the "project name"
4. Generating File System binaries
Packages which needs to be installed with the "root" as owner, will generate a ".fakeroot.<package>" file which will be used for the final build of the root file system binary.
This was previously located in the "$(STAGING_DIR)" directory, but was recently moved to the "$(PROJECT_BUILD_DIR)" directory.
Currently only three packages: "at", "ltp-testsuite" and "nfs-utils" requests fakeroot.
The makefile fragments for each file system type like "ext2", "jffs2" or "squashfs" will, when the file system binary is generated, collect all present ".fakeroot.<package>" files to a single "_fakeroot.<file system>" file and call fakeroot.
".fakeroot.<package>" files are deleted as the last action of the Buildroot Makefile.
It needs to be evaluated if any further action for the file system binary build is needed.
Using the uClibc toolchain
You may want to compile your own programs or other software that are not packaged in Buildroot. In order to do this, you can use the toolchain that was generated by Buildroot.
The toolchain generated by Buildroot by default is located in build_ARCH/staging_dir/. The simplest way to use it is to add build_ARCH/staging_dir/usr/bin/ to your PATH environnement variable, and then to use arch-linux-gcc, arch-linux-objdump, arch-linux-ld, etc.
For example, you may add the following to your .bashrc (considering you're building for the MIPS architecture and that Buildroot is located in ~/buildroot/) :
export PATH="$PATH:~/buildroot/build_mips/staging_dir/usr/bin/"
Then you can simply do :
mips-linux-gcc -o foo foo.c
Important : do not try to move a gcc-3.x toolchain to an other directory, it won't work. There are some hardcoded paths in the gcc configuration. If the default toolchain directory doesn't suit your needs, please refer to the Using the uClibc toolchain outside of buildroot section.
If you are using a current gcc-4.x, then use --sysroot and -isysroot since these toolchains have fully functional sysroot support. No hardcoded paths do exist in these configurations.
Using the uClibc toolchain outside of buildroot
By default, the cross-compilation toolchain is generated inside build_ARCH/staging_dir/. But sometimes, it may be useful to install it somewhere else, so that it can be used to compile other programs or by other users. Moving the build_ARCH/staging_dir/ directory elsewhere is not possible if using gcc-3.x, because there are some hardcoded paths in the toolchain configuration. This works, thanks to sysroot support, with current, stable gcc-4.x toolchains, of course.
If you want to use the generated gcc-3.x toolchain for other purposes, you can configure Buildroot to generate it elsewhere using the option of the configuration tool : Build options -> Toolchain and header file location, which defaults to $(BUILD_DIR)/staging_dir/.
Location of downloaded packages
It might be useful to know that the various tarballs that are downloaded by the Makefiles are all stored in the DL_DIR which by default is the dl directory. It's useful for example if you want to keep a complete version of Buildroot which is know to be working with the associated tarballs. This will allow you to regenerate the toolchain and the target filesystem with exactly the same versions.
If you maintain several buildroot trees, it might be better to have a shared download location. This can be accessed by creating a symbolic link from the dl directory to the shared download location.
I.E:
ln -s <shared download location> dl
Another way of accessing a shared download location is to create the BUILDROOT_DL_DIR environment variable. If this is set, then the value of DL_DIR in the project is overridden. The following line should be added to "~/.bashrc".
export BUILDROOT_DL_DIR <shared download location>
Extending Buildroot with more software
This section will only consider the case in which you want to add user-space software.
Package directory
First of all, create a directory under the package directory for your software, for example foo.
Config.in file
Then, create a file named Config.in. This file will contain the portion of options description related to our foo software that will be used and displayed in the configuration tool. It should basically contain :
config BR2_PACKAGE_FOO
bool "foo"
default n
help
This is a comment that explains what foo is.
http://foosoftware.org/foo/
Of course, you can add other options to configure particular things in your software.
The real Makefile
Finally, here's the hardest part. Create a file named foo.mk. It will contain the Makefile rules that are in charge of downloading, configuring, compiling and installing the software. Below is an example that we will comment afterwards.
1 #############################################################
2 #
3 # foo
4 #
5 #############################################################
6 FOO_VERSION:=1.0
7 FOO_SOURCE:=foo-$(FOO_VERSION).tar.gz
8 FOO_SITE:=http://www.foosoftware.org/downloads
9 FOO_DIR:=$(BUILD_DIR)/foo-$(FOO_VERSION)
10 FOO_BINARY:=foo
11 FOO_TARGET_BINARY:=usr/bin/foo
12
13 $(DL_DIR)/$(FOO_SOURCE):
14 $(WGET) -P $(DL_DIR) $(FOO_SITE)/$(FOO_SOURCE)
15
16 $(FOO_DIR)/.source: $(DL_DIR)/$(FOO_SOURCE)
17 $(ZCAT) $(DL_DIR)/$(FOO_SOURCE) | tar -C $(BUILD_DIR) $(TAR_OPTIONS) -
18 touch $@
19
20 $(FOO_DIR)/.configured: $(FOO_DIR)/.source
21 (cd $(FOO_DIR); rm -rf config.cache; /
22 $(TARGET_CONFIGURE_OPTS) /
23 $(TARGET_CONFIGURE_ARGS) /
24 ./configure /
25 --target=$(GNU_TARGET_NAME) /
26 --host=$(GNU_TARGET_NAME) /
27 --build=$(GNU_HOST_NAME) /
28 --prefix=/usr /
29 --sysconfdir=/etc /
30 )
31 touch $@
32
33 $(FOO_DIR)/$(FOO_BINARY): $(FOO_DIR)/.configured
34 $(MAKE) CC=$(TARGET_CC) -C $(FOO_DIR)
35
36 $(TARGET_DIR)/$(FOO_TARGET_BINARY): $(FOO_DIR)/$(FOO_BINARY)
37 $(MAKE) prefix=$(TARGET_DIR)/usr -C $(FOO_DIR) install
38 rm -Rf $(TARGET_DIR)/usr/man
39
40 foo: uclibc ncurses $(TARGET_DIR)/$(FOO_TARGET_BINARY)
41
42 foo-source: $(DL_DIR)/$(FOO_SOURCE)
43
44 foo-clean:
45 $(MAKE) prefix=$(TARGET_DIR)/usr -C $(FOO_DIR) uninstall
46 -$(MAKE) -C $(FOO_DIR) clean
47
48 foo-dirclean:
49 rm -rf $(FOO_DIR)
50
51 #############################################################
52 #
53 # Toplevel Makefile options
54 #
55 #############################################################
56 ifeq ($(strip $(BR2_PACKAGE_FOO)),y)
57 TARGETS+=foo
58 endif
First of all, this Makefile example works for a single binary software. For other software such as libraries or more complex stuff with multiple binaries, it should be adapted. Look at the other *.mk files in the package directory.
At lines 6-11, a couple of useful variables are defined :
· FOO_VERSION : The version of foo that should be downloaded.
· FOO_SOURCE : The name of the tarball of foo on the download website of FTP site. As you can see FOO_VERSION is used.
· FOO_SITE : The HTTP or FTP site from which foo archive is downloaded. It must include the complete path to the directory where FOO_SOURCE can be found.
· FOO_DIR : The directory into which the software will be configured and compiled. Basically, it's a subdirectory of BUILD_DIR which is created upon decompression of the tarball.
· FOO_BINARY : Software binary name. As said previously, this is an example for a single binary software.
· FOO_TARGET_BINARY : The full path of the binary inside the target filesystem.
Lines 13-14 defines a target that downloads the tarball from the remote site to the download directory (DL_DIR).
Lines 16-18 defines a target and associated rules that uncompress the downloaded tarball. As you can see, this target depends on the tarball file, so that the previous target (line 13-14) is called before executing the rules of the current target. Uncompressing is followed by touching a hidden file to mark the software has having been uncompressed. This trick is used everywhere in Buildroot Makefile to split steps (download, uncompress, configure, compile, install) while still having correct dependencies.
Lines 20-31 defines a target and associated rules that configures the software. It depends on the previous target (the hidden .source file) so that we are sure the software has been uncompressed. In order to configure it, it basically runs the well-known ./configure script. As we may be doing cross-compilation, target, host and build arguments are given. The prefix is also set to /usr, not because the software will be installed in /usr on your host system, but in the target filesystem. Finally it creates a .configured file to mark the software as configured.
Lines 33-34 defines a target and a rule that compiles the software. This target will create the binary file in the compilation directory, and depends on the software being already configured (hence the reference to the .configured file). It basically runs make inside the source directory.
Lines 36-38 defines a target and associated rules that install the software inside the target filesystem. It depends on the binary file in the source directory, to make sure the software has been compiled. It uses the install target of the software Makefile by passing a prefix argument, so that the Makefile doesn't try to install the software inside host /usr but inside target /usr. After the installation, the /usr/man directory inside the target filesystem is removed to save space.
Line 40 defines the main target of the software, the one that will be eventually be used by the top level Makefile to download, compile, and then install this package. This target should first of all depends on all needed dependecies of the software (in our example, uclibc and ncurses), and also depend on the final binary. This last dependency will call all previous dependencies in the correct order.
Line 42 defines a simple target that only downloads the code source. This is not used during normal operation of Buildroot, but is needed if you intend to download all required sources at once for later offline build. Note that if you add a new package providing a foo-source target is mandatory to support users that wish to do offline-builds. Furthermore it eases checking if all package-sources are downloadable.
Lines 44-46 define a simple target to clean the software build by calling the Makefiles with the appropriate option. The -clean target should run make clean on $(BUILD_DIR)/package-version and MUST uninstall all files of the package from $(STAGING_DIR) and from $(TARGET_DIR).
Lines 48-49 define a simple target to completely remove the directory in which the software was uncompressed, configured and compiled. The -dirclean target MUST completely rm $(BUILD_DIR)/ package-version.
Lines 51-58 adds the target foo to the list of targets to be compiled by Buildroot by first checking if the configuration option for this package has been enabled using the configuration tool, and if so then "subscribes" this package to be compiled by adding it to the TARGETS global variable. The name added to the TARGETS global variable is the name of this package's target, as defined on line 40, which is used by Buildroot to download, compile, and then install this package.
Conclusion
As you can see, adding a software to buildroot is simply a matter of writing a Makefile using an already existing example and to modify it according to the compilation process of the software.
If you package software that might be useful for other persons, don't forget to send a patch to Buildroot developers !
Resources
To learn more about Buildroot you can visit these websites:
· http://www.uclibc.org/
· http://www.busybox.net/