sudo is useless here as we are running as root already, and it may be missing in some minimal configurations (like Docker and VM images)
700 lines
26 KiB
Bash
700 lines
26 KiB
Bash
# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
|
|
#
|
|
# This file is licensed under the terms of the GNU General Public
|
|
# License version 2. This program is licensed "as is" without any
|
|
# warranty of any kind, whether express or implied.
|
|
|
|
# This file is a part of the Armbian build script
|
|
# https://github.com/armbian/build/
|
|
|
|
# Functions:
|
|
# cleaning
|
|
# exit_with_error
|
|
# get_package_list_hash
|
|
# create_sources_list
|
|
# fetch_from_repo
|
|
# display_alert
|
|
# fingerprint_image
|
|
# addtorepo
|
|
# prepare_host
|
|
# download_toolchain
|
|
|
|
# cleaning <target>
|
|
#
|
|
# target: what to clean
|
|
# "make" - "make clean" for selected kernel and u-boot
|
|
# "debs" - delete output/debs
|
|
# "cache" - delete output/cache
|
|
# "images" - delete output/images
|
|
# "sources" - delete output/sources
|
|
#
|
|
cleaning()
|
|
{
|
|
case $1 in
|
|
debs) # delete output/debs for current branch and family
|
|
if [[ -d $DEST/debs ]]; then
|
|
display_alert "Cleaning output/debs for" "$BOARD $BRANCH" "info"
|
|
# easier than dealing with variable expansion and escaping dashes in file names
|
|
find $DEST/debs -name "${CHOSEN_UBOOT}_*.deb" -delete
|
|
find $DEST/debs \( -name "${CHOSEN_KERNEL}_*.deb" -o \
|
|
-name "${CHOSEN_KERNEL/image/dtb}_*.deb" -o \
|
|
-name "${CHOSEN_KERNEL/image/headers}_*.deb" -o \
|
|
-name "${CHOSEN_KERNEL/image/source}_*.deb" -o \
|
|
-name "${CHOSEN_KERNEL/image/firmware-image}_*.deb" \) -delete
|
|
[[ -n $RELEASE ]] && rm -f $DEST/debs/$RELEASE/${CHOSEN_ROOTFS}_*.deb
|
|
fi
|
|
;;
|
|
|
|
extras) # delete output/debs/extra/$RELEASE for all architectures
|
|
if [[ -n $RELEASE && -d $DEST/debs/extra/$RELEASE ]]; then
|
|
display_alert "Cleaning output/debs/extra for" "$RELEASE" "info"
|
|
rm -rf $DEST/debs/extra/$RELEASE
|
|
fi
|
|
;;
|
|
|
|
alldebs) # delete output/debs
|
|
[[ -d $DEST/debs ]] && display_alert "Cleaning" "output/debs" "info" && rm -rf $DEST/debs/*
|
|
;;
|
|
|
|
cache) # delete output/cache
|
|
[[ -d $SRC/cache/rootfs ]] && display_alert "Cleaning" "rootfs cache (all)" "info" && find $SRC/cache/rootfs -type f -delete
|
|
;;
|
|
|
|
images) # delete output/images
|
|
[[ -d $DEST/images ]] && display_alert "Cleaning" "output/images" "info" && rm -rf $DEST/images/*
|
|
;;
|
|
|
|
sources) # delete output/sources and output/buildpkg
|
|
[[ -d $SRC/cache/sources ]] && display_alert "Cleaning" "sources" "info" && rm -rf $SRC/cache/sources/* $DEST/buildpkg/*
|
|
;;
|
|
|
|
oldcache)
|
|
if [[ -d $SRC/cache/rootfs && $(ls -1 $SRC/cache/rootfs | wc -l) -gt 6 ]]; then
|
|
display_alert "Cleaning" "rootfs cache (old)" "info"
|
|
(cd $SRC/cache/rootfs; ls -t | sed -e "1,${ROOTFS_CACHE_MAX}d" | xargs -d '\n' rm -f)
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# exit_with_error <message> <highlight>
|
|
#
|
|
# a way to terminate build process
|
|
# with verbose error message
|
|
#
|
|
|
|
exit_with_error()
|
|
{
|
|
local _file=$(basename ${BASH_SOURCE[1]})
|
|
local _line=${BASH_LINENO[0]}
|
|
local _function=${FUNCNAME[1]}
|
|
local _description=$1
|
|
local _highlight=$2
|
|
|
|
display_alert "ERROR in function $_function" "$_file:$_line" "err"
|
|
display_alert "$_description" "$_highlight" "err"
|
|
display_alert "Process terminated" "" "info"
|
|
# TODO: execute run_after_build here?
|
|
overlayfs_wrapper "cleanup"
|
|
# unlock loop device access in case of starvation
|
|
exec {FD}>/var/lock/armbian-debootstrap-losetup
|
|
flock -u $FD
|
|
|
|
exit -1
|
|
}
|
|
|
|
# get_package_list_hash
|
|
#
|
|
# returns md5 hash for current package list and rootfs cache version
|
|
|
|
get_package_list_hash()
|
|
{
|
|
( printf '%s\n' $PACKAGE_LIST | sort -u; printf '%s\n' $PACKAGE_LIST_EXCLUDE | sort -u; echo "$ROOTFSCACHE_VERSION" ) \
|
|
| md5sum | cut -d' ' -f 1
|
|
}
|
|
|
|
# create_sources_list <release> <basedir>
|
|
#
|
|
# <release>: jessie|stretch|xenial
|
|
# <basedir>: path to root directory
|
|
#
|
|
create_sources_list()
|
|
{
|
|
local release=$1
|
|
local basedir=$2
|
|
[[ -z $basedir ]] && exit_with_error "No basedir passed to create_sources_list"
|
|
|
|
case $release in
|
|
jessie|stretch)
|
|
cat <<-EOF > $basedir/etc/apt/sources.list
|
|
deb http://${DEBIAN_MIRROR} $release main contrib non-free
|
|
#deb-src http://${DEBIAN_MIRROR} $release main contrib non-free
|
|
|
|
deb http://${DEBIAN_MIRROR} ${release}-updates main contrib non-free
|
|
#deb-src http://${DEBIAN_MIRROR} ${release}-updates main contrib non-free
|
|
|
|
deb http://${DEBIAN_MIRROR} ${release}-backports main contrib non-free
|
|
#deb-src http://${DEBIAN_MIRROR} ${release}-backports main contrib non-free
|
|
|
|
deb http://security.debian.org/ ${release}/updates main contrib non-free
|
|
#deb-src http://security.debian.org/ ${release}/updates main contrib non-free
|
|
EOF
|
|
;;
|
|
|
|
xenial)
|
|
cat <<-EOF > $basedir/etc/apt/sources.list
|
|
deb http://${UBUNTU_MIRROR} $release main restricted universe multiverse
|
|
#deb-src http://${UBUNTU_MIRROR} $release main restricted universe multiverse
|
|
|
|
deb http://${UBUNTU_MIRROR} ${release}-security main restricted universe multiverse
|
|
#deb-src http://${UBUNTU_MIRROR} ${release}-security main restricted universe multiverse
|
|
|
|
deb http://${UBUNTU_MIRROR} ${release}-updates main restricted universe multiverse
|
|
#deb-src http://${UBUNTU_MIRROR} ${release}-updates main restricted universe multiverse
|
|
|
|
deb http://${UBUNTU_MIRROR} ${release}-backports main restricted universe multiverse
|
|
#deb-src http://${UBUNTU_MIRROR} ${release}-backports main restricted universe multiverse
|
|
EOF
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# fetch_from_repo <url> <directory> <ref> <ref_subdir>
|
|
# <url>: remote repository URL
|
|
# <directory>: local directory; subdir for branch/tag will be created
|
|
# <ref>:
|
|
# branch:name
|
|
# tag:name
|
|
# head(*)
|
|
# commit:hash@depth(**)
|
|
#
|
|
# *: Implies ref_subdir=no
|
|
# **: Not implemented yet
|
|
# <ref_subdir>: "yes" to create subdirectory for tag or branch name
|
|
#
|
|
fetch_from_repo()
|
|
{
|
|
local url=$1
|
|
local dir=$2
|
|
local ref=$3
|
|
local ref_subdir=$4
|
|
|
|
[[ -z $ref || ( $ref != tag:* && $ref != branch:* && $ref != head ) ]] && exit_with_error "Error in configuration"
|
|
local ref_type=${ref%%:*}
|
|
if [[ $ref_type == head ]]; then
|
|
local ref_name=HEAD
|
|
else
|
|
local ref_name=${ref##*:}
|
|
fi
|
|
|
|
display_alert "Checking git sources" "$dir $ref_name" "info"
|
|
|
|
# get default remote branch name without cloning
|
|
# local ref_name=$(git ls-remote --symref $url HEAD | grep -o 'refs/heads/\S*' | sed 's%refs/heads/%%')
|
|
# for git:// protocol comparing hashes of "git ls-remote -h $url" and "git ls-remote --symref $url HEAD" is needed
|
|
|
|
if [[ $ref_subdir == yes ]]; then
|
|
local workdir=$dir/$ref_name
|
|
else
|
|
local workdir=$dir
|
|
fi
|
|
mkdir -p $SRC/cache/sources/$workdir
|
|
cd $SRC/cache/sources/$workdir
|
|
|
|
# check if existing remote URL for the repo or branch does not match current one
|
|
# may not be supported by older git versions
|
|
local current_url=$(git remote get-url origin 2>/dev/null)
|
|
if [[ -n $current_url && $(git rev-parse --is-inside-work-tree 2>/dev/null) == true && \
|
|
$(git rev-parse --show-toplevel) == $(pwd) && \
|
|
$current_url != $url ]]; then
|
|
display_alert "Remote URL does not match, removing existing local copy"
|
|
rm -rf .git *
|
|
fi
|
|
|
|
if [[ $(git rev-parse --is-inside-work-tree 2>/dev/null) != true || \
|
|
$(git rev-parse --show-toplevel) != $(pwd) ]]; then
|
|
display_alert "Creating local copy"
|
|
git init -q .
|
|
git remote add origin $url
|
|
fi
|
|
|
|
local changed=false
|
|
|
|
local local_hash=$(git rev-parse @ 2>/dev/null)
|
|
case $ref_type in
|
|
branch)
|
|
# TODO: grep refs/heads/$name
|
|
local remote_hash=$(git ls-remote -h $url "$ref_name" | head -1 | cut -f1)
|
|
[[ -z $local_hash || $local_hash != $remote_hash ]] && changed=true
|
|
;;
|
|
|
|
tag)
|
|
local remote_hash=$(git ls-remote -t $url "$ref_name" | cut -f1)
|
|
if [[ -z $local_hash || $local_hash != $remote_hash ]]; then
|
|
remote_hash=$(git ls-remote -t $url "$ref_name^{}" | cut -f1)
|
|
[[ -z $remote_hash || $local_hash != $remote_hash ]] && changed=true
|
|
fi
|
|
;;
|
|
|
|
head)
|
|
local remote_hash=$(git ls-remote $url HEAD | cut -f1)
|
|
[[ -z $local_hash || $local_hash != $remote_hash ]] && changed=true
|
|
;;
|
|
esac
|
|
|
|
if [[ $changed == true ]]; then
|
|
# remote was updated, fetch and check out updates
|
|
display_alert "Fetching updates"
|
|
case $ref_type in
|
|
branch) git fetch --depth 1 origin $ref_name ;;
|
|
tag) git fetch --depth 1 origin tags/$ref_name ;;
|
|
head) git fetch --depth 1 origin HEAD ;;
|
|
esac
|
|
display_alert "Checking out"
|
|
git checkout -f -q FETCH_HEAD
|
|
elif [[ -n $(git status -uno --porcelain --ignore-submodules=all) ]]; then
|
|
# working directory is not clean
|
|
if [[ $FORCE_CHECKOUT == yes ]]; then
|
|
display_alert "Checking out"
|
|
git checkout -f -q HEAD
|
|
else
|
|
display_alert "Skipping checkout"
|
|
fi
|
|
else
|
|
# working directory is clean, nothing to do
|
|
display_alert "Up to date"
|
|
fi
|
|
if [[ -f .gitmodules ]]; then
|
|
display_alert "Updating submodules" "" "ext"
|
|
# FML: http://stackoverflow.com/a/17692710
|
|
for i in $(git config -f .gitmodules --get-regexp path | awk '{ print $2 }'); do
|
|
cd $SRC/cache/sources/$workdir
|
|
local surl=$(git config -f .gitmodules --get "submodule.$i.url")
|
|
local sref=$(git config -f .gitmodules --get "submodule.$i.branch")
|
|
if [[ -n $sref ]]; then
|
|
sref="branch:$sref"
|
|
else
|
|
sref="head"
|
|
fi
|
|
fetch_from_repo "$surl" "$workdir/$i" "$sref"
|
|
done
|
|
fi
|
|
} #############################################################################
|
|
|
|
display_alert()
|
|
#--------------------------------------------------------------------------------------------------------------------------------
|
|
# Let's have unique way of displaying alerts
|
|
#--------------------------------------------------------------------------------------------------------------------------------
|
|
{
|
|
# log function parameters to install.log
|
|
[[ -n $DEST ]] && echo "Displaying message: $@" >> $DEST/debug/output.log
|
|
|
|
local tmp=""
|
|
[[ -n $2 ]] && tmp="[\e[0;33m $2 \x1B[0m]"
|
|
|
|
case $3 in
|
|
err)
|
|
echo -e "[\e[0;31m error \x1B[0m] $1 $tmp"
|
|
;;
|
|
|
|
wrn)
|
|
echo -e "[\e[0;35m warn \x1B[0m] $1 $tmp"
|
|
;;
|
|
|
|
ext)
|
|
echo -e "[\e[0;32m o.k. \x1B[0m] \e[1;32m$1\x1B[0m $tmp"
|
|
;;
|
|
|
|
info)
|
|
echo -e "[\e[0;32m o.k. \x1B[0m] $1 $tmp"
|
|
;;
|
|
|
|
*)
|
|
echo -e "[\e[0;32m .... \x1B[0m] $1 $tmp"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
fingerprint_image()
|
|
{
|
|
#--------------------------------------------------------------------------------------------------------------------------------
|
|
# Saving build summary to the image
|
|
#--------------------------------------------------------------------------------------------------------------------------------
|
|
display_alert "Fingerprinting"
|
|
cat <<-EOF > $1
|
|
--------------------------------------------------------------------------------
|
|
Title: Armbian $REVISION ${BOARD^} $DISTRIBUTION $RELEASE $BRANCH
|
|
Kernel: Linux $VER
|
|
Build date: $(date +'%d.%m.%Y')
|
|
Authors: https://www.armbian.com/authors
|
|
Sources: https://github.com/armbian/
|
|
Support: https://forum.armbian.com/
|
|
Changelog: https://www.armbian.com/logbook/
|
|
Documantation: https://docs.armbian.com/
|
|
--------------------------------------------------------------------------------
|
|
$(cat $SRC/LICENSE)
|
|
--------------------------------------------------------------------------------
|
|
EOF
|
|
}
|
|
|
|
addtorepo()
|
|
{
|
|
# add all deb files to repository
|
|
# parameter "remove" dumps all and creates new
|
|
# function: cycle trough distributions
|
|
local distributions=("jessie" "xenial" "stretch")
|
|
|
|
for release in "${distributions[@]}"; do
|
|
|
|
# let's drop from publish if exits
|
|
if [[ -n $(aptly publish list -config=../config/aptly.conf -raw | awk '{print $(NF)}' | grep $release) ]]; then
|
|
aptly publish drop -config=../config/aptly.conf $release > /dev/null 2>&1
|
|
fi
|
|
|
|
|
|
if [[ $1 == remove ]]; then
|
|
# remove repository
|
|
aptly repo drop -config=../config/aptly.conf $release > /dev/null 2>&1
|
|
aptly db cleanup -config=../config/aptly.conf > /dev/null 2>&1
|
|
fi
|
|
|
|
|
|
if [[ $1 == replace ]]; then
|
|
local replace=true
|
|
else
|
|
local replace=false
|
|
fi
|
|
|
|
|
|
# create local repository if not exist
|
|
if [[ -z $(aptly repo list -config=../config/aptly.conf -raw | awk '{print $(NF)}' | grep $release) ]]; then
|
|
display_alert "Creating section" "$release" "info"
|
|
aptly repo create -config=../config/aptly.conf -distribution=$release -component="main" \
|
|
-comment="Armbian main repository" ${release}
|
|
fi
|
|
if [[ -z $(aptly repo list -config=../config/aptly.conf -raw | awk '{print $(NF)}' | grep "^utils") ]]; then
|
|
aptly repo create -config=../config/aptly.conf -distribution=$release -component="utils" \
|
|
-comment="Armbian utilities (backwards compatibility)" utils
|
|
fi
|
|
if [[ -z $(aptly repo list -config=../config/aptly.conf -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
|
|
aptly repo create -config=../config/aptly.conf -distribution=$release -component="${release}-utils" \
|
|
-comment="Armbian ${release} utilities" ${release}-utils
|
|
fi
|
|
if [[ -z $(aptly repo list -config=../config/aptly.conf -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
|
|
aptly repo create -config=../config/aptly.conf -distribution=$release -component="${release}-desktop" \
|
|
-comment="Armbian ${release} desktop" ${release}-desktop
|
|
fi
|
|
|
|
|
|
# adding main
|
|
if find $POT -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
|
|
display_alert "Adding to repository $release" "main" "ext"
|
|
aptly repo add -force-replace=$replace -config=../config/aptly.conf $release $POT/*.deb
|
|
else
|
|
display_alert "Not adding $release" "main" "wrn"
|
|
fi
|
|
|
|
local COMPONENTS="main"
|
|
|
|
# adding main distribution packages
|
|
if find ${POT}${release} -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
|
|
display_alert "Adding to repository $release" "root" "ext"
|
|
aptly repo add -force-replace=$replace -config=../config/aptly.conf $release ${POT}${release}/*.deb
|
|
else
|
|
display_alert "Not adding $release" "root" "wrn"
|
|
fi
|
|
|
|
# adding old utils and new jessie-utils for backwards compatibility with older images
|
|
if find ${POT}extra/jessie-utils -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
|
|
display_alert "Adding to repository $release" "utils" "ext"
|
|
aptly repo add -config=../config/aptly.conf "utils" ${POT}extra/jessie-utils/*.deb
|
|
COMPONENTS="${COMPONENTS} utils"
|
|
else
|
|
display_alert "Not adding $release" "utils" "wrn"
|
|
fi
|
|
|
|
# adding release-specific utils
|
|
if find ${POT}extra/${release}-utils -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
|
|
display_alert "Adding to repository $release" "${release}-utils" "ext"
|
|
aptly repo add -config=../config/aptly.conf "${release}-utils" ${POT}extra/${release}-utils/*.deb
|
|
COMPONENTS="${COMPONENTS} ${release}-utils"
|
|
else
|
|
display_alert "Not adding $release" "${release}-utils" "wrn"
|
|
fi
|
|
|
|
# adding desktop
|
|
if find ${POT}extra/${release}-desktop -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
|
|
display_alert "Adding to repository $release" "desktop" "ext"
|
|
aptly repo add -force-replace=$replace -config=../config/aptly.conf "${release}-desktop" ${POT}extra/${release}-desktop/*.deb
|
|
COMPONENTS="${COMPONENTS} ${release}-desktop"
|
|
else
|
|
display_alert "Not adding $release" "desktop" "wrn"
|
|
fi
|
|
|
|
# publish
|
|
aptly publish -passphrase=$GPG_PASS -origin=Armbian -label=Armbian -config=../config/aptly.conf -component=${COMPONENTS// /,} \
|
|
--distribution=$release repo $release ${COMPONENTS//main/} 2>/dev/null
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
display_alert "Publishing failed" "$release" "err"
|
|
exit 0
|
|
fi
|
|
done
|
|
display_alert "List of local repos" "local" "info"
|
|
(aptly repo list -config=../config/aptly.conf) | egrep packages
|
|
# serve
|
|
# aptly -config=../config/aptly.conf -listen=":8189" serve
|
|
}
|
|
|
|
# prepare_host
|
|
#
|
|
# * checks and installs necessary packages
|
|
# * creates directory structure
|
|
# * changes system settings
|
|
#
|
|
prepare_host()
|
|
{
|
|
display_alert "Preparing" "host" "info"
|
|
|
|
if [[ $(dpkg --print-architecture) == arm* ]]; then
|
|
display_alert "Please read documentation to set up proper compilation environment"
|
|
display_alert "http://www.armbian.com/using-armbian-tools/"
|
|
exit_with_error "Running this tool on board itself is not supported"
|
|
fi
|
|
|
|
if [[ $(dpkg --print-architecture) == i386 ]]; then
|
|
display_alert "Please read documentation to set up proper compilation environment"
|
|
display_alert "http://www.armbian.com/using-armbian-tools/"
|
|
display_alert "Running this tool on non-x64 build host in not supported officially" "" "wrn"
|
|
fi
|
|
|
|
# dialog may be used to display progress
|
|
if [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' dialog 2>/dev/null) != *ii* ]]; then
|
|
display_alert "Installing package" "dialog"
|
|
apt-get install -qq -y --no-install-recommends dialog >/dev/null 2>&1
|
|
fi
|
|
|
|
# need lsb_release to decide what to install
|
|
if [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' lsb-release 2>/dev/null) != *ii* ]]; then
|
|
display_alert "Installing package" "lsb-release"
|
|
apt-get install -qq -y --no-install-recommends lsb-release >/dev/null 2>&1
|
|
fi
|
|
|
|
# packages list for host
|
|
# NOTE: please sync any changes here with the Dockerfile and Vagrantfile
|
|
local hostdeps="wget ca-certificates device-tree-compiler pv bc lzop zip binfmt-support build-essential ccache debootstrap ntpdate \
|
|
gawk gcc-arm-linux-gnueabihf qemu-user-static u-boot-tools uuid-dev zlib1g-dev unzip libusb-1.0-0-dev fakeroot \
|
|
parted pkg-config libncurses5-dev whiptail debian-keyring debian-archive-keyring f2fs-tools libfile-fcntllock-perl rsync libssl-dev \
|
|
nfs-kernel-server btrfs-tools ncurses-term p7zip-full kmod dosfstools libc6-dev-armhf-cross \
|
|
curl patchutils python liblz4-tool libpython2.7-dev linux-base swig libpython-dev \
|
|
locales ncurses-base pixz"
|
|
|
|
local codename=$(lsb_release -sc)
|
|
display_alert "Build host OS release" "${codename:-(unknown)}" "info"
|
|
if [[ -z $codename || "trusty xenial" != *"$codename"* ]]; then
|
|
exit_with_error "It seems you ignore documentation and run an unsupported build system: ${codename:-(unknown)}"
|
|
fi
|
|
|
|
if [[ $codename == xenial ]]; then
|
|
hostdeps="$hostdeps systemd-container udev distcc \
|
|
lib32stdc++6 libc6-i386 lib32ncurses5 lib32tinfo5 aptly"
|
|
grep -q i386 <(dpkg --print-foreign-architectures) || dpkg --add-architecture i386
|
|
if systemd-detect-virt -q -c; then
|
|
display_alert "Running in container" "$(systemd-detect-virt)" "info"
|
|
# disable apt-cacher unless NO_APT_CACHER=no is not specified explicitly
|
|
if [[ $NO_APT_CACHER != no ]]; then
|
|
display_alert "apt-cacher is disabled in containers, set NO_APT_CACHER=no to override" "" "wrn"
|
|
NO_APT_CACHER=yes
|
|
fi
|
|
CONTAINER_COMPAT=yes
|
|
# trying to use nested containers is not a good idea, so don't permit EXTERNAL_NEW=compile
|
|
if [[ $EXTERNAL_NEW == compile ]]; then
|
|
display_alert "EXTERNAL_NEW=compile is not available when running in container, setting to prebuilt" "" "wrn"
|
|
EXTERNAL_NEW=prebuilt
|
|
fi
|
|
SYNC_CLOCK=no
|
|
fi
|
|
fi
|
|
|
|
# warning: apt-cacher-ng will fail if installed and used both on host and in container/chroot environment with shared network
|
|
# set NO_APT_CACHER=yes to prevent installation errors in such case
|
|
if [[ $NO_APT_CACHER != yes ]]; then hostdeps="$hostdeps apt-cacher-ng"; fi
|
|
|
|
local deps=()
|
|
local installed=$(dpkg-query -W -f '${db:Status-Abbrev}|${binary:Package}\n' '*' 2>/dev/null | grep '^ii' | awk -F '|' '{print $2}' | cut -d ':' -f 1)
|
|
|
|
for packet in $hostdeps; do
|
|
if ! grep -q -x -e "$packet" <<< "$installed"; then deps+=("$packet"); fi
|
|
done
|
|
|
|
# distribution packages are buggy, download from author
|
|
if [[ ! -f /etc/apt/sources.list.d/aptly.list ]]; then
|
|
display_alert "Updating from external repository" "aptly" "info"
|
|
wget -qO - https://www.aptly.info/pubkey.txt | apt-key add - >/dev/null 2>&1
|
|
echo "deb http://repo.aptly.info/ squeeze main" > /etc/apt/sources.list.d/aptly.list
|
|
apt-get -qq update
|
|
apt-get install aptly
|
|
fi
|
|
|
|
# sync clock
|
|
if [[ $SYNC_CLOCK != no ]]; then
|
|
display_alert "Syncing clock" "host" "info"
|
|
ntpdate -s ${NTP_SERVER:- time.ijs.si}
|
|
fi
|
|
|
|
if [[ ${#deps[@]} -gt 0 ]]; then
|
|
eval '( apt-get -q update; apt-get -q -y --no-install-recommends install "${deps[@]}" )' \
|
|
${PROGRESS_LOG_TO_FILE:+' | tee -a $DEST/debug/output.log'} \
|
|
${OUTPUT_DIALOG:+' | dialog --backtitle "$backtitle" --progressbox "Installing ${#deps[@]} host dependencies..." $TTY_Y $TTY_X'} \
|
|
${OUTPUT_VERYSILENT:+' >/dev/null 2>/dev/null'}
|
|
# this is needed in case new compilers were installed
|
|
update-ccache-symlinks
|
|
fi
|
|
|
|
if [[ $codename == xenial && $(dpkg-query -W -f='${db:Status-Abbrev}\n' 'zlib1g:i386' 2>/dev/null) != *ii* ]]; then
|
|
apt-get install -qq -y --no-install-recommends zlib1g:i386 >/dev/null 2>&1
|
|
fi
|
|
|
|
# enable arm binary format so that the cross-architecture chroot environment will work
|
|
if [[ $KERNEL_ONLY != yes ]]; then
|
|
modprobe -q binfmt_misc
|
|
mountpoint -q /proc/sys/fs/binfmt_misc/ || mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
|
test -e /proc/sys/fs/binfmt_misc/qemu-arm || update-binfmts --enable qemu-arm
|
|
test -e /proc/sys/fs/binfmt_misc/qemu-aarch64 || update-binfmts --enable qemu-aarch64
|
|
fi
|
|
|
|
# create directory structure
|
|
mkdir -p $SRC/{cache,output,userpatches}
|
|
if [[ -n $SUDO_USER ]]; then
|
|
chgrp --quiet sudo cache output userpatches
|
|
# SGID bit on cache/sources breaks kernel dpkg packaging
|
|
chmod --quiet g+w,g+s output userpatches
|
|
# fix existing permissions
|
|
find $SRC/output $SRC/userpatches -type d ! -group sudo -exec chgrp --quiet sudo {} \;
|
|
find $SRC/output $SRC/userpatches -type d ! -perm -g+w,g+s -exec chmod --quiet g+w,g+s {} \;
|
|
fi
|
|
mkdir -p $DEST/debs/extra $DEST/{config,debug,patch} $SRC/userpatches/overlay $SRC/cache/{sources,toolchains,rootfs} $SRC/.tmp
|
|
|
|
find $SRC/patch -type d ! -name . | sed "s%/patch%/userpatches%" | xargs mkdir -p
|
|
|
|
# download external Linaro compiler and missing special dependencies since they are needed for certain sources
|
|
local toolchains=(
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-5.4.1-2017.05-x86_64_arm-linux-gnueabi.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-5.4.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-6.4.1-2017.08-x86_64_arm-linux-gnueabihf.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-6.4.1-2017.08-x86_64_aarch64-linux-gnu.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-7.1.1-2017.08-x86_64_aarch64-linux-gnu.tar.xz"
|
|
"https://dl.armbian.com/_toolchains/gcc-linaro-7.1.1-2017.08-x86_64_arm-linux-gnueabihf.tar.xz"
|
|
)
|
|
|
|
for toolchain in ${toolchains[@]}; do
|
|
download_toolchain "$toolchain"
|
|
done
|
|
|
|
rm -rf $SRC/cache/toolchains/*.tar.xz $SRC/cache/toolchains/*.tar.xz.asc
|
|
local existing_dirs=( $(ls -1 $SRC/cache/toolchains) )
|
|
for dir in ${existing_dirs[@]}; do
|
|
local found=no
|
|
for toolchain in ${toolchains[@]}; do
|
|
local filename=${toolchain##*/}
|
|
local dirname=${filename//.tar.xz}
|
|
[[ $dir == $dirname ]] && found=yes
|
|
done
|
|
if [[ $found == no ]]; then
|
|
display_alert "Removing obsolete toolchain" "$dir"
|
|
rm -rf $SRC/cache/toolchains/$dir
|
|
fi
|
|
done
|
|
|
|
[[ ! -f $SRC/userpatches/customize-image.sh ]] && cp $SRC/config/templates/customize-image.sh.template $SRC/userpatches/customize-image.sh
|
|
|
|
if [[ ! -f $SRC/userpatches/README ]]; then
|
|
rm -f $SRC/userpatches/readme.txt
|
|
echo 'Please read documentation about customizing build configuration' > $SRC/userpatches/README
|
|
echo 'http://www.armbian.com/using-armbian-tools/' >> $SRC/userpatches/README
|
|
fi
|
|
|
|
# check free space (basic), doesn't work on Trusty
|
|
local freespace=$(findmnt --target $SRC -n -o AVAIL -b 2>/dev/null) # in bytes
|
|
if [[ -n $freespace && $(( $freespace / 1073741824 )) -lt 10 ]]; then
|
|
display_alert "Low free space left" "$(( $freespace / 1073741824 )) GiB" "wrn"
|
|
# pause here since dialog-based menu will hide this message otherwise
|
|
echo -e "Press \e[0;33m<Ctrl-C>\x1B[0m to abort compilation, \e[0;33m<Enter>\x1B[0m to ignore and continue"
|
|
read
|
|
fi
|
|
}
|
|
|
|
# download_toolchain <url>
|
|
#
|
|
download_toolchain()
|
|
{
|
|
local url=$1
|
|
local filename=${url##*/}
|
|
local dirname=${filename//.tar.xz}
|
|
|
|
if [[ -f $SRC/cache/toolchains/$dirname/.download-complete ]]; then
|
|
return
|
|
fi
|
|
|
|
cd $SRC/cache/toolchains/
|
|
|
|
display_alert "Downloading" "$dirname"
|
|
curl -Lf --progress-bar $url -o $filename
|
|
curl -Lf --progress-bar ${url}.asc -o ${filename}.asc
|
|
|
|
local verified=false
|
|
|
|
display_alert "Verifying"
|
|
if grep -q 'BEGIN PGP SIGNATURE' ${filename}.asc; then
|
|
if [[ ! -d $SRC/cache/.gpg ]]; then
|
|
mkdir -p $SRC/cache/.gpg
|
|
chmod 700 $SRC/cache/.gpg
|
|
touch $SRC/cache/.gpg/gpg.conf
|
|
chmod 600 $SRC/cache/.gpg/gpg.conf
|
|
fi
|
|
(gpg --homedir $SRC/cache/.gpg --no-permission-warning --list-keys 8F427EAF || gpg --homedir $SRC/cache/.gpg --no-permission-warning --keyserver keyserver.ubuntu.com --recv-keys 8F427EAF) 2>&1 | tee -a $DEST/debug/output.log
|
|
gpg --homedir $SRC/cache/.gpg --no-permission-warning --verify --trust-model always -q ${filename}.asc 2>&1 | tee -a $DEST/debug/output.log
|
|
[[ ${PIPESTATUS[0]} -eq 0 ]] && verified=true
|
|
else
|
|
md5sum -c --status ${filename}.asc && verified=true
|
|
fi
|
|
if [[ $verified == true ]]; then
|
|
display_alert "Extracting"
|
|
tar --overwrite -xf $filename && touch $SRC/cache/toolchains/$dirname/.download-complete
|
|
display_alert "Download complete" "" "info"
|
|
else
|
|
display_alert "Verification failed" "" "wrn"
|
|
fi
|
|
}
|
|
|
|
show_developer_warning()
|
|
{
|
|
local temp_rc=$(mktemp)
|
|
cat <<-'EOF' > $temp_rc
|
|
screen_color = (WHITE,RED,ON)
|
|
EOF
|
|
local warn_text="You are switching to the \Z1EXPERT MODE\Zn
|
|
|
|
This allows building experimental configurations that are provided
|
|
\Z1AS IS\Zn to developers and expert users,
|
|
\Z1WITHOUT ANY RESPONSIBILITIES\Zn from the Armbian team:
|
|
|
|
- You are using these configurations \Z1AT YOUR OWN RISK\Zn
|
|
- Bug reports related to the dev kernel, CSC, WIP and EOS boards
|
|
\Z1will be closed without a discussion\Zn
|
|
- Forum posts related to dev kernel, CSC, WIP and EOS boards
|
|
should be created in the \Z2\"Community forums\"\Zn section
|
|
"
|
|
DIALOGRC=$temp_rc dialog --title "Expert mode warning" --backtitle "$backtitle" --colors --defaultno --no-label "I do not agree" \
|
|
--yes-label "I understand and agree" --yesno "$warn_text" $TTY_Y $TTY_X
|
|
[[ $? -ne 0 ]] && exit_with_error "Error switching to the expert mode"
|
|
SHOW_WARNING=no
|
|
}
|