本文轉載自:http://blog.csdn.net/flfihpv259/article/details/51996204
1 buildroot簡介
1.1 Buildroot at a glance
根據我的使用經歷就是它可以讓你從toolchain,boot,kernel到文件系統及各類應用(如qt,gstream,busybox)一站式make,省去了你編譯工具和內核版本的不匹配,glibc庫不對啦,每次編譯都要去改arch cross_compile等N多煩惱.你也不用在去瞎找各種tarball下載了,它都給你提供了官方的下載途徑.總之就是省心省力.具體可看官網說明.
1.2下載
1.3目錄說明
anzyelay@ubuntu:buildroot-2016.05$ ls arch build dl linux output support board CHANGES configs docs Makefile package system boot Config.in COPYING fs README toolchain
- 1
- 2
- 3
- 1
- 2
- 3
- Makefile,Config.in,arch等就不說了
-
toolchain/ , boot/ , fs/ , Linux/
這幾個目錄里都是Config.in 和相關的xxx.mk文件. Config.in就是配置文件, xxx.mk呢就是指定相應的源碼包位置和下載地址之類的. -
output/
make后的所有文件都安裝在此處,如下:anzyelay@ubuntu:buildroot-2016.05$ ls output/ build host images staging target
- 1
- 2
- 1
- 2
- build:所有源碼包解壓出來的文件存放地和編譯的發生地
-
host:是由各類源碼編譯后在你主機上運行的工具(build for host)的安裝目錄,如arm-linux-gcc就是安裝在這里.
1 編譯出來的主機工具在host/usr下,
2 根目錄所需要的庫及一些基本目錄就在host/< tuple >/sysroot/或host/usr/< tuple >/sysroot/里 (< tuple >:arm-buildroot-linux-gnueabi),如果是外部toolchain,比如lirano的就在libc里,名字不一樣而矣, -
staging:軟鏈接到host/< tuple >/sysroot/ 就是上面說到的文件系統需要的庫等目錄,方便查看
-
images:生成的文件系統,內核在此處,
-
target:根文件系統的存放地,但這不能用來nfs mount到開發板,因為buildroot不是root權權運行的,所以現dev/,etc/等一些文件無法創建,所以目錄還不完整,要用images/里的rootfs.tar解壓出來的根文件目錄才能mount.使用如下命令
sudo tar -C /destination/of/extraction -xf images/rootfs.tar
- 1
- 1
-
dl/
所有默認的下載包都在這里,當這里缺少需要的包時就會自動下載,當然本身下載通常都是很慢的,你可以手動找到相關包下載后放到這里就OK了,make時會自動檢測這個目錄. -
system/
這里就是根目錄的主要骨架了和相關的啟動初始化配置,當制作根目錄時就是將此處的文件cp到output里去.然后再安裝toolchain的動態庫和你勾選的package的可執行文件之類的. -
package/
▶ all the user space packages (1800+)
▶ busybox/, gcc/, qt5/, etc.
▶ pkg-generic.mk, core package infrastructure
▶ pkg-cmake.mk, pkg-autotools.mk, pkg-perl.mk, etc.
Specialized package infrastructures -
configs/
默認的不同平台的配置文件 -
board/
存放了一些默認開發板的配置補丁之類的 -
support/
▶ misc utilities (kconfig code, libtool patches, download helpers,
and more.) -
docs/
幫助文檔,解壓出來是空的,可看在線文檔
2 使用
buildroot的編譯流程是先從dl/xxx.tar下解壓出源碼到output/build/xxx,然后它利用本身的配置文件(如果有的話)覆蓋output/build/xxx下的配置文件,在開始編譯連接完成后安裝到output/相應文件夾下.
2.1 平台配置
- Target options
首先你要選配好你的開發目標平台的一些基本項
2.2 Toolchains in Buildroot
Buildroot提供兩種方式使用toolchain,一種是非Buildroot提供的交叉編譯器(external toolthain),另一種就是Buildroot本身編譯生成的Buildroot toolchain.這個可以在make menuconfig里的 Toolchain menu–>Toolchain Type中選擇.
2.2.1. external toolthain:
-
Toolchain :
( ) Sourcery CodeBench ARM 2014.05 ( ) Musl 1.1.12 toolchain (X) Custom toolchain(用戶自己定義的交叉工具)
- 1
- 2
- 3
- 1
- 2
- 3
前面兩種是buildroot已知的toolchain,最后一個是用戶自己指定的
-
Toolchain origin(工具來源):
() Toolchain to be downloaded and installed (X) Pre-installed toolchain(以安裝的)
- 1
- 2
- 1
- 2
- 1項:需要下載安裝,選中此后,需要你在下一項中填好交叉工具的下載地址–Toolchain URL)
- 2項:配置好本地的Toolchain path,和Toolchain prefix,以及后面三項gcc version,kernel header series,C library,不知道就默認,按錯誤提示的修改就行.
使用它的好處就是不用浪費時間再去編譯個toolchain了,但缺點就是如果你的toolchain有問題那就相當麻煩.就好比我從Linaro官網下載下來的toolchain,編譯內核沒問題,但做文件系統時老是kernel panic,開始我還懷疑我內核有問題,又是用busybox,又是buildroot,內核,文件系統搞了好久,才發現是toolchain的問題.
2.2.2. Buildroot toolchain:
- custom toolchain vendor name:就是設置arm-xxx-linux-gnueabi-中的xxx
-
Kernel Headers:最好跟你要編譯的內核一致,如果提供選項上沒有就選Manually specified,然后在linux version項填版本號,
看官網說明,這些頭文件是libc庫編譯文件時用來連接內核的,C庫用該頭文件來構建用戶空間與內核的通信接口,重點是這個庫接口是向后兼容,也就是說你不知道選哪個就選舊版的吧.選太新的是不能識別舊版的內核通信,但選舊版頭文件仍可以和新版內核通信,詳細說明如下:Change the version of the Linux kernel headers used to build the toolchain. This item deserves a few explanations. In the process of building a cross-compilation toolchain, the C library is being built. This library provides the interface between userspace applications and the Linux kernel. In order to know how to “talk” to the Linux kernel, the C library needs to have access to the Linux kernel headers (i.e. the .h files from the kernel), which define the interface between userspace and the kernel (system calls, data structures, etc.). Since this interface is backward compatible, the version of the Linux kernel headers used to build your toolchain do not need to match exactly the version of the Linux kernel you intend to run on your embedded system. They only need to have a version equal or older to the version of the Linux kernel you intend to run. If you use kernel headers that are more recent than the Linux kernel you run on your embedded system, then the C library might be using interfaces that are not provided by your Linux kernel.
-
Custom kernel headers series:與上面相同
-
C library
( ) uClibc:專為嵌入式簡化的C庫,小巧精簡,但不兼容glibc,是獨立的實現的.
( ) glibc:GNU C Library 支持很多種系統平台,功能很全,但是也相對比較臃腫和龐大的C庫
( ) musl (experimental)這樣填好后它會自動去下載相應version的內核源碼,如果下載不了,可以自己下載后放到DL目錄下就好.
選擇這個的好處就是配置簡單,后續build 它里面的文件系統,第三方應用很輕松,不存在兼容性問題.缺點就是費時間,因為你make clean后所有output里的文件都沒了,下次編譯時又要重新再編譯一次toolchain.因此,你可以第一次用它編譯出來然后保存到別的地方,再選擇external toolchain來就可以了.
2.3 Root filesystem in Buildroot
-
編譯流程圖
-
System configuration
- /dev management
此處提供四種選擇
1.Static using device table(不能動態生成dev/節點,文件系統有什么就是什么)
2.Dynamic using devtmpfs only(在啟動時能動態生成,后面就不行了)
3.Dynamic using devtmpfs + mdev(嵌入式選擇這個,當有新設備時能動態生成或刪除節點文件,/etc/mdev.conf它的配置文件)
4.Dynamic using devtmpfs + eudev(比mdev要大要耗費資源,但..肯定要好些了)
要想能Dynamic using還要內核配置上CONFIG_DEVTMPFS 和 CONFIG_DEVTMPFS_MOUNT.如果是使用buildroot編譯內核,它會根所你的選擇自動檢測這兩項. - Root FS skeleton:默認就好,或者你自己有現在的文件系統框架
- Root filesystem overlay directories(如果你要使用自己或廠商提供的文件系統,可以在此填上,它會在制作鏡像時復蓋本身編譯的文件系統)
- /dev management
-
Filesystem images(選擇你要生成的鏡像類型)
- [*] tar the root filesystem
要做目錄版的文件系統,就是用來nfs mount的,就選中此,然后解壓出來就是了,其它默認就好,完了就make吧,OK之后在output/image下就是你要的文件系統了,
- [*] tar the root filesystem
-
make busybox-menuconfig(可以用於配置busybox,而不使用默認的選項)
2.4 Managing the Linux kernel configuration
-
在選中編譯內核后,指定內核配置文件有兩種方式:
(X) Using an in-tree defconfig file ( ) Using a custom (def)config file
- 1
- 2
- 1
- 2
- 第一項是使用內核 arch/< ARCH >/configs里自帶的deconfig配置,好處就是無需修改就可使用,選中此項后會出現
Defconfig name
選項叫你填寫配置名,只需要填寫name,不用全路徑,而且也不要帶后面的_defconfig; - 第二項是使用自己配置的一個完整的.config或者minimal defconfig,選中此項后,需要指定配置路徑
Configuration file path
是全路徑,不是絕對路徑;
- Additional fragments
如果上述配置還不夠需要添加也額外的配置可以用這個 - 如何修改配置:
- 使用命令
make linux-menuconfig
這樣就會彈出你上面選中的配置項的配置界面 - 你所作的修改會保存在$(O)/build/linux-< version>/,它們在clean后不會保留下來
- 當你指定配置時用的是custom的方式,那可以通過
make linux-update-config
命令來保存.config,用make linux-update-defconfig來保存minimal defconfig.如果是指定使用內核的配置則不能用此來保存.
- 使用命令
2.5 編譯
make <要編譯的包>-<要做什么>
要編譯的包:toolchain,busybox,linux,uboot等
要做什么:menuconfig,dirclean,reconfigure,rebuild等
使用make help查看更多
2.5.1 如何編譯一個單獨的包
make package-build
2.5.2 如何刪除一個單獨的包
不支持Removing a package,是因為buildroot沒有記錄在output中安裝的相應信息,和依賴的包.但只要刪了output/build下的相應目錄,再make時它就會重新解壓配置編譯了,所以可以使用如下命令來刪除相應目錄.
make < package>-dirclean
eg:make linux-custom-dirclean
2.5.3 如何重新編譯
make < package>-reconfigure:更改配置好重新編譯使用
make < package>-rebuild:更改代碼文件后重新編譯使用
2.5.4 如何查詢要使用的包
make external-deps:列出所有要用的源碼包.當你不知道要下載哪個包時可以查詢等.
3 問題記錄
3.1 將buildroot編譯出的toolchain移動到本地使用出現arm-linux-gcc.br_real: No such file or directory
anzyelay@ubuntu:/$ cd /usr/local/arm/ anzyelay@ubuntu:arm$ 4.9.3/bin/arm-linux-gcc -v /usr/local/arm/usr/bin/arm-linux-gcc.br_real: No such file or directory
- 1
- 2
- 3
- 1
- 2
- 3
但 arm-linux-gcc.br_real這個文件是有的,看了下,gcc的鏈接是鏈接到一個toolchain-wrapper,估計是這個文件處理之后又找到的arm-linux-gcc.br_real,后來仔細一看提示發現目錄也不對呀,我只好在4.9.3下加個usr目錄,把其它文件都移動到里面,就是保持buildroot里的原樣目錄,這樣就可以了
anzyelay@ubuntu:usr$ bin/arm-linux-gcc -v Using built-in specs. COLLECT_GCC=/usr/local/arm/4.9.3/usr/bin/arm-linux-gcc.br_real COLLECT_LTO_WRAPPER=/usr/local/arm/4.9.3/usr/bin/../libexec/gcc/arm-buildroot-linux-gnueabi/4.9.3/lto-wrapper Target: arm-buildroot-linux-gnueabi
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
3.2 使用buildroot編譯出的toolchain工具能成功編譯出的內核及文件系統,但將內核下載無法到開發板無法正常啟動
一啟動就停在”Uncompressing Linux…done,booting the kernel”,用外部的編譯器編譯的同一份源碼的內核是能正常啟動的,所以應該就是內核完全無法執行,並不是以前碰到的無法輸出打印信息到console里,但奇怪的是編譯出的文件系統居然能正常使用…..對比外部工具鏈和buildroot的工具鏈的編譯配置信息發現一個疑點:–with-mode=thumb與–with-mode=arm,更改為thumb后,問題依然.在附加選項添加上一些選項后也是一樣,有幾個一添加就會出錯, 還是打算用網上下載的lirano版gcc試試.記得以前這個是可以成功編譯運行但編譯出的文件系統會kernel panic.這回將平台指令換成thumb再編譯次試試.
- 測試結果是:
- 測試的內核版本3.6.6,(4.2.16也試過,這里主要以3.6.6說明),linaro的是下載的可執行版,沒有自己編譯,所以其它項沒有變化.
cross-compile | gcc版本 | kernel header | libc | 指令集 | fs | kernel | hello.c編譯執行情況 |
---|---|---|---|---|---|---|---|
arm-buildroot-gcc | 4.9.3 | 3.6.6 | eglibc | arm | Y | N | N |
arm-buildroot-gcc | 4.9.3 | 3.2.x | eglibc | arm | Y | N | Y |
arm-buildroot-gcc | 4.9.3 | 3.6.6 | uClibc | arm | Y | N | N |
arm-buildroot-gcc | 4.9.3 | 3.2.x | uClibc | arm | Y | N | Y |
arm-buildroot-gcc | 4.9.3 | 3.6.6 | eglibc | thumb | Y | N | N |
arm-buildroot-gcc | 4.9.3 | 3.2.x | eglibc | thumb | Y | N | Y |
arm-linaro-gcc | 4.9.4 | 4.0.0 | eglibc | thumb | N | Y | N |
由上知buildroot自制的arm-buildroot-gcc(無論是arm/thumb,uclibc/glibc,不同的kernel header等)編譯的內核都無法啟動,但可以編譯出可執行的文件系統,同時用它編譯出的可執行文件也可以執行(用3.6.6頭文件會出現缺少庫函數無法編譯的現象),如果是arm-linaro-gcc編譯出的內核可以啟動,但編譯出的文件系統出現Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b,用其編譯的程序會出現segment fault錯誤.其它的就沒試了.
3.3 修改為無賬號密碼登錄
用buildroot編譯的文件系統默認是需要輸入賬號的,如何開機自動登錄shell呢?
如果你刪除賬戶的話那就無法 登錄了,buildroot默認使用的是getty登錄的,這個程序好像非要有賬戶號才能運行。即使我在inittab中給它加了-a user參數也不行,buildroot編譯出來的不支持這個參數。那直接改為-bin/sh就行了,如下:
etc/inittab修改部分的內容:
26 # Put a getty on the serial port 27 #ttySAC0::respawn:/sbin/getty -L ttySAC0 115200 vt100 # GENERIC_SERIAL 28 ::respawn:-/bin/sh 29 # Stuff to do for the 3-finger salute 30 #::ctrlaltdel:/sbin/reboot