uci-docker-build/lib/build.lib

331 lines
9.8 KiB
Bash
Executable File

#!/bin/bash
quiet () {
if [[ $VERBOSE ]]; then $@; fi
}
get_arch () {
local arch="$(uname -m)"
case "$arch" in
x86_64) arch='amd64' ;;
armhf) arch='armv6' ;;
armv7) arch='armv7' ;;
aarch64) arch='arm64' ;;
ppc64el|ppc64le) arch='ppc64le' ;;
s390x) arch='s390x';;
*) return 1 ;;\
esac;
echo $arch
}
isAbsPath() {
if [[ "${1:0:1}" == / || "${1:0:2}" == ~[/a-z] ]]
then
echo "true"
return 0
else
return 1
fi
}
sed_ignore_comments () {
cmd="sed -r 'h;s/[^#]*//1;x;s/#.*//;${1};G;s/(.*)\n/\1/'"
if (( $# == 2 )) ; then
eval $cmd <<< "$2"
else
eval $cmd < /dev/stdin
fi
}
clean_env_file () {
local compact; local lines
# -c will also remove comments and all empty lines
[[ $1 == "-c" ]] && compact=true && shift 1
#
# remove trailing spaces | remove double quotes
# | remove blanks after equals and quote value | remove any spaces before afer =
# remove blank lines | remove comment lines if requested
[[ -f $1 ]] && lines=$(<$1) || lines="$1"
echo "$lines" | sed_ignore_comments s/\\s*$//g | sed_ignore_comments s/\"//g \
| sed_ignore_comments s/\(=[[:blank:]]*\)\(.*\)/\\1\"\\2\"/ \
| sed_ignore_comments s/\\s*=\\s*/=/g \
| sed -rz 's/^\n+//; s/\n+$/\n/g' | if [[ $compact ]]; then grep -v '^#' | grep -v "^$" ; else cat; fi
}
env_file () {
env=${1:-.env}
[[ -f "${env}" ]] && { echo $env; return 0; } # || echo not $env
[[ -f "${env}.env" ]] && { echo "${env}.env"; return 0; } # || echo not ${env}.env
[[ -f "${env}/.env" ]] && { echo "${env}/.env"; return 0; } # || echo not ${env}/.env
return 1
}
read_env_file() {
local evar
while read line; do
evar=$(echo $line | cut -d '=' -f1)
if [[ $(echo $(c() { echo $#; }; c $line)) -gt 1 ]];then
echo the environment file: $1
echo has a format error on this line
echo "--------------"
echo $line
echo "--------------"
echo you must correct this before the build can continue
return 1
fi
if [[ ! ${!evar} ]]; then
# echo DECLARE $evar via $line
if declare -gx "$(echo "${line}" | sed 's/\"//g' )"; then
quiet echo loaded: ${evar}=${!evar}
else
quiet echo error setting $evar
return 1
fi
else
quiet echo $evar already set to ${!evar}
fi
done < <(clean_env_file -c $1)
}
source_env_file () {
local default;local efile
if efile=$(env_file ${1:-$BUILD_EFILE}); then
[[ $efile == ".env" ]] && default=true
[[ ! $(isAbsPath $efile) ]] && efile=$(realpath $efile)
quiet echo -e "\e[1;37m********************\e[0;37m"
quiet echo loading build environment with environment file
quiet echo $efile
quiet echo ----------------
quiet cat $efile
quiet echo ----------------
if read_env_file "$efile"; then
[[ $default ]] && quiet echo -e "\e[1;31mNOTE: sourced default .env file in present directory\e[0;37m"
quiet echo -e "\e[1;37m********************\e[0;37m"
BUILD_EFILE=$efile
else
quiet echo error occured while loading environment file
quiet echo $efile
quiet echo exiting
quiet echo -e "\e[1;37m********************\e[0;37m"
return 2
fi
else
if [[ $efile ]]; then
quiet echo unable to find an environment file with passed ${1}
else
quiet echo unable to find default environment file .env
quiet echo using the current environment plus default build options
fi
return 2
fi
}
load_csv () {
# add newline, remove comments, remove empty lines, remove extra whitespace around ,
if [[ -f $1 ]]; then
sed -e '$a\' "$1" | \
sed -e '/\s*#.*$/d' | \
sed -e '/^\s*$/d' | \
sed 's/\s*,\s*/,/g'
else
return 1
fi
}
get_default_distro_image () {
local distro
distro="$(echo "$(load_csv $BDIR/distros.csv)" | grep $LINUX_DISTRO)"
echo $distro | cut -d',' -f2
}
validate_image_distro() {
local temp=/tmp/os-release.tmp
local distro; local distros
if docker create --name dummy $1 > /dev/null; then
if docker cp -L dummy:/etc/os-release $temp > /dev/null; then
docker rm -f dummy > /dev/null
# echo $(load_csv $BDIR/distros.csv)
distros=$(echo $(echo "$(load_csv $BDIR/distros.csv)" | grep -Eo "^[^,]+") | sed "s/\s/|/g")
distro=$(cat $temp | tr [:upper:] [:lower:] | grep -Eio -m 1 $distros)
rm $temp
[[ ! $distro ]] && echo "image $1 is not a valid distro ($distros)" && return 1
[[ ! "$distro" == "${2:-$LINUX_DISTRO}" ]] && echo "image ${1}'s distro ($distro) is NOT build distro (${2:-$LINUX_DISTRO})" && return 1
quiet echo "base image $1 distro ($distro) has been validated"
else
echo "unable to retreive /etc/os-release from image $1, unable to determine image distro"
fi
else
echo "there is no image $1 locally or at docker hub, can't set the base image"
return 1
fi
}
get_base_image() {
[[ ! $BASE_IMAGE ]] && BASE_IMAGE=$(get_default_distro_image)
if [[ $BASE_IMAGE ]]; then
quiet echo determining DISTRO of base image: $BASE_IMAGE
if ! validate_image_distro $BASE_IMAGE; then
echo "unable to get or use base image: $BASE_IMAGE, aborting build" && return 5
fi
quiet echo $BASE_IMAGE is built from distro $LINUX_DISTRO
else
echo unable to determine a base image, aborting build
return 6
fi
}
make_image_name () {
local arch
# echo making image name $@
# echo name: $NAME
# echo APPEND: $APPEND_DISTRO
# echo user: $RUSER
# echo distro $LINUX_DISTRO
if [[ $1 ]]; then
# [[ $NAME ]] && echo changing image name from $NAME to $1
NAME=$1
fi
if [[ $2 ]]; then
# [[ $RUSER ]] && echo changing image username from $RUSER to $2
RUSER=$2
fi
if [[ $NAME ]]; then
[[ $APPEND_DISTRO ]] && NAME=$NAME-${LINUX_DISTRO}
else
# echo no image name supplied using distro name ${LINUX_DISTRO:-alpine}
NAME=${LINUX_DISTRO:-alpine}
fi
[[ $TARGET == "arm64" && ! $TARGET == $(get_arch) ]] && arch=-$TARGET
[[ $TARGET == "amd64" && ! $TARGET == $(get_arch) ]] && arch=-$TARGET
echo $([[ $RUSER ]] && echo ${RUSER}/)${NAME}$arch
}
get_build_src () {
# processing the build source directory
local src; local spath; local spaths
# will determine if there are any minimal build source files/directories
check_dir () {
if
[ $(ls $1/packages/*system.pkgs 2> /dev/null) ] || \
[ $(ls $1/packages/system/*.pkgs 2> /dev/null) ] || \
[ -f $1/packages/repositories.sh ] || \
[ -f $1/packages/packages.sh ]
then
_packages_=true
return 0
fi
[[ -f $1/init/init.sh ]] && return 0
[[ -d $1/rootfs ]] && return 0
return 1
}
src=${1:-$BUILD_SRC}
[[ $src == "_core_" ]] && return 0
src=${src:-src}
unset BUILD_SRC
if check_dir $src; then
BUILD_SRC=$(realpath $src)
return 0
fi
echo build source path \'$src\' not initially found, echo looking
echo in \$PWD,\$PWD/src/,../\$PWD/src for valid build source
echo to avoid this search use BUILD_SRC= in an environment file
spaths="$PWD $PWD/src $(dirname $PWD)/$src $(dirname $PWD)"
for spath in $spaths; do
echo checking for source in: $spath
if check_dir $spath; then
echo found valid source directory!
echo using $spath
BUILD_SRC=$spath
return 0
fi
done
echo -e "\e[1;31mERROR: unable to find a build source directory as $src \e[1;37m"
return 1
}
build_info () {
if [[ $VERBOSE ]]; then
echo -e "\n!!!!!!!!!!!!!!!!EXTRA BUILD INFO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
pushd "$BDIR" > /dev/null || return 3
docker buildx bake --print $TARGET
popd > /dev/null || return 4
echo -e "\n---------------------------------"
echo "build source at $BUILD_SRC to be mounted to /build in container ***** "
ls -la $BUILD_SRC
echo -e "\n----- base init script init.sh ------\n"
cat $BUILD_SRC/init/init.sh
echo -e "\n----- end base init script init.sh ------"
echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
fi
echo -e "\e[1;37m**************BUILD PARAMETERS *******************************"
echo "Architecture of this machine doing the building: $ARCH"
if [[ "$BUILD_SRC" == "_core_" ]] ;then
echo Building ONLY the UCI core
else
echo "Using scripts source directory at $BUILD_SRC"
fi
echo "Building with base image: $BASE_IMAGE"$([[ "${BASE_IMAGE}" == *":"* ]] || echo :latest)
echo "Build logs can be found in directory $log_dir"
echo "Linux Distro of Image: $LINUX_DISTRO"
echo "Using build target: ${TARGET}"
if [[ -f $APPEND_BUILD_ENV ]]; then
echo "Will append contents of $APPEND_BUILD_ENV to build envionrment"
echo "-------"
cat $APPEND_BUILD_ENV
echo "-------"
fi
echo "----- output --------"
echo creating image
case $TARGET in
multi)
echo "names for both amd64 and arm64, image without architecture suffix is $ARCH"
echo -e "\e[1;31m$IMAGE_NAME$([[ ! $ARCH == amd64 ]] && echo -amd64):${TAG:-latest}\n$IMAGE_NAME$([[ ! $ARCH == arm64 ]] && echo -arm64):${TAG:-latest}\e[1;37m"
echo "building locally and then pushing to ${REPO:-hub.docker.com}"
if [[ ! $REPO ]]; then
echo "NOTE: use target 'publish' to build and push these both"
echo "to docker hub without architecture suffix or local copy"
fi
;;
dev)
;&
default)
echo -e "name => \e[1;31m$IMAGE_NAME:${TAG:-latest}\e[1;37m"
echo "Will build this single image on this machine with architecture $ARCH"
;;
arm64)
echo -e "name => \e[1;31m$IMAGE_NAME$([[ ! $ARCH == arm64 ]] && echo -arm64):${TAG:-latest}\e[1;37m"
echo "Will build this single arm64 image on this machine"
;;
amd64)
echo -e "name => \e[1;31m$IMAGE_NAME$([[ ! $ARCH == amd64 ]] && echo -amd64):${TAG:-latest}\e[1;37m"
echo "Will build this single amd64 image on this machine"
;;
publish)
echo -e "image name \e[1;31m$IMAGE_NAME:${TAG:-latest}\e[1;37m"
echo "Will build and push both amd64 and arm64"
echo "architecture images to hub.docker.com with this single name"
echo "and no local copy will remain"
;;
esac
echo "------------------"
echo -e "********************\e[0;37m"
}