Support emulation of an ARM environment on Intel systems.

qemu-user is used to emulate an ARM chroot environment
that is used to compile the system for ARM target systems.
This commit is contained in:
Michael Tremer
2014-05-24 17:18:13 +02:00
parent 3d02c09165
commit bcb9dc13d7
2 changed files with 216 additions and 32 deletions

29
make.sh
View File

@@ -34,16 +34,13 @@ NICE=10 # Nice level
MAX_RETRIES=1 # prefetch/check loop
BUILD_IMAGES=1 # Flash and Xen Downloader
KVER=`grep --max-count=1 VER lfs/linux | awk '{ print $3 }'`
MACHINE=`uname -m`
GIT_TAG=$(git tag | tail -1) # Git Tag
GIT_LASTCOMMIT=$(git log | head -n1 | cut -d" " -f2 |head -c8) # Last commit
TOOLCHAINVER=7
BUILDMACHINE=$MACHINE
if [ "$MACHINE" = "x86_64" ]; then
BUILDMACHINE="i686";
fi
# New architecture variables
BUILD_ARCH="$(uname -m)"
BUILDMACHINE="${BUILD_ARCH}"
# Debian specific settings
if [ ! -e /etc/debian_version ]; then
@@ -68,6 +65,8 @@ mkdir $BASEDIR/log/ 2>/dev/null
# Include funtions
. tools/make-functions
configure_target "default"
if [ -f .config ]; then
. .config
fi
@@ -241,7 +240,7 @@ prepareenv() {
buildtoolchain() {
local error=false
case "${MACHINE}:$(uname -m)" in
case "${TARGET_ARCH}:${BUILD_ARCH}" in
# x86
i586:i586|i586:i686|i586:x86_64)
# These are working.
@@ -898,6 +897,22 @@ ipfirepackages() {
rm -rf $BASEDIR/build/install/packages/*
}
while [ $# -gt 0 ]; do
case "${1}" in
--target=*)
configure_target "${1#--target=}"
;;
-*)
exiterror "Unknown configuration option: ${1}"
;;
*)
# Found a command, so exit options parsing.
break
;;
esac
shift
done
# See what we're supposed to do
case "$1" in
build)

View File

@@ -60,6 +60,69 @@ WARN="\\033[1;35m"
FAIL="\\033[1;31m"
NORMAL="\\033[0;39m"
configure_target() {
local target_arch="${1}"
if [ "${target_arch}" = "default" ]; then
target_arch="$(configure_target_guess)"
fi
case "${target_arch}" in
i586)
BUILDTARGET="${TARGET_ARCH}-pc-linux-gnu"
CROSSTARGET="${BUILD_ARCH}-cross-linux-gnu"
CFLAGS_ARCH="-march=i586 -fomit-frame-pointer"
;;
armv5tel)
BUILDTARGET="${TARGET_ARCH}-unknown-linux-gnueabi"
CROSSTARGET="${BUILD_ARCH}-cross-linux-gnueabi"
CFLAGS_ARCH="-march=armv5te -mfloat-abi=soft -fomit-frame-pointer"
MACHINE_TYPE="arm"
;;
*)
exiterror "Cannot build for architure ${target_arch}"
;;
esac
# Check if the QEMU helper is available if needed.
if qemu_is_required "${target_arch}"; then
local qemu_target_helper="$(qemu_find_target_helper_name "${target_arch}")"
if [ -n "${qemu_target_helper}" ]; then
QEMU_TARGET_HELPER="${qemu_target_helper}"
else
exiterror "Could not find a binfmt_misc helper entry for ${target_arch}"
fi
fi
TARGET_ARCH="${target_arch}"
# Old variable names
MACHINE="${TARGET_ARCH}"
CFLAGS="-O2 -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fPIC"
CFLAGS="${CFLAGS} -fstack-protector-all --param=ssp-buffer-size=4 ${CFLAGS_ARCH}"
CXXFLAGS="${CFLAGS}"
C2FLAGS="${CFLAGS}"
CXX2FLAGS="${CXXFLAGS}"
}
configure_target_guess() {
case "${BUILD_ARCH}" in
x86_64|i686|i586)
echo "i586"
;;
armv7*|armv6*|armv5*)
echo "armv5tel"
;;
*)
exiterror "Cannot guess target architecture"
;;
esac
}
evaluate() {
if [ "$?" -eq "0" ]; then
beautify message DONE
@@ -217,30 +280,6 @@ get_pkg_ver()
echo "$PKG_VER"
} # End of get_pkg_ver()
if [ 'x86_64' = $MACHINE -o 'i686' = $MACHINE -o 'i586' = $MACHINE ]; then
echo "`date -u '+%b %e %T'`: Machine is iX86 (or equivalent)" >> $LOGFILE
MACHINE=i586
CROSSTARGET=${MACHINE}-cross-linux-gnu
BUILDTARGET=i586-pc-linux-gnu
CFLAGS_ARCH="${GLOBAL_CFLAGS} -march=i586 -fomit-frame-pointer"
elif [ 'armv5tejl' = $MACHINE -o 'armv5tel' = $MACHINE -o 'armv6l' = $MACHINE -o 'armv7l' = $MACHINE ]; then
echo "`date -u '+%b %e %T'`: Machine is ARM (or equivalent)" >> $LOGFILE
MACHINE=armv5tel
MACHINE_TYPE=arm
CROSSTARGET=${MACHINE}-cross-linux-gnueabi
BUILDTARGET=${MACHINE}-unknown-linux-gnueabi
CFLAGS_ARCH="-march=armv5te -mfloat-abi=soft -fomit-frame-pointer"
else
echo "`date -u '+%b %e %T'`: Can't determine your architecture - $MACHINE"
exit 1
fi
CFLAGS="-O2 -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fPIC"
CFLAGS="${CFLAGS} -fstack-protector-all --param=ssp-buffer-size=4 ${CFLAGS_ARCH}"
CXXFLAGS="${CFLAGS}"
C2FLAGS="${CFLAGS}"
CXX2FLAGS="${CXXFLAGS}"
# Define immediately
stdumount() {
umount $BASEDIR/build/sys 2>/dev/null;
@@ -282,16 +321,130 @@ fake_environ() {
env="${env} UTS_RELEASE=${KVER}"
# Fake machine version.
env="${env} UTS_MACHINE=${MACHINE}"
env="${env} UTS_MACHINE=${TARGET_ARCH}"
echo "${env}"
}
qemu_environ() {
local env
# Don't add anything if qemu is not used.
if ! qemu_is_required; then
return
fi
# Set default qemu options
case "${TARGET_ARCH}" in
arm*)
QEMU_CPU="${QEMU_CPU:-cortex-a9}"
env="${env} QEMU_CPU=${QEMU_CPU}"
;;
esac
# Enable QEMU strace
#env="${env} QEMU_STRACE=1"
echo "${env}"
}
qemu_is_required() {
local target_arch="${1}"
if [ -z "${target_arch}" ]; then
target_arch="${TARGET_ARCH}"
fi
case "${BUILD_ARCH},${target_arch}" in
x86_64,arm*|i?86,arm*)
return 0
;;
*)
return 1
;;
esac
}
qemu_install_helper() {
# Do nothing, if qemu is not required
if ! qemu_is_required; then
return 0
fi
if [ -z "${QEMU_TARGET_HELPER}" ]; then
exiterror "QEMU_TARGET_HELPER not set"
fi
# Check if the helper is already installed.
if [ -x "${LFS}${QEMU_TARGET_HELPER}" ]; then
return 0
fi
# Try to find a suitable binary that we can install
# to the build environment.
local file
for file in "${QEMU_TARGET_HELPER}" "${QEMU_TARGET_HELPER}-static"; do
# file must exist and be executable.
[ -x "${file}" ] || continue
# Must be static.
file_is_static "${file}" || continue
local dirname="${LFS}$(dirname "${file}")"
mkdir -p "${dirname}"
install -m 755 "${file}" "${LFS}${QEMU_TARGET_HELPER}"
return 0
done
exiterror "Could not find a statically-linked QEMU emulator: ${QEMU_TARGET_HELPER}"
}
qemu_find_target_helper_name() {
local target_arch="${1}"
local magic
case "${target_arch}" in
arm*)
magic="7f454c4601010100000000000000000002002800"
;;
esac
[ -z "${magic}" ] && return 1
local file
for file in /proc/sys/fs/binfmt_misc/*; do
# Search for the file with the correct magic value.
grep -qE "^magic ${magic}$" "${file}" || continue
local interpreter="$(grep "^interpreter" "${file}" | awk '{ print $2 }')"
[ -n "${interpreter}" ] || continue
[ "${interpreter:0:1}" = "/" ] || continue
[ -x "${interpreter}" ] || continue
echo "${interpreter}"
return 0
done
return 1
}
file_is_static() {
local file="${1}"
file ${file} 2>/dev/null | grep -q "statically linked"
}
entershell() {
if [ ! -e $BASEDIR/build/usr/src/lfs/ ]; then
exiterror "No such file or directory: $BASEDIR/build/usr/src/lfs/"
fi
# Install QEMU helper, if needed
qemu_install_helper
echo "Entering to a shell inside LFS chroot, go out with exit"
chroot $LFS /tools/bin/env -i HOME=/root TERM=$TERM PS1='\u:\w\$ ' \
PATH=/tools/ccache/bin:/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
@@ -308,6 +461,7 @@ entershell() {
MACHINE_TYPE="$MACHINE_TYPE" \
KGCC="ccache /usr/bin/gcc" \
$(fake_environ) \
$(qemu_environ) \
/tools/bin/bash
if [ $? -ne 0 ]; then
beautify message FAIL
@@ -410,6 +564,9 @@ lfsmake2() {
lfsmakecommoncheck $*
[ $? == 1 ] && return 0
# Install QEMU helper, if needed
qemu_install_helper
local PKG_TIME_START=`date +%s`
chroot $LFS /tools/bin/env -i HOME=/root \
TERM=$TERM PS1='\u:\w\$ ' \
@@ -426,6 +583,7 @@ lfsmake2() {
CROSSTARGET="${CROSSTARGET}" \
MACHINE="$MACHINE" \
MACHINE_TYPE="$MACHINE_TYPE" \
$(qemu_environ) \
$(fake_environ) \
/tools/bin/bash -x -c "cd /usr/src/lfs && \
make -f $* LFS_BASEDIR=/usr/src install" >>$LOGFILE 2>&1
@@ -446,6 +604,9 @@ ipfiremake() {
lfsmakecommoncheck $*
[ $? == 1 ] && return 0
# Install QEMU helper, if needed
qemu_install_helper
local PKG_TIME_START=`date +%s`
chroot $LFS /tools/bin/env -i HOME=/root \
TERM=$TERM PS1='\u:\w\$ ' \
@@ -463,6 +624,7 @@ ipfiremake() {
CROSSTARGET="${CROSSTARGET}" \
MACHINE="$MACHINE" \
MACHINE_TYPE="$MACHINE_TYPE" \
$(qemu_environ) \
$(fake_environ) \
/bin/bash -x -c "cd /usr/src/lfs && \
make -f $* LFS_BASEDIR=/usr/src install" >>$LOGFILE 2>&1
@@ -483,6 +645,9 @@ ipfiredist() {
lfsmakecommoncheck $*
[ $? == 1 ] && return 0
# Install QEMU helper, if needed
qemu_install_helper
local PKG_TIME_START=`date +%s`
chroot $LFS /tools/bin/env -i HOME=/root \
TERM=$TERM PS1='\u:\w\$ ' \
@@ -498,6 +663,7 @@ ipfiredist() {
CROSSTARGET="${CROSSTARGET}" \
MACHINE="$MACHINE" \
MACHINE_TYPE="$MACHINE_TYPE" \
$(qemu_environ) \
$(fake_environ) \
/bin/bash -x -c "cd /usr/src/lfs && \
make -f $1 LFS_BASEDIR=/usr/src dist" >>$LOGFILE 2>&1
@@ -518,6 +684,9 @@ installmake() {
lfsmakecommoncheck $*
[ $? == 1 ] && return 0
# Install QEMU helper, if needed
qemu_install_helper
local PKG_TIME_START=`date +%s`
chroot $LFS /tools/bin/env -i HOME=/root \
TERM=$TERM PS1='\u:\w\$ ' \