Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
429 lines (357 sloc) 12.1 KB
# Generate cross compile environment for the Raspberry Pi
#
# This is a code generator built using the iMatix GSL code generation
# language. See https://github.com/zeromq/gsl for details.
#
# Copyright (c) the Contributors as noted in the AUTHORS file.
# This file is part of zproject.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
register_target ("rpi", "Raspberry Pi cross build system")
.macro target_rpi
.directory.create('builds/rpi')
.output "builds/rpi/build.sh"
#!/usr/bin/env bash
$(project.GENERATED_WARNING_HEADER:)
# Set this to enable verbose profiling
[ -n "${CI_TIME-}" ] || CI_TIME=""
case "$CI_TIME" in
[Yy][Ee][Ss]|[Oo][Nn]|[Tt][Rr][Uu][Ee])
CI_TIME="time -p " ;;
[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee])
CI_TIME="" ;;
esac
# Set this to enable verbose tracing
[ -n "${CI_TRACE-}" ] || CI_TRACE="no"
case "$CI_TRACE" in
[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee])
set +x ;;
[Yy][Ee][Ss]|[Oo][Nn]|[Tt][Rr][Uu][Ee])
set -x ;;
esac
# Parse parameters
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-i|--incremental)
INCREMENTAL=0
;;
-u|--update)
UPDATE=0
;;
*)
# unknown option
;;
esac
shift # past argument or value
done
if [ $INCREMENTAL ] && [ $UPDATE ]; then
echo Error: Incremental and update are exclusiv!
exit -1
fi
# Download cross compiler and sysroot
if [ ! -d $PWD/tools ]; then
git clone --depth 1 https://github.com/raspberrypi/tools
fi
if [ $UPDATE ]; then
( cd tools && git pull --rebase ) || exit 1
fi
# Cross build for the Raspberry Pi
if [ -d "./tmp" ]; then
# Proto installation area for this project and its deps
rm -rf ./tmp
fi
if [ -d "./tmp-deps" ]; then
# Checkout/unpack and build area for dependencies
rm -rf ./tmp-deps
fi
mkdir -p tmp tmp-deps
BUILD_PREFIX=$PWD/tmp
TOOLCHAIN_HOST="arm-linux-gnueabihf"
TOOLCHAIN_PATH="${PWD}/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin"
SYSROOT=$PWD/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot
CFLAGS="--sysroot=${SYSROOT} -I${BUILD_PREFIX}/include"
CPPFLAGS="--sysroot=${SYSROOT} -I${BUILD_PREFIX}/include"
CXXFLAGS="--sysroot=${SYSROOT} -I${BUILD_PREFIX}/include"
LDFLAGS="-L${BUILD_PREFIX}/lib"
CONFIG_OPTS=()
CONFIG_OPTS+=("CFLAGS=${CFLAGS}")
CONFIG_OPTS+=("CPPFLAGS=${CPPFLAGS}")
CONFIG_OPTS+=("CXXFLAGS=${CXXFLAGS}")
CONFIG_OPTS+=("LDFLAGS=${LDFLAGS}")
CONFIG_OPTS+=("PKG_CONFIG_DIR=")
CONFIG_OPTS+=("PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${SYSROOT}/usr/share/pkgconfig")
CONFIG_OPTS+=("PKG_CONFIG_SYSROOT=${SYSROOT}")
CONFIG_OPTS+=("PKG_CONFIG_PATH=${BUILD_PREFIX}/lib/pkgconfig")
CONFIG_OPTS+=("--prefix=${BUILD_PREFIX}")
CONFIG_OPTS+=("--host=${TOOLCHAIN_HOST}")
CONFIG_OPTS+=("--with-docs=no")
CPP="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-cpp"
CC="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-gcc"
CXX="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-g++"
LD="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ld"
AS="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-as"
AR="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ar"
RANLIB="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ranlib"
CONFIG_OPTS+=("CPP=${CPP}")
CONFIG_OPTS+=("CC=${CC}")
CONFIG_OPTS+=("CXX=${CXX}")
CONFIG_OPTS+=("LD=${LD}")
CONFIG_OPTS+=("AS=${AS}")
CONFIG_OPTS+=("AR=${AR}")
CONFIG_OPTS+=("RANLIB=${RANLIB}")
if [ ! $INCREMENTAL ]; then
# Clone and build dependencies
. for use where defined (use.tarball)
BASE_PWD=${PWD}
cd tmp-deps
if [ ! -e \$(basename "$(use.tarball)") ]; then
$CI_TIME wget $(use.tarball)
tar -xzf \$(basename "$(use.tarball)")
fi
pushd \$(basename "$(use.tarball)" .tar.gz)
(
. if count(use.add_config_opts) > 0
( # Custom additional options for $(use.project)
. for use.add_config_opts as add_cfgopt
CONFIG_OPTS+=("$(add_cfgopt)")
. endfor
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
)
. else
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
. endif
$CI_TIME make -j4
$CI_TIME make install
) || exit 1
popd
cd ${BASE_PWD}
. endfor
. for use where defined (use.repository) & ! defined (use.tarball)
BASE_PWD=${PWD}
cd tmp-deps
if [ ! -e $(use.project) ]; then
. if defined (use.release)
$CI_TIME git clone --quiet --depth 1 -b $(use.release:) $(use.repository) $(use.project)
. else
$CI_TIME git clone --quiet --depth 1 $(use.repository) $(use.project)
. endif
fi
pushd $(use.project)
(
if [ $UPDATE ]; then
$CI_TIME git pull --rebase
fi
git --no-pager log --oneline -n1
if [ -e autogen.sh ]; then
$CI_TIME ./autogen.sh 2> /dev/null
fi
if [ -e buildconf ]; then
$CI_TIME ./buildconf 2> /dev/null
fi
if [ ! -e autogen.sh ] && [ ! -e buildconf ] && [ ! -e ./configure ] && [ -s ./configure.ac ]; then
$CI_TIME libtoolize --copy --force && \\
$CI_TIME aclocal -I . && \\
$CI_TIME autoheader && \\
$CI_TIME automake --add-missing --copy && \\
$CI_TIME autoconf || \\
$CI_TIME autoreconf -fiv
fi
. if count(use.add_config_opts) > 0
( # Custom additional options for $(use.project)
. for use.add_config_opts as add_cfgopt
CONFIG_OPTS+=("$(add_cfgopt)")
. endfor
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
)
. else
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
. endif
$CI_TIME make -j4
$CI_TIME make install
) || exit 1
popd
cd ${BASE_PWD}
. endfor
fi
# Cross build this project
pushd ../..
(
. if count(add_config_opts) > 0
# Custom additional options for this project
. for add_config_opts as add_cfgopt
CONFIG_OPTS+=("$(add_cfgopt)")
. endfor
. endif
$CI_TIME ./autogen.sh 2> /dev/null
$CI_TIME ./configure --enable-drafts=yes "${CONFIG_OPTS[@]}"
$CI_TIME make -j4
$CI_TIME make install
) || exit 1
popd
$(project.GENERATED_WARNING_HEADER:)
.close
.chmod_x ("builds/rpi/build.sh")
.output "builds/rpi/build_image.sh"
#!/usr/bin/env bash
$(project.GENERATED_WARNING_HEADER:)
# Cross compile this project and its dependencies
\./build.sh
# Get the latest Raspbian image and enlarge it so there is enough space to
# install to it.
sudo ./prepare_img.sh
# Sync with image
sudo rsync -avz --no-p --no-g --chmod=ugo=rwX tmp/ raspbian-root/usr
sudo proot -Q qemu-arm -B -r raspbian-root -b raspbian-boot:/boot sudo ldconfig
# Umount image
sync; sudo umount ./raspbian-boot ./raspbian-root
# Make sure all allocated loop devices are free'd
for i in {0..7};
do
sudo sudo dmsetup clear loop${i}p1 &&
sudo sudo dmsetup clear loop${i}p2 &&
sudo sudo dmsetup remove loop${i}p1 &&
sudo sudo dmsetup remove loop${i}p2 &&
sudo sudo losetup -d /dev/loop$i
done
$(project.GENERATED_WARNING_HEADER:)
.close
.chmod_x ("builds/rpi/build_image.sh")
.output("builds/rpi/prepare_img.sh")
#!/usr/bin/env bash
$(project.GENERATED_WARNING_HEADER:)
if [ ! -f $PWD/raspbian_lite_latest.zip ]; then
wget --connect-timeout=10 https://downloads.raspberrypi.org/raspbian_lite_latest -O raspbian_lite_latest.zip
fi
RASPBIAN_IMG=\$(unzip -Z1 raspbian_lite_latest.zip)
if [ ! -f $PWD/$RASPBIAN_IMG ]; then
unzip raspbian_lite_latest.zip
fi
if [ ! -f $PWD/raspbian_$(project.name:c).img ]; then
# Allocate disk space for extended image
truncate -s 1536M raspbian_$(project.name:c).img
# Begin partitioning disk image.
# Creating two partitions:
# BOOT = 100 MB
# ROOT = 1536 MB
fdisk raspbian_$(project.name).img <<EOF
o
n
p
1
+100M
t
c
n
p
2
w
EOF
# Create a loop device and mount the extended image's partitions
export LOOPDEV_EX="\$(losetup --show --find raspbian_$(project.name).img)"
# Use sudo kpartx to create partitions in /dev/mapper
kpartx -av $LOOPDEV_EX
dmsetup --noudevsync mknodes
# Create partition names to mount
export BOOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p1
export ROOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p2
# Create file systems for the partitions
mkfs.vfat $BOOTPARTION_EX
mkfs.ext4 $ROOTPARTION_EX
# Create a loop device and mount the original image's partitions
export LOOPDEV_ORIG="\$(losetup --show --find $RASPBIAN_IMG)"
# Use sudo kpartx to create partitions in /dev/mapper
kpartx -av $LOOPDEV_ORIG
dmsetup --noudevsync mknodes
# Create partition names to mount
export BOOTPARTION_ORIG=\$(echo $LOOPDEV_ORIG | sed 's|'/dev'/|'/dev/mapper/'|')p1
export ROOTPARTION_ORIG=\$(echo $LOOPDEV_ORIG | sed 's|'/dev'/|'/dev/mapper/'|')p2
# Copy data from original image to extended image
dd if=$BOOTPARTION_ORIG of=$BOOTPARTION_EX bs=64K conv=noerror,sync
dd if=$ROOTPARTION_ORIG of=$ROOTPARTION_EX bs=64K conv=noerror,sync
# Remove loop devices for original image
dmsetup clear $BOOTPARTION_ORIG
dmsetup clear $ROOTPARTION_ORIG
dmsetup remove $BOOTPARTION_ORIG
dmsetup remove $ROOTPARTION_ORIG
losetup -d $LOOPDEV_ORIG
fi
# Try to mount extended image
if [ -z "\$(mount|grep raspbian-boot)" ] && [ -z "\$(mount|grep raspbian-root)" ]; then
# Create a loop device and mount the disk image
export LOOPDEV_EX="\$(losetup --show --find ./raspbian_$(project.name).img)"
# Use sudo kpartx to create partitions in /dev/mapper
kpartx -av $LOOPDEV_EX
dmsetup --noudevsync mknodes
# Create partition names to mount
export BOOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p1
export ROOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p2
# Make sure mount points exist and are clean
mkdir -p raspbian-boot
mkdir -p raspbian-root
rm -rf raspbian-boot/*
rm -rf raspbian-root/*
# Mount partitions
mount $BOOTPARTION_EX -t vfat raspbian-boot
mount $ROOTPARTION_EX -t ext4 raspbian-root
else
echo "Image already mounted!"
fi
$(project.GENERATED_WARNING_HEADER:)
.close
.chmod_x ("builds/rpi/prepare_img.sh")
.output "builds/rpi/README.md"
# Raspberry Pi
Cross compile environment for the Raspberry Pi (all models)
## Cross compile for Raspbian
Simply run
./build.sh
Once the build script finishes the installation data is located at `tmp/`.
To copy those files to your Raspberry Pi you can use `rsync`. Therefore
you'll have to make sure rsync is installed on the Raspberry Pi
apt-get install rsync
Next make sure your Pi user has sufficient access rights to copy data to
`/usr/local`. To force this you can use the following command to change
the ownership of the directory accordingly.
chown -R root:users /usr/local/
And finally sync your libraries to the Pi
rsync -avz tmp/ <pi-user>@<pi-ip>:/usr/local
The first time you install a library onto the Raspberry Pi you'll need to run
sudo ldconfig
During development running the build script with all dependencies just to test
a minor change is overkill. To run an incremental build use the option
`-i|--incremental` which will only build this project.
./build.sh --incremental
Once in a while you might want to update the dependencies. You can do this by
adding the option `-u|--update`.
./build.sh --update
Note that incremental and update are exclusiv options.
## Cross compile and install to Raspbian image
This requires sudo access rights on your local maschine. Also make sure
you have `kpartx`, `qemu-user` and `proot` installed.
To cross compile and install this project to an raspbian image run
./build_image.sh
This script will download the latest Raspbian image extend it so we can install
software into it and finally copy the cross compiled stuff to it. Once it's done
simple copy the image to a SD card and plug it into your Raspberry Pi.
```
$(project.GENERATED_WARNING_HEADER:)
```
.close
.output "builds/rpi/.gitignore"
. for use where defined (use.tarball)
$(use.project)*
. endfor
. for use where defined (use.repository) & ! defined (use.tarball)
$(use.project)
. endfor
raspbian-boot
raspbian-root
tmp/
tools/
*.img
*.zip
.close
.endmacro