然后,順便學(xué)習(xí)一下嵌入式軟件的開(kāi)發(fā)

先說(shuō)一下,搞這個(gè)需要很大的耐心。
我用的硬件是Sempron3100+, 512MB內(nèi)存, 編譯環(huán)境是windowsXP + vmware5.5 + gentoo,
在CUI下,花了大概20個(gè)小時(shí)才編譯完(我從晚上八點(diǎn)一直弄到第二天下午四點(diǎn)

1. 準(zhǔn)備源碼:
binuitls-2.17
gcc-4.1.1
glibc-2.5
glibc-ports-2.5
以上都可以在gnu.org的ftp上下載
默認(rèn)glibc不支持其它處理器, glibc-ports是支持其它處理器架構(gòu)的補(bǔ)丁
另外還有kernel,我使用最新的2.19.1(kernel用于提供編譯頭文件)
2. 準(zhǔn)備補(bǔ)丁:
這個(gè)可以在cross-lfs.org上面根據(jù)它的指南下載,我使用了下面的補(bǔ)丁:
Binutils Branch Update
Binutils Posix Patch
GCC Cross Search Paths Patch
GCC PR20425 Patch
GCC Posix Patch
Glibc Branch Update
Glibc Cross-Compiling Hacks Patch
Glibc Disable linking with libgcc_eh.a
Glibc Localedef Segfault
準(zhǔn)備編譯環(huán)境,我直接使用的debian(sid)并且所有包都是最新?tīng)顟B(tài),另外需要安裝texinfo, gawk(注意mawk編譯glibc header時(shí)會(huì)有問(wèn)題), bison, flex
4. 準(zhǔn)備環(huán)境變量.我寫(xiě)了一個(gè)pre.sh,所有相關(guān)內(nèi)容都放里面
set +h #關(guān)閉bash的hash功能,hash功能用來(lái)記憶系統(tǒng)中所有可執(zhí)行文件來(lái)避免查找path. 編譯時(shí)可能會(huì)增加新的同名可執(zhí)行程序在其它目錄下
umask 022
export CLFS_HOST="$(echo $MACHTYPE | sed "s/$(echo $MACHTYPE | cut -d- -f2)/cross/")"
export CLFS_TARGET="arm-unknown-linux-gnu"
export CLFS=/home/lizl/arm
export LC_ALL=POSIX # 舊的libc2.2.4以下在LOCALE為其它時(shí)chroot回來(lái)可能會(huì)有異常
export PATH=$CLFS/bin:$PATH
# CFLAGS和CXXFLAGS對(duì)編譯時(shí)可能會(huì)有影響
unset CFLAGS
unset CXXFLAGS
5. 準(zhǔn)備環(huán)境.執(zhí)行source pre.sh后執(zhí)行下面的操作:
install -dv ${CLFS} #創(chuàng)建目標(biāo)目錄
install -dv ${CLFS}/include
install -dv ${CLFS}/usr/include
另外最好使用其它用戶身份去進(jìn)行編譯的操作, 因?yàn)?/span>root可能會(huì)對(duì)系統(tǒng)造成破壞.建議創(chuàng)建一個(gè)clfs用戶和組專門(mén)操作(我是直接使用的root):
groupadd clfs #增加組
useradd -s /bin/bash -g clfs -m -k /dev/null clfs #創(chuàng)建用戶
passwd clfs #給用戶指定口令
chown -Rv clfs ${CLFS} #修改輸出目錄的權(quán)限
CLFS建議clfs帳號(hào)登錄時(shí), 最好不要被系統(tǒng)中其它環(huán)境變量影響, 所以它在clfs帳號(hào)的~/.bash_profile里面寫(xiě)入下面內(nèi)容:
exec env -i HOME=${HOME} TERM=${TERM} PS1='\u:\w\$ ' /bin/bash
因?yàn)槲沂?/span>root, 沒(méi)有修改.
su - clfs #切換到clfs用戶執(zhí)行操作
開(kāi)始創(chuàng)建一些目錄. 這里我沒(méi)有創(chuàng)建, 因?yàn)槲抑恍枰?/span>gcc, binutils和glibc這三個(gè)
6. 編譯binutils:
下載binutils-2.17并解壓.
下載補(bǔ)丁:
注意安裝gcc bison flex texinfo
不然編譯過(guò)程會(huì)出錯(cuò)
我編譯時(shí)報(bào)的錯(cuò)是 missing makeinfo
然后安裝了texinfo還是不行
后面檢查makefile才發(fā)現(xiàn)bison等都沒(méi)有安裝
patch -Np1 -i ../patch/binutils-2.17-posix-1.patch
patch -Np1 -i ../patch/binutils-2.17-branch_update-1.patch
binutils建議編譯時(shí)在其它目錄編譯,所以我們創(chuàng)建binutils-build并在里面執(zhí)行操作
mkdir -v ../binutils-build
cd ../binutils-build
如果你在binutils-2.17執(zhí)行操作的話,那后面的make configure-host時(shí)可能會(huì)報(bào)錯(cuò)
我因?yàn)閳?bào)錯(cuò)然后重做了一下干凈的解壓目錄重執(zhí)行
開(kāi)始配置
../binutils-2.17/configure --prefix=${CLFS} \
--host=${CLFS_HOST} --target=${CLFS_TARGET} --with-sysroot=${CLFS} \
--disable-nls --enable-shared --disable-multilib
檢查看主機(jī)上的運(yùn)行條件是不是符合
make configure-host
編譯并安裝:
make
make install
cp -v ../binutils-2.17/include/libiberty.h ${CLFS}/usr/include
7. 安裝內(nèi)核頭文件:
clfs中是直接復(fù)制目錄, 我則是先make menuconfig然后修改一此事配置后才復(fù)制的
clfs中操作:
install -dv ${CLFS}/usr/include
cp -av include/{asm-generic,linux,mtd,scsi,sound} ${CLFS}/usr/include
cp -av include/asm-arm ${CLFS}/usr/include/asm
我的操作:
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
在menuconfig里面load一個(gè)別人的2410的配置然后退出并保存
cp -av include/{asm-generic,linux} ${CLFS}/usr/include
cp -av include/asm-arm ${CLFS}/usr/include/asm
8. 安裝glibc的頭文件.
先把3.4的依賴去掉
cd glibc-2.5
cp configure{,.orig}
sed -e 's/3.4/3.[0-9]/g' configure.orig > configure
然后解壓glibc-ports
tar -jxvf ../glibc-ports-2.5.tar.bz2
mv -v glibc-ports-2.5 ports
注意是解壓到當(dāng)前目錄(glibc-2.5)下,不然執(zhí)行后面的configure時(shí)會(huì)報(bào)cpu不支持
然后開(kāi)始準(zhǔn)備編譯目錄, 同上, 我們也在其它目錄下進(jìn)行編譯
mkdir -v ../glibc-build
cd ../glibc-build
為打開(kāi)NPTL支持進(jìn)行如下操作:
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
echo "libc_cv_arm_tls=yes" >> config.cache
然后把安裝路徑指定一下:
echo "install_root=${CLFS}" > configparms
再執(zhí)行下面的編譯:
CC=gcc ../glibc-2.5/configure --prefix=/usr --host=${CLFS_TARGET} --build=${CLFS_HOST} --with-headers=${CLFS}/usr/include --cache-file=config.cache
make install-headers
由于awk語(yǔ)法兼容原因,如果安裝mawk的話上面的步驟會(huì)出錯(cuò), 安裝gawk則不會(huì)
有一些文件還沒(méi)有被自動(dòng)復(fù)制過(guò)去, 需要手工復(fù)制:
install -dv ${CLFS}/usr/include/bits
cp -v bits/stdio_lim.h ${CLFS}/usr/include/bits
touch ${CLFS}/usr/include/gnu/stubs.h
cp -v ../glibc-2.5/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h \
${CLFS}/usr/include/bits
9. 安裝gcc第一次,這次是為了編譯交叉版本的glibc和gcc,先打補(bǔ)丁
patch -Np1 -i ../patch/gcc-4.1.1-posix-1.patch
patch -Np1 -i ../patch/gcc-4.1.1-cross_search_paths-1.patch
然后同樣創(chuàng)建編譯目錄并在里面進(jìn)行編譯:
mkdir -v ../gcc-build
cd ../gcc-build
../gcc-4.1.1/configure --prefix=${CLFS} --host=${CLFS_HOST} --target=${CLFS_TARGET} --disable-multilib --with-sysroot=${CLFS} --disable-nls --disable-shared --enable-languages=c
make all-gcc
make install-gcc
10. 安裝glibc
在前面安裝glibc的頭時(shí)已經(jīng)做了一些事情,如把port解壓. 現(xiàn)在做的先是給glibc打補(bǔ)丁:
cd glibc-2.5
patch -Np1 -i ../patch/glibc-2.5-libgcc_eh-2.patch
patch -Np1 -i ../patch/glibc-2.5-localedef_segfault-1.patch
patch -Np1 -i ../patch/glibc-2.5-cross_hacks-2.patch
patch -Np1 -i ../patch/glibc-2.5-branch_update-1.patch
然后創(chuàng)建編譯目錄并開(kāi)始編譯:
cd ../glibc-build
rm -rf *
為支持NPTL做如下操作:
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
指明安裝目錄:
echo "install_root=${CLFS}" > configparms
開(kāi)始編譯:
BUILD_CC="gcc" CC="${CLFS_TARGET}-gcc" AR="${CLFS_TARGET}-ar" RANLIB="${CLFS_TARGET}-ranlib" ../glibc-2.5/configure --prefix=/usr --libexecdir=/usr/lib/glibc --host=${CLFS_TARGET} --build=${CLFS_HOST} --disable-profile --enable-add-ons --with-tls --enable-kernel=2.6.0 --with-__thread --with-binutils=${CLFS}/bin --with-headers=${CLFS}/usr/include --cache-file=config.cache
由于使用的是2.6.19的內(nèi)核, 內(nèi)核中使用了新的netlink接口, 把一些宏去掉了
參考maillist可知這些定義已經(jīng)不在內(nèi)核中使用, 但是應(yīng)該還在用戶空間使用
CLFS中對(duì)最新內(nèi)核的支持現(xiàn)在只到2.6.18.2
所以用2.6.19的需要自己修改一下:
修改目錄和文件為:
glibc-2.5/sysdeps/unix/sysv/linux# grep IFA * -l
check_pf.c
if_index.c
ifaddrs.c
在上面的文件中增加如下內(nèi)容:
#include <linux/if_addr.h>
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
然后執(zhí)行下面操作
make
make install
下面安裝locale, 如果想安裝全部locale的話可以執(zhí)行下面的命令(時(shí)間比較長(zhǎng), 可能有半小時(shí)):
make localedata/install-locales
而如果你不想全裝, 只想裝某些locale那clfs推薦按下面命令執(zhí)行:
mkdir -pv ${CLFS}/usr/lib/locale
export I18NPATH=${PWD}/localedata
export GCONV_PATH=${PWD}/iconvdata
export LOCALEDEF="${PWD}/locale/localedef-native --alias-file=../intl/locale.alias"
cd ../glibc-2.5/localedata
${LOCALEDEF} -i locales/de_DE -f charmaps/ISO-8859-1 --prefix=${CLFS} de_DE
${LOCALEDEF} -i locales/de_DE@euro -f charmaps/ISO-8859-15 --prefix=${CLFS} de_DE@euro
${LOCALEDEF} -i locales/en_HK -f charmaps/ISO-8859-1 --prefix=${CLFS} en_HK
${LOCALEDEF} -i locales/en_PH -f charmaps/ISO-8859-1 --prefix=${CLFS} en_PH
${LOCALEDEF} -i locales/en_US -f charmaps/ISO-8859-1 --prefix=${CLFS} en_US
${LOCALEDEF} -i locales/es_MX -f charmaps/ISO-8859-1 --prefix=${CLFS} es_MX
${LOCALEDEF} -i locales/fa_IR -f charmaps/UTF-8 --prefix=${CLFS} fa_IR
${LOCALEDEF} -i locales/fr_FR -f charmaps/ISO-8859-1 --prefix=${CLFS} fr_FR
${LOCALEDEF} -i locales/fr_FR@euro -f charmaps/ISO-8859-15 --prefix=${CLFS} fr_FR@euro
${LOCALEDEF} -i locales/it_IT -f charmaps/ISO-8859-1 --prefix=${CLFS} it_IT
${LOCALEDEF} -i locales/ja_JP -f charmaps/EUC-JP --prefix=${CLFS} ja_JP
unset I18NPATH GCONV_PATH LOCALEDEF
個(gè)人認(rèn)為如果不想全裝, 直接修改一下localedata/Makefile,把不需要的locale去掉后再執(zhí)行第一種方法可能更簡(jiǎn)單. 這里我執(zhí)行的是第一種方法.
11. 配置glibc運(yùn)行信息
如果不配置的話glibc也會(huì)有默認(rèn)配置, 但是在網(wǎng)絡(luò)環(huán)境下可能不正常. 所以需要配置一下.
用如下命令創(chuàng)建文件/etc/nsswitch.conf,當(dāng)然直接編輯更快(直接編輯時(shí)把后面的EOF去掉):
cat > ${CLFS}/etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
# End /etc/nsswitch.conf
EOF
然后用下面命令配置一下時(shí)區(qū):
TZDIR="${CLFS}/usr/share/zoneinfo" ${CLFS}/usr/bin/tzselect
回答一些問(wèn)題后, 使用下面命令保存timezone:
cp -v --remove-destination ${clfs}/usr/share/zoneinfo/[xxx] \
${clfs}/etc/localtime
[xxx]就是上面的結(jié)果.
我的結(jié)果是:
TZ='Asia/Shanghai'; export TZ
所以命令是:
cp -v --remove-destination ${clfs}/usr/share/zoneinfo/'Asia/Shanghai' ${clfs}/etc/localtime
12. 配置動(dòng)態(tài)裝載器(如果你有庫(kù)文件放在/lib和/usr/lib外的其它目錄的話)
動(dòng)態(tài)裝載器(/lib/ld-linux.so.2) 在/lib和/usr/lib目錄下查找程序需要的動(dòng)態(tài)庫(kù).
如果動(dòng)態(tài)庫(kù)所在目錄不上上面兩個(gè)目錄下, 那需要把它的目錄寫(xiě)到/etc/ld.so.conf中.
一般/usr/local/lib和/opt/lib目錄也需要查找.
如果你有動(dòng)態(tài)庫(kù)放在這兩個(gè)目錄下的話, 做如下操作(我沒(méi)有所以不做):
cat > ${CLFS}/etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib
# End /etc/ld.so.conf
EOF
13. 編譯gcc. 前面已經(jīng)編譯過(guò)一次. 前面的編譯是為了創(chuàng)建交叉版本的glibc, 現(xiàn)在則是創(chuàng)建交叉版本的gcc.
先打補(bǔ)丁
cd gcc-4.1.1
patch -Np1 -i ../patch/gcc-4.1.1-posix-1.patch
patch -Np1 -i ../patch/gcc-4.1.1-PR20425-1.patch
patch -Np1 -i ../patch/gcc-4.1.1-cross_search_paths-1.patch
第一個(gè)和每三個(gè)前面都已經(jīng)打過(guò)了, 所以這里只需要再打第二個(gè)就可以了
然后創(chuàng)建編譯目錄:
mkdir -v ../gcc-build
cd ../gcc-build
../gcc-4.1.1/configure --prefix=${CLFS} \
--host=${CLFS_HOST} --target=${CLFS_TARGET} --disable-multilib \
--with-sysroot=${CLFS} --disable-nls --enable-shared \
--enable-languages=c,c++ --enable-__cxa_atexit \
--enable-c99 --enable-long-long --enable-threads=posix
make
make install
14. 交叉編譯工具鏈已經(jīng)做好,現(xiàn)在就小試一下牛刀,馬上來(lái)個(gè)Hello World
