Derick Swanepoel wrote:
Hi,
I'm busy building a cross-compile environment for an ARM (XScale) in an x86
host environment, but I'm having trouble emerging packages like procps and
gdb which require headers from /usr/include.
What do you need procps for? If you're using busybox, it already
contains ps, free, top and kill and it should be enough for most
embedded systems.
I've built an armeb-softfloat-linux-uclibc cross toolchain with crossdev
which can successfully compile uclibc, bash, baselayout, etc. and install
in ROOT=/gentoo-arm. However, when I try to emerge something like procps,
it fails to find curses.h and termcap.h. Where should the cross-compiler be
looking for these headers?
Is ROOT the only variable you set? There are some other important vars,
like ARCH, CBUILD, CHOST, CTARGET. Many others are also useful while
cross-emerging.
Another problem I have is that gawk (3.1.4-r4) fails to execute with:
awk: can't resolve symbol '__fixdfsi'
As far as I can determine, __fixdfsi is one of GCC's softfloat library routines.
I would really like to know how the armeb-uclibc-softfloat stages (found in
experimental/arm/embedded on various Gentoo mirrors) were built.
As far as I know, they use catalyst.
Thanks,
Derick
I am building small Embedded Gentoo systems for i686 and ARM920T
architectures and for that I wrote a little script called egg
(attached). Perhaps you will find it useful. To create such a system for
arm920t (baselayout+uclibc+busybox), I'd simply run:
# crossdev -t arm-unknown-linux-uclibc
# egg -l uclibc -a arm920t -o /home/gentoo-for-arm
Later, to add some packages (e.g. dropbear and ncurses) I'd write:
# egg -l uclibc -a arm920t -o /home/gentoo-for-arm -fn dropbear ncurses
And finally, when I'm satisfied with my rootfs, I can strip it off
unnecessary trash:
# egg -l uclibc -arm920t -o /home/gentoo-for-arm -fns
This is an extremely simple tool (e.g. you can't set USE flags for
individual packages), but still I find it quite sufficient for my work.
You can use it to generate a rootfs for an armeb architecture just by
adding it to parse_arch() function. If you do that, don't forget to send
me the updated version.
Hope you find it useful,
Stanislaw Raczynski
#!/bin/bash
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#
# This script creates a tiny rootfs intended for embedded
# systems. It consists of baselayout, a C library, system tools
# and optional user packages.
#
# Created by Stanislaw Raczynski (sutashu at gmail dot com)
#
# Written by Stanislaw Raczynski (sutashu at gmail dot com),
# Marek Malczak
#-----------------------------------------------------------------------------
source /sbin/functions.sh || exit 3
if [[ `whoami` != "root" ]] ; then
eerror "You must run this as root"
exit 2
fi
#-----------------------------------------------------------------------------
die() {
echo
eerror $*
eerror Please read the logfiles:
eerror ${PORT_LOGDIR}/mkrootfs.log
eerror ${logfile}
exit 1
}
#-----------------------------------------------------------------------------
# Far out of date
usage() {
cat << EOF
Usage: ${HILITE}egg${NORMAL} ${GOOD}[options]${NORMAL}
${GOOD}[extra packages]${NORMAL}
Options:
${GOOD}-l${NORMAL} libc
Specify variant of libc to use. See egg -l help for details.
${GOOD}-b${NORMAL} baselayout
Specify variant of baselayout to use. See egg -b help for details.
${GOOD}-u${NORMAL} utils
Specify variant of system tools to use. See egg -u help for details.
${GOOD}-a${NORMAL} arch
Specify target architecture.
${GOOD}-s${NORMAL}
Strip rootfs at the end.
${GOOD}-v${NORMAL}
Be verbose.
EOF
exit ${1:-0}
}
#-----------------------------------------------------------------------------
parse_arch() {
CROSS_COMPILING="yes"
case $1 in
help) cat << EOF
Supported architectures for cross-compiling:
${GOOD}arm{$NORMAL} Generic ARM
${GOOD}arm920t{$NORMAL} ARM 920t
${GOOD}x86{$NORMAL} Generic x86
EOF
exit 0;;
arm) TARCH="arm";
EKEYWORDS="-* arm";
ECHOST="arm-unknown-linux-";
EUCLIBC_CPU="GENERIC_ARM";;
arm920t) TARCH="arm";
EKEYWORDS="-* arm";
ECHOST="arm-unknown-linux-";
EUCLIBC_CPU="ARM920T";;
x86) TARCH="x86";
EKEYWORDS="-* x86";
ECHOST="i386-unknown-linux-";
EUCLIBC_CPU="GENERIC_386";;
esac
}
#-----------------------------------------------------------------------------
parse_baselayout() {
case $1 in
help) cat << EOF
Supported baselayouts:
${GOOD}baselayout${NORMAL} Standard Gentoo baselayout.
${GOOD}baselayout-lite${NORMAL} Embedded Gentoo baselayout.
EOF
exit 0;;
baselayout) BPKG="sys-apps/baselayout";;
baselayout-lite) BPKG="sys-apps/baselayout-lite";;
*) eerror "Unsopported baselayout - '$1'!";
parse_baselayout "help"; exit 1;;
esac
}
#-----------------------------------------------------------------------------
parse_libc () {
case $1 in
help) cat << EOF
Supported C libraries:
${GOOD}gnu${NORMAL} GNU C Library (glibc). Pretty fat.
${GOOD}uclibc${NORMAL} uClibc. Intended for embedded systems.
${GOOD}diet${NORMAL} dietlibc. Minimal C library.
EOF
exit 0;;
gnu) LPKG="sys-libs/glibc"; EELIBC="glibc";;
uclibc) LPKG="sys-libs/uclibc"; EELIBC="uclibc";;
diet) LPKG="dev-libs/dietlibc";;
*) eerror "Unsopported C library - '$1'!";
parse_libc "help";
exit 1;;
esac
}
#-----------------------------------------------------------------------------
parse_utils () {
case $1 in
help) cat << EOF
Supported init systems:
${GOOD}busybox${NORMAL} Busybox. Complete, but small toolset.
${GOOD}minutils${NORMAL} Set of minimalistic system utilities.
${GOOD}core${NORMAL} Standard GNU file utilities.
EOF
exit 0;;
busybox) UPKG="busybox";;
minutils) UPKG="minutils";;
core) UPKG="sys-apps/coreutils";;
# embutils) NOT IN PORTAGE!
*) eerror "Unsopported system toolset - '$1'!"; parse_utils "help";
exit 1;;
esac
}
#-----------------------------------------------------------------------------
doemerge() {
[[ $# < 3 ]] && return 1
name_without_slashes=`echo "$1" | tr "/" "_"`
local
logfile="${PORT_LOGDIR}/rootfsmaker-$2-${name_without_slashes}.log"
export USE="$3 elibc_${EELIBC}"
einfo "Log: ${logfile}"
ebegin "Emerging $1"
if [[ ${UOPTS/-v} != ${UOPTS} ]] ; then
emerge info
emerge $1 ${EOPTS} 2>&1 | tee ${logfile}
else
emerge $1 ${EOPTS} >& ${logfile}
fi
local _pipestatus=${PIPESTATUS[*]}
[[ "${_pipestatus// /}" -eq 0 ]] || die "$1 failed :("
eend 0
}
#-----------------------------------------------------------------------------
dounmerge() {
name_without_slashes=`echo "$1" | tr "/" "_"`
local
logfile="${PORT_LOGDIR}/rootfsmaker-unmerge-${name_without_slashes}.log"
export USE="elibc_${EELIBC}"
einfo "Log: ${logfile}"
ebegin "Unmerging $1"
if [[ ${UOPTS/-v} != ${UOPTS} ]] ; then
emerge info
emerge -C $1 ${UOPTS} 2>&1 | tee ${logfile}
else
emerge -C $1 ${UOPTS} >& ${logfile}
fi
local _pipestatus=${PIPESTATUS[*]}
[[ "${_pipestatus// /}" -eq 0 ]] || die "$1 failed :("
eend 0
}
#-----------------------------------------------------------------------------
PORTDIR=$(portageq envvar PORTDIR)
PORT_LOGDIR=$(portageq envvar PORT_LOGDIR)
PORT_LOGDIR=${PORT_LOGDIR:-/var/log/portage}
export PORTAGE_TMPDIR="$(portageq envvar PORTAGE_TMPDIR)"
[[ ! -d ${PORT_LOGDIR} ]] && mkdir -p ${PORT_LOGDIR}
[[ ! -d ${PORTAGE_TMPDIR} ]] && mkdir -p ${PORTAGE_TMPDIR}
CBUILD=$(portageq envvar CBUILD)
CHOST=$(portageq envvar CHOST)
# Initial variable values
HARCH=$(env -uARCH portageq envvar ARCH)
TARCH=${HARCH}
EKEYWORDS="-* ${TARCH}"
#God will strike me down for this :/ (plz any1 knowing how to do it better,
change it)
#this basically cuts the last part of arch name i.e. arch-arm-cutthis
arch_word_count=`echo ${CHOST} | tr "-" " " | wc -w`
arch_word_count=`expr ${arch_word_count} - 1`
ECHOST="`echo ${CHOST} | cut -d "-" -f -${arch_word_count}`-"
# Packages to emerge
LPKG="sys-libs/uclibc"
BPKG="sys-apps/baselayout-lite"
IPKG=""
UPKG="busybox"
XPKG=""
# Packages to unmerge
CPKG=""
# emerge parameters
UOPTS=
EOPTS=
# Options
STRIP="no"
FORCE_CREATE="no"
CROSS_COMPILING="yes"
EMERGE_SYSTEM_PACKAGES="yes"
# Other vars
EELIBC="uclibc"
EROOT="${PORTAGE_TMPDIR}/rootfsmaker"
UCLIBC_CPU=${HARCH}
export CBUILD=$(portageq envvar CBUILD)
#Logging activity
echo "`date` $0 $*" >> "${PORT_LOGDIR}/rootfsmaker.log"
# Parse arguments:
while getopts "l:b:u:a:sVhfvo:c:n" flag
do
case $flag in
l) parse_libc ${OPTARG};;
b) parse_baselayout ${OPTARG};;
u) parse_utils ${OPTARG};;
a) parse_arch ${OPTARG};;
s) STRIP="yes";;
V) echo rootfsmaker version 0.2; exit 0;;
h) usage; exit;;
f) FORCE_CREATE="yes";;
v) UOPTS="${UOPTS} -v";;
o) EROOT=`echo ${OPTARG} | grep -q "^/" && echo ${OPTARG} ||
echo "${PWD}/${OPTARG}"`;;
c) CPKG="${CPKG}${OPTARG} ";;
n) EMERGE_SYSTEM_PACKAGES="no";;
?) usage; exit;;
esac
done
# --nodeps is quite necessary, since all packages have unwanted system-related
dependencies
EOPTS="${UOPTS} -u --nodeps"
# Extra packages to emerge:
shift `expr ${OPTIND} - 1`
XPKG=$*
#-----------------------------------------------------------------------------
if [[ -d ${EROOT} && ${FORCE_CREATE} != "yes" ]]; then
eerror "Directory ${EROOT} already exists (try -f option). Exitting."
exit 1
fi
mkdir -p ${EROOT}
# Export variables for emerge
export ARCH=${TARCH}
export ACCEPT_KEYWORDS=${EKEYWORDS}
if [[ ${CROSS_COMPILING} = "yes" ]]; then
case ${EELIBC} in
"uclibc") export CHOST="${ECHOST}uclibc";;
"glibc") export CHOST="${ECHOST}gnu";;
*) die "Unknown C library - '${EELIBC}'.";;
esac
export CROSS=${CHOST}-
export CTARGET=${CHOST}
else
# TODO
export CBUILD=${CHOST}
export CTARGET=${CHOST}
export CHOST=${CHOST}
fi
export CFLAGS="-Os -pipe"
export CXXFLAGS=${CFLAGS}
export ROOT=${EROOT}
export FEATURES="-* -distcc ccache nodoc noinfo noman strict"
export CONFIG_PROTECT="-* ${ROOT}/etc"
# This should strip executables of unneeded content
export PORTAGE_STRIP_FLAGS="--strip-unneeded -R .comment"
# This should choose the C library we use
export ELIBC=${EELIBC}
export PORTAGE_LIBC=${ELIBC}
#export PROFILE_ARCH="arm920t"
# These are for uClibc:
export UCLIBC_CPU=${EUCLIBC_CPU}
# Print info
(
einfo "Host Portage ARCH: ${HARCH}"
einfo "Target Portage ARCH: ${TARCH}"
echo
einfo "rootfs location: ${EROOT}"
einfo "Strip rootfs: ${STRIP}"
echo
if [[ ${EMERGE_SYSTEM_PACKAGES} = "yes" ]]; then
einfo "C library: ${LPKG}"
einfo "Baselayout: ${BPKG}"
einfo "System toolset: ${UPKG}"
else
einfo "Skipping system packages"
fi
echo
if [[ -n ${XPKG} ]] ; then
einfo "Extra packages to install: ${XPKG}"
echo
fi
) >& ${PORT_LOGDIR}/rootfsmaker.log || exit 1
cat ${PORT_LOGDIR}/rootfsmaker.log
emerge info >> ${PORT_LOGDIR}/rootfsmaker.log
#Emerge system packages
if [[ ${EMERGE_SYSTEM_PACKAGES} = "yes" ]]; then
# Emerge baselayout
if [[ ${BPKG} == "sys-apps/baselayout-lite" ]] ; then
mkdir -p /etc/portage
grep -qs "baselayout-lite" /etc/portage/package.keywords \
|| echo "sys-apps/baselayout-lite -*" \
>> /etc/portage/package.keywords
fi
doemerge ${BPKG} "baselayout" "-* bootstrap" \
|| die "Could not emerge ${BKPG}"
# Emerge C library
if [[ ${LPKG} = "sys-libs/glibc" ]] ; then
doemerge ${LPKG} libc "userlocales -*" || die "Could emerge
${LPKG}"
else
doemerge ${LPKG} libc "-*" || die "Could emerge ${LPKG}"
fi
# Emerge busybox
doemerge ${UPKG} "utils" "-* static make-symlinks" \
|| die "Could not emerge busybox."
#doemerge "tinylogin" "utils" "-* static make-symlinks" \
# || die "Could not emerge tinylogin."
fi
#Unmerge packages
if [[ -n ${CPKG} ]] ; then
for SINGLE_PACKAGE_UNMERGE in ${CPKG};do
dounmerge ${SINGLE_PACKAGE_UNMERGE} \
|| die "Could not unmerge package
'${SINGLE_PACKAGE_UNMERGE}'."
done
fi
# Emerge extra packages
if [[ -n ${XPKG} ]] ; then
for SINGLE_PACKAGE_MERGE in ${XPKG};do
if [[ ${SINGLE_PACKAGE_MERGE} = "dropbear" ]] ; then
doemerge ${SINGLE_PACKAGE_MERGE} "extra" "-* minimal
multicall static" \
|| die "Could not emerge extra package
'${SINGLE_PACKAGE_MERGE}'."
else
doemerge ${SINGLE_PACKAGE_MERGE} "extra" "-* minimal
multicall" \
|| die "Could not emerge extra package
'${SINGLE_PACKAGE_MERGE}'."
fi
done
fi
# Statistics
echo
einfo "rootfs size: `du -sh ${EROOT}`"
# Stripping the rootfs
if [[ ${STRIP} == "yes" ]] ; then
ebegin "Stripping rootfs"
(
rm -R ${EROOT}/usr/include
rm -R ${EROOT}/usr/share/doc
rm -R ${EROOT}/usr/share/man
rm -R ${EROOT}/tmp/*
rm -R ${EROOT}/var/tmp/*
rm -R ${EROOT}/var/db
rm -R ${EROOT}/var/cache
rm -R ${EROOT}/var/lib/portage
) >& ${PORTAGE_LOGDIR}/rootfsmaker.log \
|| die "Stripping error."
eend 0
einfo "rootfs size: `du -sh ${EROOT}`"
fi
# Finished
echo
einfo "Done. Enjoy your rootfs."
echo