Создание Linux для ARM9

Материал из Belgorod Linux User Group - Белгород

Перейти к: навигация, поиск

Содержание

SAM

Описание будет базироваться на утилитах, собранный на сайте:

http://www.linux4sam.org/

Дано

Устройство с ARM-процессором. В этом разделе будет рассмотрен ATMEL AT91 Smart ARM-based Microcontroller (так же известный как SAM). К примеру AT91SAM9.

Требуется

Разработать дистрибутив Linux, с необходимым набором ПО.

Компилятор

Берем тут : http://www.codesourcery.com/public/gnu_toolchain/arm-none-linux-gnueabi/arm-2007q1-10-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

Распаковываем куда-нибудь. К примеру будем использовать домашнюю директорию.

cd ~/
tar -xjf arm-2007q1-10-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

В переменной пути прописываем путь до бинарников:

export PATH=/home/user/arm-2007q1/bin:$PATH

Обертки

* ВНИМАНИЕ! Для дальнейшей компиляции мы будем использовать скрипты-обертки ~/bin/configure.sh 

На самом деле их можно заменить алиасами, или как вам будет удобнее. Их смысл в том, чтобы запускать configure с определенными параметрами, просто не набирая их каждый раз.

Для использования этих скриптов, и вообще для облегчения работы нам потребуется экспортировать некоторые переменные окружения связанные с кросс-компиляцией. К примеру записать их в отдельный файл: ~/cross.env

BASE=/home/user
export PATH=$BASE/arm-2007q1/bin:$PATH
export PREFIX=$BASE/root

export ARCH=arm
export TARGET=arm-none-linux-gnueabi

export CROSS_COMPILE=$TARGET-
export CC="$TARGET-gcc"
export LD_LIBRARY_PATH="$BASE/root/lib"
export INSTALL_PATH="$BASE/root"
export INSTALL_MOD_DIR="$BASE/root"
export INCLUDES="-I $PREFIX/include"

export CFLAGS="-O2 -march=armv5te -mtune=arm926ej-s -s"
export CXXFLAGS="${CFLAGS}"


Далее в вашем ~/.bash_rc или ~/.zshrc необходимо подргузить этот файл, добавив строку:

source /home/user/cross.env

После запуска убедитесь в том, что переменные применились:

env

configure

mkdir ~/bin

наш ~/bin/configure.sh выглядит примерно так:

#!/bin/bash
echo $@
./configure --prefix=$PREFIX --target=$TARGET --host=$TARGET $@
chmod +x ~/bin/configure.sh

Напомню, что все переменные $PREFIX, $TARGET - выставлены выше, в cross.env

  • Во время конфигурирования обратите внимание, чтобы строки соответствовали кросс-компиляции, т.е. были вида:
checking build system type... i686-pc-linux-gnu
checking host system type... arm-none-linux-gnueabi
checking target system type... arm-none-linux-gnueabi

Ядро

Патчим

Скачиваем патчи на ваш процессор. Я брал от сюда:

http://www.linux4sam.org/twiki/bin/view/Linux4SAM/LinuxKernel

Распаковываем ядро и накладываем патчи:

mkdir ~/linux
cd ~/linux
cp /usr/portage/distfiles/linux-2.6.xx.tar.bz2 ./
tar -xjf linux-2.6.xx.tar.bz2
zcat linux-2.6.xx-at91-exp.diff.gz | patch -p1

Берем дефолтный конфиг, я брал по той же ссылке выше и называем его .config

cp at91sam9261ek_defconfig .config
make ARCH=arm oldconfig 
make ARCH=arm menuconfig

Собираем

make

uImage

Теперь необходимо сделать ядро читаемым для загрузчика. Для этого нужна утилита mkimage:

cd ~/bin/
wget http://www.linux4sam.org/twiki/pub/Linux4SAM/SoftwareTools/mkimage.bin
chmod +x mkimage.bin

Далее делаем скрипт-обертку:

vim ~/bin/mkimage.sh
#!/bin/bash
~/bin/mkimage -A arm -O linux -C none -T kernel -a 20008000 -e 20008000 -n linux-2.6 -d arch/arm/boot/Image uImage

Запустить его можно будет просто:

~/bin/mkimage.sh

и мы получим наше ядро в виде файла uImage. Создадим директорию, где будет лежать все готовое, и положим туда ядро.

mkdir ~/my
cp ./uImage ~/my

rootfs

Ядро готово, приступим к созданию файловой системы.

mkdir ~/root

BusyBox

Скачиваем, распаковываем, собираем:

mkdir ~/busybox
cp /usr/portage/busybox-x.xx.x.tar.bz2
tar -xjf busybox-x.xx.x.tar.bz2
cd busybox-x.xx.x
make ARCH=arm menuconfig
make
make install

Все. Файлы готовы, и лежат в ./_install (по умолчанию). Их можно перенести в наш ~/root.

JFFS2

Файловая система Journalling Flash File System v2 В вашей хост-системе должна быть поддержка JFFS2. В ядре это опции:

   * "Device Drivers"
         o "Block Devices"
               + "Loopback Device Support" (loop)
         o "Memory Technology Device (MTD) support"
               + "Caching block device access to MTD devices" (mtdblock module) (required for block2mtd)
               + "Self-contained MTD device drivers..."
                     # "MTD emulation using block device" (block2mtd),
   * "File Systems"
         o "Miscellaneous Filesystems"
               + "Journalling Flash File System v2 (JFFS2) support"
                     # "Advanced compression options for JFFS2"
                           * "JFFS2 ZLIB compression support"

Программа для создания файловой системы тут:

ftp://sources.redhat.com/pub/jffs2/mkfs.jffs2

Скачиваем и так же кладем в ~/bin/

Полее подробно можно почитать тут:

http://www.gentoo-wiki.info/JFFS2/Mounting

Скрипт для создания файловой системы:  vim ~/bin/mkfs.sh

#!/bin/bash
~/bin/mkfs.jffs2 -e 128 –d=265289728 -n --root=$PREFIX -o rootfs.jffs2


(у вас может отличаться)


Монтируем

Скрипт монтирования:

vim ~/bin/mount-jffs2.sh                                                                                            
#!/bin/bash
if [ $# -lt 2 ]; then
 echo "USE: $0 <file.jffs2> <mount_point>"
 exit 1
fi
echo "Mounting $1 to $2..."
if [ $(whoami) != "root" ]; then
 echo "Need su"
 exit 1
fi
mknod /dev/mtdblock0 b 31 0 2>/dev/null
/sbin/losetup /dev/loop0 $1
echo "/dev/loop0" > /sys/module/block2mtd/parameters/block2mtd
mount -t jffs2 /dev/mtdblock0 $2

Скрипт размонтирования:

vim ~/bin/umount-jffs2.sh                                                                                            
#!/bin/bash
if [ $# -lt 1 ]; then
 echo "USE: $0 <mount_point>"
 exit 1
fi
echo "umounting $1..."
if [ $(whoami) != "root" ]; then
 echo "Need su"
 exit 1
fi
umount $1
echo "" > /sys/module/block2mtd/parameters/block2mtd
rm /dev/mtdblock0
/sbin/losetup -d /dev/loop0 2>/dev/null

Использование:

~/bin/mount-jffs2.sh rootfs.jffs2 /mnt/tmp
~/bin/umount-jffs2.sh /mnt/tmp

Подготавливаем

Подготовка корневой файловой системы. Вот примерный скрипт для минимального ее создания:

pwd=/home/user/root
cd $pwd
mkdir dev etc etc/init.d bin proc mnt tmp var var/shm
chmod 755 . dev etc etc/init.d bin proc mnt tmp var var/shm
######
# DEV
cd $pwd/dev
# Create the generic terminal devices:
mknod tty c 5 0
mknod console c 5 1
chmod 666 tty console
# Create the virtual terminal device
mknod tty0 c 4 0
chmod 666 tty0
# Create the RAM disk device:
mknod ram0 b 1 0
chmod 600 ram0
# Create the null device, used to discard unwanted output:
mknod null c 1 3
chmod 666 null
######
# etc
cd $pwd/etc
# rcS
echo "mount -a" >> init.d/rcS
chmod 744 init.d/rcS
# fstab
echo "proc  /proc      proc    defaults     0      0" >> fstab
echo "none  /var/shm   shm     defaults     0      0" >> fstab

Заворачиваем

cd ~/my
~/bin/mkfs.sh

в результате у нас в директории my уже 2 файла - ядро и образ файловой системы:

uImage
rootfs.sh

Заливаем

Заливаем на устройство. Для этого будем использовать программа SAM-BA. Взять ее можно тут:

ftp://ftp.linux4sam.org/devel/tools/sam-ba_cdc_2.8.linux_01.zip

Распаковали в ~/

Скрипт заливки

Скрипты для SAM-BA пишутся на tcl. Вот пример скрипта, который заливает ядро в DataFlash, а rootfs в NAND:

my.tcl
proc set_uboot_env {nameOfLstOfVar} {
   upvar $nameOfLstOfVar lstOfVar
   # sector size is the size defined in u-boot CFG_ENV_SIZE
   set sectorSize [expr 0x4000 - 4]
   set strEnv [join $lstOfVar "\0"]
   while {[string length $strEnv] < $sectorSize} {
       append strEnv "\0"
   }
   set strCrc [binary format i [::vfs::crc $strEnv]]
   return "$strCrc$strEnv"
}

set bootstrapFile       "dataflash_at91sam9261ek.bin"
set ubootFile           "u-boot-1.1.5_atmel_1.7-at91sam9261ek-dataflash.bin"
set kernelFile          "uImage.bin"
set rootfsFile          "rootfs.jffs2"
set ubootEnvFile        "ubootEnvtFileDataFlash.bin"
## DataFlash Mapping
set baseAddr            0xC0000000
set bootStrapAddr       0x00000000
set ubootAddr           0x00008000
set ubootEnvAddr        0x00004000
set kernelAddr          0x00040000
# u-boot variable
set kernelUbootAddr [format "0x%08X" [expr $baseAddr + $kernelAddr]]
set kernelLoadAddr      0x22200000
## NandFlash Mapping
set rootfsAddr  0x00400000
set kernelSize  [format "0x%08X" [file size $kernelFile]]
lappend u_boot_variables \
   "ethaddr=3a:1f:34:08:54:54" \
   "bootdelay=3" \
   "baudrate=115200" \
   "stdin=serial" \
   "stdout=serial" \
   "stderr=serial" \
   "bootargs=mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2" \
   "bootcmd=cp.b $kernelUbootAddr $kernelLoadAddr $kernelSize; bootm $kernelLoadAddr"

#puts "-I- === Initialize the DataFlash access ==="
#DATAFLASH::SelectDataflash AT91C_SPI0_CS0

#puts "-I- === Erase all the DataFlash blocs and test the erasing ==="
#DATAFLASH::EraseAllDataFlash

#puts "-I- === Load the bootstrap: dataflash_at91sam9263ek in the first sector ==="
#DATAFLASH::SendBootFile $bootstrapFile

#puts "-I- === Load the u-boot in the next sectors ==="
#send_file {DataFlash AT45DB/DCB} "$ubootFile" $ubootAddr 0

#puts "-I- === Load the u-boot environment variables ==="
#set fh [open "$ubootEnvFile" w]
#fconfigure $fh -translation binary
#puts -nonewline $fh [set_uboot_env u_boot_variables]
#close $fh
#send_file {DataFlash AT45DB/DCB} "$ubootEnvFile" $ubootEnvAddr 0

#puts "-I- === Load the Kernel image ==="
#send_file {DataFlash AT45DB/DCB} "$kernelFile" $kernelAddr 0

puts "-I- === Initialize the NAND access ==="
NANDFLASH::Init

puts "-I- === Erase all the NAND flash blocs and test the erasing ==="
NANDFLASH::EraseAllNandFlash

puts "-I- === Load the linux file system ==="
send_file {NandFlash} "$rootfsFile" $rootfsAddr 0

В файле видны адреса. Для уточнения - обращайтесь к инструкции по МК либо примеры скпритов можно посомотреть тут, к примеру для дистрибутива Angstrom:

http://www.linux4sam.org/twiki/bin/view/Linux4SAM/GettingStarted
http://www.angstrom-distribution.org

USB

Скрипт инициализации устройства:

vim ~/bin/samba-usb.sh                                                                                           
#!/bin/bash
if [ $(whoami) != "root" ]; then
 echo "Need su"
 exit 1
fi
rmmod usbserial
modprobe usbserial vendor=0x03eb product=0x6124
lsusb -d 03eb:6124
dmesg | tail

(см. внимание на джамперы, чтобы инициализировалась загрузка, устройство будет видно, если не пойдет загрузка). В результате устройство будет видно как ttyUSBx

Загружаем

cd ~/my
~/sam-ba_cdc_2.8.linux_01/sam-ba_cdc_2.8.linux_01 /dev/ttyUSB0 AT91SAM9261-EK ./my.tcl

Тут я вызвал бинарный файл sam-ba, с параметрами <tty> <имя контроллера> <скрипт загрузка>

Так же у sam-ba есть GUI, можно и в нем потыкать, но скриптом удобнее.


Buildroot

TODO: дописать

Полезная вещь - BuildRoot - это набор скриптов и Makefile-ов, для сборки приложений под встраеваемые системы. Т.е. теоретически для построения всей системы достаточно только этого пакета. Его надо скачать, распаковать, и использовать. Конфигурирование идет по принципу Kconfig (как у ядра).


Загрузчик

TODO: дописать

Будем использовать uBoot....... Я брал готовый тут:

http://www.linux4sam.org/twiki/bin/view/Linux4SAM/GettingStarted#Software

LFS

Существует специальный проект CLFS - это cross complinig LFS . Тут рассказано как собирать свой Linux с нуля, под ARM:

 http://cross-lfs.org/view/clfs-sysroot/arm/

По этой документации мы и будем делать, описывая все шаги в скрипты. Скрипты я буду складывать в директорию ~/bin/clfs, сборку производить в ~/src, файлы хранить в ~/clfs, а целевая система будет в ~/root, по этому создадим эти директории:

mkdir -p ~/bin/clfs
mkdir ~/src
mkdir ~/clfs
mkdir ~/root


$CLFS

Необходимо выставить некоторые переменные окружения, которые будут использоваться на протяжении всей сборки. Во-первых это переменная ${CLFS}, указывающая на директорию, где будет все собираться. Все остальные пути будут обозначаться относительно этой директории. Необходимо создать эту директорию, и выставить переменную.

Я буду использовать файл ~/cross.env для выставления в нем всех переменных:


BASE=/home/clfs
export CLFS=$BASE/root
export PATH=${CLFS}/cross-tools/bin:$PATH
export CLFS_HOST=i686-pc-linux-gnu
export CLFS_TARGET=armv5te-none-linux-gnueabi
export CFLAGS="-O2 -march=armv5te -mtune=arm926ej-s -s"
export CXXFLAGS="${CFLAGS}"


  • Внимание! Обратите внимание на флаги! Возможно у вас они будут другими! Особенно CFLAGS (зависит от целевого CPU).

Все действия по сборке желательно производить от непривилигированного пользователя. Лучше создать отдельного. В его ~/.bash_rc (или ~/.zshrc) добавьте строку подгрузки файла переменных, созданного выше:

source /home/usr/cross.env

patch

0-download.sh

Выкачаем все патчи, предлагаемые CLFS:

#!/bin/bash
cd ~/clfs
curl "http://cross-lfs.org/view/clfs-sysroot/arm/materials/patches.html" | grep '"http://svn' | sed 's/>//gi' | xargs wget

Этот скрипт выкачает все патчи.

* Внимание! Если патчи требуют последовательности в наложении (важна очередность) - то их необходимо соответствующим образом переименовать. 

К примеру:

glibc-2.9-001-cross_hacks.patch
glibc-2.9-002-libgcc_eh-1.patch

Но как правило этого не понадобится.

Так же мне понадобился этот патч:

http://sourceware.org/bugzilla/attachment.cgi?id=3058&action=view

сохранил его как ~/clfs/binutils-2.19-tc-arm.patch

rootfs

1-rootfs.sh

Формируем корневую файловую систему

#!/bin/bash
mkdir -pv ${CLFS}/{bin,boot,dev,{etc/,}opt,home,lib,mnt}
mkdir -pv ${CLFS}/{proc,media/{floppy,cdrom},sbin,srv,sys}
mkdir -pv ${CLFS}/var/{lock,log,mail,run,spool}
mkdir -pv ${CLFS}/var/{opt,cache,lib/{misc,locate},local}
install -dv -m 0750 ${CLFS}/root
install -dv -m 1777 ${CLFS}{/var,}/tmp
mkdir -pv ${CLFS}/usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv ${CLFS}/usr/{,local/}share/{doc,info,locale,man}
mkdir -pv ${CLFS}/usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv ${CLFS}/usr/{,local/}share/man/man{1,2,3,4,5,6,7,8}
for dir in ${CLFS}/usr{,/local}; do
 ln -sfnv share/{man,doc,info} ${dir}
done
ln -s usr/include ${CLFS}/include
ln -s usr/share ${CLFS}/share
ln -s /bin/bash ${CLFS}/bin/sh
ln -s /usr/bin/bash ${CLFS}/bin/bash

password

2-password.sh

Создаем файлы групп и паролей.

#/bin/bash
cat > ${CLFS}/etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
EOF
cat > ${CLFS}/etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:4:
tape:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
wheel:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
uucp:x:32:
EOF
touch ${CLFS}/var/run/utmp ${CLFS}/var/log/{btmp,lastlog,wtmp}
chmod -v 664 ${CLFS}/var/run/utmp ${CLFS}/var/log/lastlog
chmod -v 600 ${CLFS}/var/log/btmp

header

3-header.sh

Необходимы файлы заголовок ядра (про ядро см. в соответствующем разделе этой статьи):

#!/bin/bash
cd ~/linux/linux
make ARCH=arm headers_check
make ARCH=arm INSTALL_HDR_PATH=dest headers_install
cp -rv dest/include/* ${CLFS}/usr/include


dev

6-dev.sh Создает директорию /dev с минимальным и устройствами

#!/bin/bash

if [ $(whoami) != "root" ]; then
 echo "Need su"
 exit 1
fi

PREFIX=/home/clfs/tmpfs
mkdir -p $PREFIX/dev
cd $PREFIX

mknod -m 600 dev/console c 5 1
mknod -m 666 dev/null c 1 3

mknod -m 666 dev/tty c 5 0
mknod -m 666 dev/tty0 c 4 0
mknod -m 666 dev/tty1 c 4 1
mknod -m 666 dev/tty2 c 4 2
mknod -m 666 dev/tty3 c 4 3
mknod -m 666 dev/tty4 c 4 4

# Create the RAM disk device:
mknod -m 600 dev/ram0 b 1 0


ln -s /proc/self/fd dev/fd
ln -s /proc/self/fd/0 dev/stdin
ln -s /proc/self/fd/1 dev/stdout
ln -s /proc/self/fd/2 dev/stderr
ln -s /proc/kcore dev/core
mkdir dev/pts
mkdir dev/shm

cross-tools

4-cross-tools.sh

Набор инструментов для кросс-компиляции (в состав которых входит binutils, gcc, glibc и пр.) называют cross-tools. Этими инструментами мы будем собирать файлы для целевой системы.

Собираться эти инструменты будут в отдельную директорию (cross-tools), по этому prefix у них будет ${CLFS}/cross-tools. А сама система уже позже будет собираться с prefix=/usr, но инсталлироваться в sysroot. Этим самым мы разделяем так называемый buildroot и sysroot.

Сборка пакетов идет в последовательности по зависимостям. Описано в CLFS.

packages

Тут описаны имена пакетов. Позаботьтесь о том, чтобы они были свежими, и соответствовали сегодняшней версии CLFS. Так же необходимо подготовить все эти нужные файлы. У меня онинаходятся в директории DISTFILES. В процессе работы скрипта они будут складываться в SRC и там распаковываться и собираться (процедура m_default).

~/bin/clfs/packages.inc:

GMP=gmp-4.2.4.tar.bz2
MPFR=mpfr-2.4.1.tar.lzma
BINUTILS=binutils-2.19.1.tar.bz2
GCC=gcc-4.3.3.tar.bz2
GLIBC_PORTS=glibc-ports-2.9.tar.bz2 
GLIBC=glibc-2.9.tar.bz2
FILE=file-5.00.tar.gz
GROFF=groff-1.20.1.tar.gz
SHADOW=shadow-4.1.2.2.tar.bz2
NCURSES=ncurses-5.7.tar.gz
ZLIB=zlib-1.2.3.tar.bz2
SED=sed-4.1.5.tar.gz
E2FSPROGS=e2fsprogs-1.41.4.tar.gz
E2FSPROGS_LIBS=e2fsprogs-libs-1.41.4.tar.gz
COREUTILS=coreutils-7.1.tar.gz
IANA=iana-etc-2.30.tar.bz2
M4=m4-1.4.9.tar.bz2
BISON=bison-2.4.1.tar.bz2
PROCPS=procps-3.2.7.tar.gz
LIBTOOL=libtool-2.2.6a.tar.lzma
FLEX=flex-2.5.35.tar.bz2
UTIL=util-linux-ng-2.14.2.tar.bz2 
IPUTILS=iputils-s20071127.tar.bz2
IPROUTE2=iproute2-2.6.28.tar.bz2
NET=net-tools-1.60_p20071202044231.tar.lzma
BASH=bash-4.0.tar.gz
SYSVINIT=sysvinit-2.86.tar.gz
KBD=kbd-1.15.tar.gz
LESS=less-424.tar.gz
GREP=grep-2.5.4.tar.bz2
FINDUTILS=findutils-4.5.3.tar.gz
UDEV=udev-140.tar.bz2
BOOTSCRIPTS=bootscripts-cross-lfs-1.2-pre6.tar.bz2   

functions

Процедура m_default служит для сборки всех пакетов, которые могут быть собраны стандартной схемой configure && make && make install. Эту функцию (и пару дополнительных) я вынес в общий файл ~/bin/clfs/functions.inc.sh

~/bin/clfs/functions.inc.sh


#!/bin/bash
# functions

# save variable
function _save () {
        eval $1_SAVE="\$$1"
}
# restore variable
function _restore () {
        eval export $1="\$$1_SAVE"
}

######
# my default building procedure
# USE : m_default NAME [configure_opts make_first_command build_dir pre_configure_command]
function m_default () {
	NAME="$(echo "$1" | tr "[:upper:]" "[:lower:]")"
	eval TAR="\$${1}"
	COPT="$2"
	MMAKE="$3"
	BDIR="$4"
	PRECONF="$5"
echo -e ">>> \033[32m \033[1m * \033[37m $1 \033[0m"
echo "-> Making $NAME from $TAR with configure $COPT && $MMAKE && make && make install (in $BDIR)."
echo "$0 -> Making $NAME from $TAR with configure $COPT && $MMAKE && make && make install (in $BDIR)." >> ~/clfs.log
cd $SRC
if [ ! -f $DISTFILES/$TAR ]; then
	echo "ERROR: File $DISTFILES/$TAR not found for copy $NAME"
	exit 1
fi
cp -v $DISTFILES/$TAR ./ || exit 1
if [ $(echo $TAR | grep lzma) ]; then
	lzma -d $TAR
fi
echo "untaring..."
ls $NAME*tar* | while read line
do
	echo tar -xxf $line
	tar -xxf $line || exit 1
done
cd ./$NAME*/
ls ~/clfs/$NAME*.patch | while read line 
do 
	echo patch -Np1 -i $line
	patch -Np1 -i $line || exit 1
done
if [ ! -z "$BDIR" ]; then
	cd $BDIR
	echo "-> Making in $(pwd)"
	PREV="../$NAME*/"
fi
if [ ! -z "$PRECONF" ]; then
	echo "-> Pre configure : $PRECONF"
fi
echo "-> $PREV./configure $COPT && $MMAKE && make && make install (into ${DESTDIR})"
eval $PRECONF && \
$PREV./configure $COPT && \
eval $MMAKE && \
make && \
make DESTDIR=${DESTDIR} install || exit 1
echo "-> Done $NAME."
}
#
#######


cross-tools

Тут я просто оберну сборку каждого пакета в функцию b_<имя пакета>, а затем последовательно, по зависимостям вызову (MAIN). В файле сборки подключены functions.inc.sh с функциями и packages.inc, со списком пакетов.

4-cross-tools.sh:


#!/bin/bash

# v 0.2

export CFLAGS=""
export CXXFLAGS=""

#export CHOST="i686-pc-linux-gnu"
#export CFLAGS="-march=prescott -O2 -pipe -fomit-frame-pointer -s"
export CXXFLAGS="${CFLAGS}"
export ABI=32

export CC=""
export CROSS_COMPILE=""
export DESTDIR=""

DISTFILES=/usr/portage/distfiles
SRC=~/src/
 


. ~/bin/clfs/functions.inc.sh
. ~/bin/clfs/packages.inc

# GMP
function b_gmp () {
m_default GMP "--prefix=${CLFS}/cross-tools --enable-cxx --enable-mpbsd"
}

# MPFR
function b_mpfr () {
_save LDFLAGS
export LDFLAGS="-Wl,-rpath,${CLFS}/cross-tools/lib"
m_default MPFR "--prefix=${CLFS}/cross-tools --enable-shared --with-gmp=${CLFS}/cross-tools"
_restore LDFLAGS
}

# BINUTILS
function b_binutils () {
mkdir -v ~/src/binutils-build
m_default BINUTILS "--prefix=${CLFS}/cross-tools --host=${CLFS_HOST} --target=${CLFS_TARGET} \
		--with-sysroot=${CLFS} --disable-nls --enable-shared --disable-multilib" "make configure-host" "../binutils-build/"
cp -v ../binutils-*/include/libiberty.h ${CLFS}/usr/include
}

# GCC
function b_gcc () {
mkdir -v ~/src/gcc-build
_save LDFLAGS
export LDFLAGS="-Wl,-rpath,${CLFS}/cross-tools/lib" 
m_default GCC "--prefix=${CLFS}/cross-tools --build=${CLFS_HOST} --host=${CLFS_HOST} --target=${CLFS_TARGET} \
    --disable-multilib --with-sysroot=${CLFS} --disable-nls \
    --without-headers --with-newlib --disable-decimal-float \
    --disable-libgomp --disable-libmudflap --disable-libssp \
    --with-mpfr=${CLFS}/cross-tools --with-gmp=${CLFS}/cross-tools \
    --disable-shared --disable-threads --enable-languages=c" "" "../gcc-build/"
_restore LDFLAGS
}

# GLIBC 
function b_glibc () {
echo "-> Glibc ports"
cd ~/src
cp $DISTFILES/$GLIBC_PORTS ./
mkdir -v ~/src/glibc-build
cd ~/src/glibc-build
cat > config.cache << EOF
libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
libc_cv_gnu89_inline=yes
EOF
cat > configparms << EOF
install_root=${CLFS}
EOF
_save BUILD_CC
_save CC
_save AR
_save RANLIB
export BUILD_CC="gcc"
export CC="${CLFS_TARGET}-gcc"
export AR="${CLFS_TARGET}-ar" 
export RANLIB="${CLFS_TARGET}-ranlib"
m_default GLIBC "--prefix=/usr \
    --libexecdir=/usr/lib/glibc --host=${CLFS_TARGET} --build=${CLFS_HOST} \
    --disable-profile --enable-add-ons=../glibc*-ports*/,nptl --with-tls --enable-kernel=2.6.0 \
    --with-__thread --with-binutils=${CLFS}/cross-tools/bin \
    --with-headers=${CLFS}/usr/include --cache-file=config.cache" "" "../glibc-build/"
_restore BUILD_CC
_restore CC
_restore AR
_restore RANLIB
# locale
echo "-> Locale"
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.9/localedata
${LOCALEDEF} -i locales/en_US -f charmaps/ISO-8859-1 --prefix=${CLFS} en_US
${LOCALEDEF} -i locales/ru_RU -f charmaps/UTF-8 --prefix=${CLFS} ru_RU
unset I18NPATH GCONV_PATH LOCALEDEF
# config
echo "-> Config"
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
# timezone
cp -v --remove-destination ${CLFS}/usr/share/zoneinfo/Europe/Moscow ${CLFS}/etc/localtime
# dynamic loader
cat > ${CLFS}/etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib
/usr/lib
/lib
# End /etc/ld.so.conf
EOF
}

# GCC final
function b_gcc_final () {
rm -fr ~/src/gcc*
mkdir -p ~/src/gcc-build/
_save AR
_save LDFLAGS
_save AS_FOR_TARGET
_save LD_FOR_TARGET
export AR=ar 
export LDFLAGS="-Wl,-rpath,${CLFS}/cross-tools/lib"
export AS_FOR_TARGET=${CLFS_TARGET}-as
export LD_FOR_TARGET=${CLFS_TARGET}-ld
m_default GCC "--prefix=${CLFS}/cross-tools \
    --build=${CLFS_HOST} --host=${CLFS_HOST} --target=${CLFS_TARGET} \
    --disable-multilib --with-sysroot=${CLFS} --disable-nls \
    --enable-shared --enable-languages=c,c++ --enable-__cxa_atexit \
    --with-mpfr=${CLFS}/cross-tools --with-gmp=${CLFS}/cross-tools \
    --enable-c99 --enable-long-long --enable-threads=posix" "" "../gcc-build/"
_restore AR
_restore LDFLAGS
_restore AS_FOR_TARGET
_restore LD_FOR_TARGET
}


# FILE
function b_file () {
m_default FILE "--prefix=${CLFS}/cross-tools"
}

# GROFF
function b_groff () {
m_default GROFF "--prefix=${CLFS}/cross-tools --without-x"
}

# SHADOW
function b_shadow () {
export shadow_cv_passwd_dir="${CLFS}/bin"
export ac_cv_func_lckpwdf=no
m_default SHADOW "--prefix=${CLFS}/cross-tools --sbindir=${CLFS}/cross-tools/bin \
    --sysconfdir=$CLFS/etc --disable-shared --without-libpam \
    --without-audit --without-selinux --program-prefix=${CLFS_TARGET}- \
    --cache-file=config.cache" "cp config.h{,.orig} && sed '/PASSWD_PROGRAM/s/passwd/${CLFS_TARGET}-&/' config.h.orig > config.h"
}

# NCURSES
function b_ncurses () {
m_default NCURSES "--prefix=${CLFS}/cross-tools \
	    --without-shared" "make -C include && make -C progs tic && install -m755 progs/tic ${CLFS}/cross-tools/bin && return"
}


#####################
# MAIN
 
# cross-tools

case "$1" in

1)
# stage 1
b_gmp 
b_mpfr
b_binutils
b_gcc
b_glibc
b_gcc_final
echo "Stage1 complete! Please, run stage 2" && exit
;;

2)
# stage 2
b_file
b_groff
b_shadow
b_ncurses
echo "All Done"
echo "clear $SRC"
rm -fr ~/src/*
;;

*) 
echo "Use $0 <stage>"
;;


По окончании сборки у нас будет набор инструментов в ${CLFS}/cross-tools/, которым мы будем собирать всю целевую систему. По этому-то в переменной $PATH мы и прописали первым ее bin/.

Если все прошло успешно - заархивируйте этот этап:

cd ~/
tar -czf cross-tools.tar.gz ${CLFS}

Если что-всегда можно будет вернуться к чистой системе с этого этапа.

system

Сборка целевой системы. Так же последовательно, следуя документации CLFS. В отличии от сборки для cross-tools пакеты будут собираться с prefix=/usr, а не prefix=/${CLFS}/cross-tools. Так же будет экспортирована переменная DESTDIR, указывающая make - куда необходимо ставить пакеты.

Перед сборкой целевой системы желательно почистить директорию ~/src

rm -fr ~/src/*

Сборка:

5-system.sh

#!/bin/bash

# v 0.2.1

DISTFILES=/usr/portage/distfiles/
SRC=~/src/

export DESTDIR=${CLFS}
export CC="${CLFS_TARGET}-gcc"
export CXX="${CLFS_TARGET}-g++"
export AR="${CLFS_TARGET}-ar"
export AS="${CLFS_TARGET}-as"
export RANLIB="${CLFS_TARGET}-ranlib"
export LD="${CLFS_TARGET}-ld"
export STRIP="${CLFS_TARGET}-strip"
export CROSS_COMPILE="${CLFS_TARGET}-"


. ~/bin/clfs/functions.inc.sh
. ~/bin/clfs/packages.inc


# GMP
function b_gmp () {
m_default GMP "--prefix=/usr \
	    --build=${CLFS_HOST} --host=${CLFS_TARGET} \
            --enable-cxx --enable-mpbsd"
rm -v ${CLFS}/usr/lib/lib{gmp,gmpxx,mp}.la
}


# MPFR 
function b_mpfr () {
m_default MPFR "--prefix=/usr --enable-shared \
    --build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --with-gmp-lib=${CLFS}/usr/lib"
rm -v ${CLFS}/usr/lib/libmpfr.la
}


# ZLIB
function b_zlib () {
_save AR
export AR="${AR} rc"
m_default ZLIB "--prefix=/usr --shared" "make && make prefix=${CLFS}/usr install && return"
_restore AR
mv -v ${CLFS}/usr/lib/libz.so.* ${CLFS}/lib
ln -sfv ../../lib/libz.so.1 ${CLFS}/usr/lib/libz.so
chmod -v 644 ${CLFS}/usr/lib/libz.a
}


# BINUTILS
function b_binutils () {
_save AR
_save AS
export AR=ar 
export AS=as
mkdir -v ~/src/binutils-build
m_default BINUTILS "../binutils-*/configure --prefix=/usr \
    --build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --target=${CLFS_TARGET} --enable-shared" "make configure-host && make tooldir=/usr && make tooldir=/usr install && return" "../binutils-build/"
}


# GCC
function b_gcc () {
mkdir -v ~/src/gcc-build
# gcc patch from CLFS
cat > ~/clfs/gcc-4.3.3-clfs.patch << "EOF"
diff -Naur gcc-4.3.3.orig/gcc/gccbug.in gcc-4.3.3/gcc/gccbug.in
--- gcc-4.3.3.orig/gcc/gccbug.in	2009-03-19 13:21:37.000000000 +0300
+++ gcc-4.3.3/gcc/gccbug.in	2009-03-19 13:28:37.000000000 +0300
@@ -81,7 +81,7 @@
   fi
 fi
 
-if [ @have_mktemp_command@ = yes ]; then
+if [ yes = yes ]; then
 	TEMP0=`mktemp $TMPDIR/poXXXXXX` || exit 1
 	TEMP=`mktemp $TMPDIR/pXXXXXX` || exit 1
 	BAD=`mktemp $TMPDIR/pbadXXXXXX` || exit 1
diff -Naur gcc-4.3.3.orig/gcc/Makefile.in gcc-4.3.3/gcc/Makefile.in
--- gcc-4.3.3.orig/gcc/Makefile.in	2009-03-19 13:21:37.000000000 +0300
+++ gcc-4.3.3/gcc/Makefile.in	2009-03-19 13:30:40.000000000 +0300
@@ -3525,7 +3525,7 @@
 	      SHELL='$(SHELL)'; MACRO_LIST=`${PWD_COMMAND}`/macro_list ; \
 	      export TARGET_MACHINE srcdir SHELL MACRO_LIST && \
 	      cd $(build_objdir)/fixincludes && \
-	      $(SHELL) ./fixinc.sh ../../gcc/$${fix_dir} \
+	      $(SHELL) -c true ../../gcc/$${fix_dir} \
 	        $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS) ); \
 	    rm -f $${fix_dir}/syslimits.h; \
 	    if [ -f $${fix_dir}/limits.h ]; then \
diff -Naur gcc-4.3.3.orig/libiberty/Makefile.in gcc-4.3.3/libiberty/Makefile.in
--- gcc-4.3.3.orig/libiberty/Makefile.in	2009-03-19 13:21:37.000000000 +0300
+++ gcc-4.3.3/libiberty/Makefile.in	2009-03-19 13:22:33.000000000 +0300
@@ -344,7 +344,7 @@
 @MAINT@	echo stamp > stamp-functions
 
 INSTALL_DEST = @INSTALL_DEST@
-install: install_to_$(INSTALL_DEST) install-subdir
+install: install-subdir
 
 # This is tricky.  Even though CC in the Makefile contains
 # multilib-specific flags, it's overridden by FLAGS_TO_PASS from the
EOF
m_default GCC "--prefix=/usr --libexecdir=/usr/lib \
    --build=${CLFS_HOST} --host=${CLFS_TARGET} --target=${CLFS_TARGET} \
    --enable-shared --enable-threads=posix --enable-__cxa_atexit \
    --enable-c99 --enable-long-long --enable-clocale=gnu \
    --enable-languages=c,c++ --disable-libstdcxx-pch" "" "../gcc-build/" 
ln -sfv ../usr/bin/cpp ${CLFS}/lib
ln -sfv gcc ${CLFS}/usr/bin/cc
}
 

# SED
function b_sed () {
m_default SED "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --bindir=/bin"
}
 

# e2fsprogs
function b_e2fsprogs () {
#cp -v $DISTFILES/$E2FSPROGS_LIBS $SRC/
mkdir -v ~/src/e2fsprogs-build
m_default E2FSPROGS "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --with-root-prefix="" \
    --enable-elf-shlibs" "make COMPILE_ET=compile_et && make DESTDIR=${CLFS} install &&  make DESTDIR=${CLFS} install-libs && return" "../e2fsprogs-build/"
rm -v ${CLFS}/usr/lib/lib{blkid,com_err,e2p,ext2fs,ss,uuid}.so
ln -sv ../../lib/libblkid.so.1 ${CLFS}/usr/lib/libblkid.so
ln -sv ../../lib/libcom_err.so.2 ${CLFS}/usr/lib/libcom_err.so
ln -sv ../../lib/libe2p.so.2 ${CLFS}/usr/lib/libe2p.so
ln -sv ../../lib/libext2fs.so.2 ${CLFS}/usr/lib/libext2fs.so
ln -sv ../../lib/libss.so.2 ${CLFS}/usr/lib/libss.so
ln -sv ../../lib/libuuid.so.1 ${CLFS}/usr/lib/libuuid.so
}


# coreutils
function b_coreutils () {
m_default COREUTILS "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --cache-file=config.cache \
    --enable-no-install-program=kill,uptime \
    --enable-install-program=hostname" "make fu_cv_sys_stat_statfs2_bsize=yes && make install && return" "" "touch man/uname.1 man/hostname.1"
mv -v ${CLFS}/usr/bin/{cat,chgrp,chmod,chown,cp,date} ${CLFS}/bin
mv -v ${CLFS}/usr/bin/{dd,df,echo,false,hostname,ln,ls,mkdir} ${CLFS}/bin
mv -v ${CLFS}/usr/bin/{mv,pwd,rm,rmdir,stty,true,uname} ${CLFS}/bin
mv -v ${CLFS}/usr/bin/chroot ${CLFS}/usr/sbin
mv -v ${CLFS}/usr/bin/{\[,basename,head,install,nice} ${CLFS}/bin
mv -v ${CLFS}/usr/bin/{readlink,sleep,sync,test,touch} ${CLFS}/bin
ln -sfv ../../bin/install ${CLFS}/usr/bin
}


# iana-etc
function b_iana_etc () {
_save PREFIX
export PREFIX=${CLFS}
m_default IANA "" "" "" "cp Makefile Makefile.orig && sed 's/PREFIX=//gi' Makefile.orig > Makefile && make && make install && return"
_restore PREFIX
}


# m4
function b_m4 () {
m_default M4 "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr"
}


# bison
function b_bison () {
m_default BISON "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr" "echo '#define YYENABLE_NLS 1' >> config.h"
}


# ncurses
function b_ncurses () {
m_default NCURSES "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
	--prefix=/usr --libdir=/lib --with-shared \
	--without-debug --without-ada \
	--enable-widec \
	--with-build-cppflags=-D_GNU_SOURCE"
mv -v ${CLFS}/lib/lib{panelw,menuw,formw,ncursesw,ncurses++w}.a ${CLFS}/usr/lib

rm -v ${CLFS}/lib/lib{ncursesw,menuw,panelw,formw}.so
ln -sfv ../../lib/libncursesw.so.5 ${CLFS}/usr/lib/libncursesw.so
ln -sfv ../../lib/libmenuw.so.5 ${CLFS}/usr/lib/libmenuw.so
ln -sfv ../../lib/libpanelw.so.5 ${CLFS}/usr/lib/libpanelw.so
ln -sfv ../../lib/libformw.so.5 ${CLFS}/usr/lib/libformw.so

for lib in curses ncurses form panel menu ; do
        echo "INPUT(-l${lib}w)" > ${CLFS}/usr/lib/lib${lib}.so
        ln -sfv lib${lib}w.a ${CLFS}/usr/lib/lib${lib}.a
done
ln -sfv libncursesw.so ${CLFS}/usr/lib/libcursesw.so
ln -sfv libncursesw.a ${CLFS}/usr/lib/libcursesw.a
ln -sfv libncurses++w.a ${CLFS}/usr/lib/libncurses++.a
ln -sfv ncursesw5-config ${CLFS}/usr/bin/ncurses5-config

ln -sfv ../../usr/share/terminfo ${CLFS}/usr/lib/terminfo
}


# procps
function b_procps () {
_save CPPFLAGS
export CPPFLAGS=""
m_default PROCPS "" "" "" "make CPPFLAGS= lib64=lib m64= && make DESTDIR=${CLFS} lib64=lib m64= ldconfig= install='install -D' install && return "
_restore CPPFLAGS
}


# libtool
function b_libtool () {
m_default LIBTOOL "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr"
}


# flex
function b_flex () {
m_default FLEX "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr" "make CC='${CC} -fPIC' libfl.a"
ln -sfv libfl.a ${CLFS}/usr/lib/libl.a
cat > ${CLFS}/usr/bin/lex << "EOF"
#!/bin/sh
# Begin /usr/bin/lex

exec /usr/bin/flex -l "$@"

# End /usr/bin/lex
EOF
chmod -v 755 ${CLFS}/usr/bin/lex
}


# bash
function b_bash () {
cat > ~/tmp/config.cache << "EOF"
ac_cv_func_mmap_fixed_mapped=yes
ac_cv_func_strcoll_works=yes
ac_cv_func_working_mktime=yes
bash_cv_func_sigsetjmp=present
bash_cv_getcwd_malloc=yes
bash_cv_job_control_missing=present
bash_cv_printf_a_format=yes
bash_cv_sys_named_pipes=present
bash_cv_ulimit_maxfds=yes
bash_cv_under_sys_siglist=yes
bash_cv_unusable_rtsigs=no
gt_cv_int_divbyzero_sigfpe=yes
EOF
m_default "BASH" "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
   --prefix=/usr --bindir=/bin --cache-file=config.cache \
   --without-bash-malloc --with-installed-readline" "" "" "cp ~/tmp/config.cache ./"
}

# shadow
function b_shadow () {
cat > ~/tmp/config.cache << EOF
ac_cv_func_setpgrp_void=yes
EOF
m_default SHADOW "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --sysconfdir=/etc --without-libpam \
    --without-audit --without-selinux \
    --cache-file=config.cache" "" "" "cp ~/tmp/config.cache ./"
cp ${CLFS}/etc/login.defs login.defs.orig
sed -e's@#MD5_CRYPT_ENAB.no@MD5_CRYPT_ENAB yes@' \
    -e 's@/var/spool/mail@/var/mail@' \
    login.defs.orig > ${CLFS}/etc/login.defs
mv -v ${CLFS}/usr/bin/passwd ${CLFS}/bin
echo "Config"
${CLFS_TARGET}-pwconv
${CLFS_TARGET}-passwd root
}

# sysvinit
function b_sysvinit () {
cat > ~/clfs/sysvinit-2.86-clfs.patch <<"EOF"
diff -Naur sysvinit-2.86.orig/src/Makefile sysvinit-2.86/src/Makefile
--- sysvinit-2.86.orig/src/Makefile	2009-03-19 14:27:09.000000000 +0300
+++ sysvinit-2.86/src/Makefile	2009-03-19 14:27:25.000000000 +0300
@@ -50,7 +50,7 @@
 MANDIR		= /usr/share/man
 
 # Additional libs for GNU libc.
-ifneq ($(wildcard /usr/lib/libcrypt.a),)
+ifneq ($(wildcard $(ROOT)/usr/lib/libcrypt.a),)
 LCRYPT		= -lcrypt
 endif
 
@@ -137,12 +137,12 @@
 		for i in $(MAN8); do \
 			$(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man8/; \
 		done
-ifeq ($(ROOT),)
+ifeq (,)
 		#
 		# This part is skipped on Debian systems, the
 		# debian.preinst script takes care of it.
-		@if [ ! -p /dev/initctl ]; then \
-		 echo "Creating /dev/initctl"; \
-		 rm -f /dev/initctl; \
-		 mknod -m 600 /dev/initctl p; fi
+		@if [ ! -p $(ROOT)/dev/initctl ]; then \
+		 echo "Creating $(ROOT)/dev/initctl"; \
+		 rm -f $(ROOT)/dev/initctl; \
+		 mknod $(ROOT)/dev/initctl p; chmod 600 $(ROOT)/dev/initctl ; fi
 endif
EOF
m_default SYSVINIT "" "" "" "make -C src clobber && \
	make -C src ROOT=${CLFS} CC='${CC}' && \
	make -C src ROOT=${CLFS} INSTALL=install install && return"
echo "-> Config"

cat > ${CLFS}/etc/inittab <<"EOF"
# Begin /etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/init.d/rc sysinit
l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
su:S016:once:/sbin/sulogin
1:2345:respawn:/sbin/agetty -I '\033(K' tty1 9600
2:2345:respawn:/sbin/agetty -I '\033(K' tty2 9600
3:2345:respawn:/sbin/agetty -I '\033(K' tty3 9600
4:2345:respawn:/sbin/agetty -I '\033(K' tty4 9600
5:2345:respawn:/sbin/agetty -I '\033(K' tty5 9600
6:2345:respawn:/sbin/agetty -I '\033(K' tty6 9600
c0:12345:respawn:/sbin/agetty 115200 ttyS0 vt100
# End /etc/inittab
EOF
echo "done"
}


# IPUTILS
function b_iputils () {
m_default IPUTILS "" "" "" "make CC=${CC} && return"
install -v -m755 ping{,6} ${CLFS}/bin
install -v -m755 arping ${CLFS}/usr/bin
install -v -m755 clockdiff ${CLFS}/usr/bin
install -v -m755 rdisc ${CLFS}/usr/bin
install -v -m755 tracepath ${CLFS}/usr/bin
install -v -m755 trace{path,route}6 ${CLFS}/usr/bin
install -v -m644 doc/*.8 ${CLFS}/usr/share/man/man8
}


# IPROUTE2
function b_iproute2 () {
cat > ~/clfs/iproute2-2.6.28-tunnel.patch <<EOF
--- iproute2-2.6.9-050209/ip/iptunnel.c.orig    2005-03-06 00:22:11.069784441 
+0800
+++ iproute2-2.6.9-050209/ip/iptunnel.c 2005-03-06 01:50:29.711234091 +0800
@@ -29,6 +29,11 @@
 #include <linux/if.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
+
+#ifndef __constant_htons
+#define __constant_htons(x)  htons(x)
+#endif
+
 #include <linux/if_tunnel.h>
 
 #include "rt_names.h"
EOF
_save LIBS 
export LIBS=""
m_default IPROUTE2 "" "make DESTDIR=${CLFS} CC=${CC} && make DESTDIR=${CLFS} install && return" "" "cp misc/Makefile{,.orig} && sed '/^TARGETS/s@arpd@@g' misc/Makefile.orig > misc/Makefile"
ln -sf ${CLFS}/sbin/ip ${CLFS}/bin/
_restore LIBS
}


# NET TOOLS
function b_net_tools () {
cat > ~/clfs/net-tools-null.patch <<EOF
diff -up net-tools-1.60/lib/ec_hw.c.old net-tools-1.60/lib/ec_hw.c
--- net-tools-1.60/lib/ec_hw.c.old	1999-11-20 22:02:53.000000000 +0100
+++ net-tools-1.60/lib/ec_hw.c	2008-02-25 09:04:00.000000000 +0100
@@ -18,6 +18,7 @@
 
 #include <net/if_arp.h>
 #include "net-support.h"
+#define NULL ((void *) 0)
 
 struct hwtype ec_hwtype =
 {
EOF
_save BASEDIR
export BASEDIR=${CLFS}
m_default NET "" "" "" "yes  | ./configure.sh config.in && make && BASEDIR=${CLFS} make DESTDIR=${CLFS} install && return"
_restore BASEDIR
}

# UTIL-LINUX
function b_util_linux () {
#     --enable-arch --enable-partx --disable-wall --enable-write \ 
m_default UTIL "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --disable-makeinstall-chown"
mv -v ${CLFS}/usr/bin/logger ${CLFS}/bin
}

# KBD
function b_kbd () {
cat > ~/tmp/config.cache << EOF
ac_cv_func_setpgrp_void=yes
ac_cv_func_malloc_0_nonnull=yes
ac_cv_func_realloc_0_nonnull=yes
EOF
m_default KBD "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --cache-file=config.cache" "" "" "cp ~/tmp/config.cache ./"
mv -v ${CLFS}/usr/bin/{kbd_mode,dumpkeys,loadkeys,openvt,setfont} ${CLFS}/bin
}

# LESS
function b_less () {
m_default LESS "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --sysconfdir=/etc"
mv -v ${CLFS}/usr/bin/less ${CLFS}/bin
}

# GREP
function b_grep () {
m_default GREP "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --bindir=/bin --disable-perl-regexp"
}

# FIND
function b_findutils () {
cat > ~/tmp/config.cache << EOF
gl_cv_func_wcwidth_works=yes
gl_cv_header_working_fcntl_h=yes
ac_cv_func_fnmatch_gnu=yes
EOF
m_default FINDUTILS "--build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --cache-file=config.cache \
    --libexecdir=/usr/lib/locate \
    --localstatedir=/var/lib/locate" "" "" "cp ~/tmp/config.cache ./"
mv -v ${CLFS}/usr/bin/find ${CLFS}/bin
cp ${CLFS}/usr/bin/updatedb{,.orig}
sed 's@find:=${BINDIR}@find:=/bin@' ${CLFS}/usr/bin/updatedb.orig > \
    ${CLFS}/usr/bin/updatedb
rm ${CLFS}/usr/bin/updatedb.orig
}

# UDEV
function b_udev () {
m_default UDEV " --build=${CLFS_HOST} --host=${CLFS_TARGET} \
    --prefix=/usr --exec-prefix= \
    --sysconfdir=/etc"
install -dv ${CLFS}/lib/firmware
install -dv ${CLFS}/lib/udev/devices
}


function b_bootscripts () {
#m_default BOOTSCRIPTS "" "" "" "make DESTDIR=${CLFS} install&& return"
m_default BOOTSCRIPTS "" "" "" "make DESTDIR=${CLFS} install-bootscripts && make DESTDIR=${CLFS} install-network && return"
echo "Configure"
# CLOCK
cat > ${CLFS}/etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=0
# End /etc/sysconfig/clock
EOF
# FSTAB
cat > ${CLFS}/etc/fstab << "EOF"
# Begin /etc/fstab
# file system  mount-point  type   options          dump  fsck
#/dev/[xxx]     /            [fff]  defaults         1     1
#/dev/[yyy]     swap         swap   pri=1            0     0
/dev/mtdblock1  /       jffs2   defaults        0       0
proc           /proc        proc   defaults         0     0
sysfs          /sys         sysfs  defaults         0     0
devpts         /dev/pts     devpts gid=4,mode=620  0     0
shm            /dev/shm     tmpfs  defaults         0     0
# End /etc/fstab
EOF
# NETWORK
cat > ${CLFS}/etc/sysconfig/network << EOF
HOSTNAME=[clfs]
EOF
cd ${CLFS}/etc/sysconfig/network-devices &&
mkdir -v ifconfig.eth0 &&
cat > ifconfig.eth0/ipv4 << "EOF"
ONBOOT=yes
SERVICE=ipv4-static
IP=172.22.244.96
GATEWAY=172.22.244.4
PREFIX=24
BROADCAST=172.22.244.255
EOF
}


# MAIN
case "$1" in

1) 
# stage 1
b_gmp
b_mpfr
b_zlib
b_binutils
b_gcc
b_e2fsprogs
echo "Stage 1 complete! Please, run $0 <stage>" && exit
;;

2)
# stage 2
b_coreutils
b_iana_etc
b_m4
b_bison
b_ncurses
b_procps
b_sed 
b_libtool
b_util_linux
b_iputils
b_iproute2
b_net_tools
b_bash 
b_shadow
b_sysvinit 
b_kbd
b_less
b_grep
b_findutils
b_udev
b_bootscripts
echo "All Done"
;;

*) 
echo "Use $0 <stage>"
;;
esac

Все. Система готова. Можно заворачивать и загружаться.

Сборку дальнейших опциональных пакетов желательно так же описать в отдельном скрипте, используя текущие functions.sh и packages.inc

заворачиваем

mkfs.sh

#!/bin/bash
BASE=/home/clfs

sudo rm -fr /home/clfs/tmpfs
sudo mkdir /home/clfs/tmpfs

echo "Clear old"
rm -ivfr $BASE/tmpfs 
mkdir $BASE/tmpfs

echo "Copy new"
rsync --exclude "cross-tools/" \
 --exclude "usr/share/i18n/" \
 --exclude "usr/share/locale/" \
 --exclude "usr/share/info/" \
 --exclude "usr/share/man/" \
 --exclude "usr/share/doc/" \
 --exclude "usr/share/" \
 --exclude "armv5te-none-linux-gnueabi/" \
 --exclude "usr/include/" \
 --exclude "*.a" \
 --exclude "*.h" \
 -a \
$BASE/root/ $BASE/tmpfs/

echo "Stripe"
find $BASE/tmpfs/ -type f -exec arm-none-linux-gnueabi-strip -s {} 2>/dev/null \;

echo "REMOVE ME TODO: mkdev"
sudo $BASE/bin/clfs/6-dev.sh

echo "Chown"
sudo chown -R root:root $BASE/tmpfs

echo "Making fs"
sudo $BASE/bin/mkfs.jffs2 -e 128 –d=265289728 -n --root=$BASE/tmpfs -o rootfs.jffs2

ядро

#!/bin/bash
cd ~/linux/linux
export CC="${CLFS_TARGET}-gcc"
export CXX="${CLFS_TARGET}-g++"
export AR="${CLFS_TARGET}-ar"
export AS="${CLFS_TARGET}-as"
export RANLIB="${CLFS_TARGET}-ranlib"
export LD="${CLFS_TARGET}-ld"
export STRIP="${CLFS_TARGET}-strip"
export CROSS_COMPILE="${CLFS_TARGET}-"
make ARCH=arm
~bin/mkimage.sh
cp -v uImage ~/my

Gentoo

Если у вас довольно много места (от 250 Мб) - можно попробовать Gentoo. На зеркалах можно найти stage3-arm-xxxx.x.tar.bz2 Последовательность действий будет примерно следующей:

Распаковать, Завернуть в свою ФС (jffs2 к примеру), залить как rootfs, загрузиться, подключить по сети репозитарии, собрать distcc и далее уже собирать на МК, в помощь которым будут компиляторы по distcc, а изменения сливать обратно по rsync.

Но у меня к примеру Gentoo очень долго загружается (несколько минут) и довольно медленно работает, по это все-таки лучше имхо собирать свою систему.

Сборка

Можно собирать конечно-же прямо на целевой системе, используя distcc, но это как правило не очень удобно. По этому существуют gentoo инструменты кросс-компиляции. Это crossdev


Подробнее: http://www.gentoo.org/proj/en/base/embedded/handbook/cross-compiler.xml http://www.gentoo.org/proj/en/base/embedded/handbook/index.xml


toolchain

Прописываем в /etc/make.conf

PORTDIR_OVERLAY="/usr/local/portage"

Ставим тулчан:

crossdev --target armv5te-gentoo-linux-gnueabi

Тут триплет armv5te-gentoo-linux-gnueabi указывает на нашу архитектуру. В Gentoo этот параметр называется CBUILD


Эта команда собирет набор для компиляции: компилятор (armv5te-gentoo-linux-gnueabi), binutils (и все что потребуется). В оверлее появится соответствующая директория:

ls  /usr/local/portage/cross-armv5te-gentoo-linux-gnueabi/
   binutils  gcc  gdb  glibc  insight  linux-headers и т.п.

которыми мы и будем собирать пакеты для целевой системы.

Далее handbook предалгает собираться по принципу CLFS:

./configure \
      --target=$CTARGET \
      --prefix=/usr \
      --with-sysroot=/usr/$CTARGET \
      --disable-werror
make
make install DESTDIR=$PWD/install-root

Но можно так же использовать emerge.

sysroot

Старый стиль сборки использует --prefix=<целевая диретория> при configure. Как показывает практика - не все пакеты корректно так собираются или работают. Необходимо разделять sysroot (системная директория, где хранится компилятор, заголовки и библиотеки), buildroot (директория где происходит сборка), и rootfs (целевая директория, которая в дальнейшем будет файловой системой целевого устройства. Ее так же называют DESTDIR).

В Gentoo используется sysroot вида:

/usr/$CTARGET/
|-- bin/
|-- lib/            critical runtime libs (libc/ldso/etc...)
`-- usr/
    |-- include/    development headers
    |   |-- linux/      like the linux kernel
    |   `-- asm/        like the arch-specific
    `-- lib/        non critical runtime libs / development libs

( см. handbook ).

Где $CTARGET - наша целевая система.

По этому мы будем ставить необходимые для линковки пакеты и туда, и в DESTDIR.

ROOT

Целевая директория (она же DESTDRIR, она же rootfs) в Gentoo называется ROOT. Это та директория, которая будет образовывать виртуальный / нашей целевой системы.


make.conf

Подготовим наш make.conf, который будет использоваться для сборки кросс-компилятором:

/usr/$CTARGET/etc/make.conf

ACCEPT_KEYWORDS="*- arm"
ARCH="arm"
CHOST="armv5te-gentoo-linux-gnueabi"
CFLAGS="-O2-march=armv5te -mtune=arm926ej-s -s "
CXXFLAGS="${CFLAGS}"
USE="-* minimal"
ln -s /etc/make.globals SYSROOT/etc/make.globals
ln -s /usr/portage/profiles/embeded SYSROOT/etc/make.profile


emerge

Ставим обертку:

emerge crossdev-wrappers

Далее собираем все пакеты по:

emerge-armv5te-gentoo-linux-gnueabi <имя_пакета>

Опции ROOT= указывает куда собирать. Некоторые пакеты (ncurses, ) надо собрать и в CTARGET и в наш rootfs (для линковки).


Ссылки

Личные инструменты