root/build-tools/build-pkgs-parallel
Scott Little b20ac0164d Build Avoidance
Purpose:
   Reduce build times after a repo sync by pulling in pre-generated
srpms and rpms and other build products created by a local reference build.

Usage:
  repo sync
  generate-cgcs-centos-repo.sh ...
  populate_downloads.sh ...
  build-pkgs --build-avoidance [--build-avoidance-user <user> \
     --build-avoidance-host <addr> --build-avoidance-dir <dir>]

Reference builds:
- A server performs a regular (daily?), automated builds using
  existing methods. Call these the reference builds.

- The builds are timestamped, and preserved for some time. (weeks?)
  The MY_WORKSPACE directory for the build shall have a common root
  directory, and a leaf directory that is a UTC time stamp of format
  YYYYMMDDThhmmssZ.
  e.g.
  MY_WORKSPACE=/localdisk/loadbuild/jenkins/StarlingX/20180719T113021Z

  Alternative formats are possible by setting values in ...
  "$MY_REPO/local-build-data/build_avoidance_source"
  e.g.
  BUILD_AVOIDANCE_DATE_FORMAT="%Y-%m-%d"
  BUILD_AVOIDANCE_TIME_FORMAT="%H-%M-%S"
  BUILD_AVOIDANCE_DATE_TIME_DELIM="_"
  BUILD_AVOIDANCE_DATE_TIME_POSTFIX=""
  BUILD_AVOIDANCE_DATE_UTC=0

  Which results in YYYY-MM-DD_hh-mm-ss format using local time.
  The one property that the timestamp must have is that they
  are sortable, and that the reference build and the consumer of
  the reference builds agree on the format.

- A build CONTEXT is captured, consisting of the SHA of each and every
  git that contributed to the build.

- For each package built, a file shall capture he md5sums of all the
  source code inputs to the build of that package.

- All these build products are accessible locally (e.g. a regional
  office) via rsync (other protocols can be added later).  ssh
  is also required to run remote query commands on the reference build.

  Initial ground work to support a selection variable ....
  BUILD_AVOIDANCE_FILE_TRANSFER="my-transfer-protocol"
  in $MY_REPO/local-build-data/build_avoidance_source"
  has been created, but "rsync" is the only valid value at this time.

- Location of the reference build can be specified via command line, or
  defaults can be put in $MY_REPO/local-build-data/build_avoidance_source.
  The local-build-data directory is gitignored by stx-root and so can be
  customized for local needs.
  e.g.
  cat $MY_REPO/local-build-data/build_avoidance_source
  BUILD_AVOIDANCE_USR="jenkins"
  BUILD_AVOIDANCE_HOST="stx-build-server.myco.com"
  BUILD_AVOIDANCE_DIR="/localdisk/loadbuild/jenkins/StarlingX"

Notes:
- Build avoidance is only used if requested.
- Build avoidance does not necessarily use the latest reference build.
  It compares the git context of all available reference builds vs your
  own git context, and chooses the most recent for which you gits have
  all the conent.  i.e. all your gits will be same or newer than that
  used by the reference build.  This also meens that some packages might
  still need to be rebuilt after the download step.
- Normally build avoidance remembers the last download context and will only
  consider reference builds newer than the last download.   You can reset
  using 'build-pkgs --build-avoidance --clear' to erase the download history.
  When might this matter to me?  If you change to an old branch that
  hasn't been synced recently and want to build in that context.
- The primary assumtion of Build Avoidance is that it is faster to
  download packages than to build them.  This is typically true of a
  good LAN, but likely not true of a WAN. This is why we emphasize the
  local nature of your reference build server.

Also in this update:
- reworked context generation to be relative to 'dirname $MY_REPO'
- Moved md5sum calculation to a common file, and fixed case where
  symlinks where canonacalized to paths outside of $MY_REPO.
  We'll make an exception to canonacalization to keep paths
  relative to $MY_REPO.
- In future other functions could be moved to the common file.

Story: 2002835
Task: 22754
Change-Id: I757780190cc6063d0a2d3ad9d0a6020ab5169e99
Signed-off-by: Scott Little <scott.little@windriver.com>
2018-09-17 16:41:31 -04:00

482 lines
17 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# Build first src.rpms, then rpms, from source, or from a downloaded tarball
# or src.rpm plus our additional patches.
#
# This program is a wrapper around build-srpms-parallel and build-rpms-parallel
#
BUILD_PKGS_PARALLEL_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source "${BUILD_PKGS_PARALLEL_DIR}/git-utils.sh"
source "${BUILD_PKGS_PARALLEL_DIR}/build-avoidance-utils.sh"
source "${BUILD_PKGS_PARALLEL_DIR}/spec-utils"
usage () {
echo ""
echo "Usage: "
echo " Create source and Binary rpms:"
echo " Build optimizations (--no-descendants, --no-required, --no-build-info,"
echo " --no-autoclean, --no-build-avoidance) are not recommended for the first build"
echo " after a clone/pull, nor the final build prior to creating an iso or patch,"
echo " but can be used for intermediate builds."
echo " i.e. while debugging compilation failures."
echo " build-pkgs-parallel [--build-avoidance | --no-build-avoidance] [--no-descendants] [--no-required] [--no-build-info] [--no-autoclean] [--careful] [--formal] [ list of package names ]"
echo ""
echo " Delete source rpms, and the directories associated with it's creation:"
echo " Note: does not clean an edit environment"
echo " build-pkgs-parallel --clean [--build-avoidance | --no-build-avoidance] [ list of package names ]"
echo ""
echo " Extract an src.rpm into a pair of git trees to aid in editing it's contents,"
echo " one for source code and one for metadata such as the spec file."
echo " If --no-meta-patch is specified, then WRS patches are omitted."
echo " build-pkgs-parallel --edit [--no-meta-patch] [ list of package names ]"
echo ""
echo " Delete an edit environment"
echo " build-pkgs-parallel --edit --clean [ list of package names ]"
echo ""
echo " This help page"
echo " build-pkgs-parallel [--help]"
echo ""
}
HELP=0
CLEAN_FLAG=0
EDIT_FLAG=0
APPEND_LOG_FLAG=0
BUILD_AVOIDANCE_FLAG=0
STD_BUILD=1
RT_BUILD=1
INSTALLER_BUILD=0
export BUILD_AVOIDANCE_URL=""
# read the options
TEMP=$(getopt -o h --long parallel,rt,std,installer,edit,build-avoidance,no-build-avoidance,build-avoidance-dir:,build-avoidance-host:,build-avoidance-user:,build-avoidance-day:,no-meta-patch,no-descendants,no-required,no-build-info,no-autoclean,formal,careful,help,clean,append-log -n 'build-pkgs-parallel' -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
eval set -- "$TEMP"
# extract options and their arguments into variables.
EXTRA_ARGS_COMMON=""
EXTRA_ARGS_SRPM=""
EXTRA_ARGS_RPM=""
export BUILD_AVOIDANCE_OVERRIDE_DIR=""
export BUILD_AVOIDANCE_OVERRIDE_HOST=""
export BUILD_AVOIDANCE_OVERRIDE_USR=""
export BUILD_AVOIDANCE_DAY=""
while true ; do
case "$1" in
--append-log) APPEND_LOG_FLAG=1 ; shift ;;
--build-avoidance) BUILD_AVOIDANCE_FLAG=1 ; shift ;;
--no-build-avoidance) BUILD_AVOIDANCE_FLAG=0 ; shift ;;
--build-avoidance-dir) BUILD_AVOIDANCE_OVERRIDE_DIR=$2; shift 2 ;;
--build-avoidance-host) BUILD_AVOIDANCE_OVERRIDE_HOST=$2; shift 2 ;;
--build-avoidance-user) BUILD_AVOIDANCE_OVERRIDE_USR=$2; shift 2 ;;
--build-avoidance-day) BUILD_AVOIDANCE_DAY=$2; shift 2 ;;
--no-descendants) EXTRA_ARGS_COMMON+=" --no-descendants" ; shift ;;
--formal) EXTRA_ARGS_COMMON+=" --formal" ; shift ;;
--careful) EXTRA_ARGS_RPM+=" --careful" ; shift ;;
--no-required) EXTRA_ARGS_RPM+=" --no-required" ; shift ;;
--no-build-info) EXTRA_ARGS_COMMON+=" --no-build-info" ; shift ;;
--no-autoclean) EXTRA_ARGS_RPM+=" --no-autoclean" ; shift ;;
--no-meta-patch) EXTRA_ARGS_SRPM+=" --no-meta-patch" ; shift ;;
-h|--help) HELP=1 ; shift ;;
--clean) CLEAN_FLAG=1 ; shift ;;
--edit) EDIT_FLAG=1 ; EXTRA_ARGS_SRPM+=" --edit"; shift ;;
--rt) STD_BUILD=0 ; shift ;;
--std) RT_BUILD=0 ; shift ;;
--installer) INSTALLER_BUILD=1 ; STD_BUILD=0 ; RT_BUILD=0 ; shift ;;
--parallel) shift ;;
--) shift ; break ;;
*) usage; exit 1 ;;
esac
done
if [ $HELP -eq 1 ]; then
usage
exit 0
fi
function my_exit() {
build-rpms-parallel --std --tmpfs-clean
build-rpms-parallel --rt --tmpfs-clean
}
function my_sigint() {
echo "build-pkgs-parallel sigint"
pkill -SIGABRT -P $BASHPID &> /dev/null
echo "build-pkgs-parallel waiting"
wait
echo "build-pkgs-parallel wait complete"
}
function my_sighup() {
echo "build-pkgs-parallel sighup"
pkill -SIGABRT -P $BASHPID &> /dev/null
echo "build-pkgs-parallel waiting"
wait
echo "build-pkgs-parallel wait complete"
}
function my_sigabrt() {
echo "build-pkgs-parallel sigabrt"
pkill -SIGABRT -P $BASHPID &> /dev/null
echo "build-pkgs-parallel waiting"
wait
echo "build-pkgs-parallel wait complete"
}
function my_sigterm() {
echo "build-pkgs-parallel sigterm"
pkill -SIGABRT -P $BASHPID &> /dev/null
echo "build-pkgs-parallel waiting"
wait
echo "build-pkgs-parallel wait complete"
}
trap my_exit EXIT
trap my_sigint INT
trap my_sighup HUP
trap my_sigabrt ABRT
trap my_sigterm TERM
# Note: For ease of parsing, a TARGETS list always begins and ends
# with a space. An empty target list consistes of two spaces.
TARGETS=" $@ "
EMPTY_TARGETS=" "
TARGETS_STD="$EMPTY_TARGETS"
TARGETS_RT="$EMPTY_TARGETS"
TARGETS_INSTALLER="$EMPTY_TARGETS"
TARGETS_MISC="$EMPTY_TARGETS"
find_targets () {
local centos_pkg_dirs=$1
local d=""
local d2=""
local g=""
local x=""
local name=""
local path=""
local RESULT=" "
local FOUND=0
for d in $GIT_LIST; do
if [ -f $d/$centos_pkg_dirs ]; then
for d2 in $(grep -v '^#' $d/$centos_pkg_dirs); do
name=""
if [ -f $d/$d2/centos/srpm_path ]; then
path=$(cat $d/$d2/centos/srpm_path | head -n 1 | sed "s#^mirror:CentOS/tis-r3-CentOS/mitaka#$MY_REPO/cgcs-centos-repo#" | sed "s#^mirror:#$MY_REPO/cgcs-centos-repo/#" | sed "s#^repo:#$MY_REPO/#" | sed "s#^3rd_party:#$MY_REPO/cgcs-3rd-party-repo/#" | sed "s#^Source/#$MY_REPO/cgcs-centos-repo/Source/#")
name=$(rpm -q --qf='%{NAME}' --nosignature -p $path)
else
path=$(find $d/$d2/centos/ -name '*.spec' | head -n 1)
if [[ ( -z "$path" ) && ( -f $d/$d2/centos/spec_path ) ]]; then
path=$(find $MY_REPO/$(cat $d/$d2/centos/spec_path) -maxdepth 1 -name '*.spec' | head -n 1)
fi
if [ "$path" != "" ]; then
name=$(spec_find_tag Name "$path" 2>> /dev/null)
fi
fi
if [ "$name" != "" ]; then
if [ "$BUILD_TYPE" == "rt" ]; then
FOUND=0
for x in $TARGETS; do
if [ "${x: -3}" == "-rt" ]; then
if [ "${name}" == "$x" ] || [ "${name}-rt" == "${x}" ]; then
RESULT+="$x "
FOUND=1
break
fi
fi
done
if [ $FOUND -eq 0 ]; then
for x in $TARGETS; do
if [ "${name}" == "${x}-rt" ]; then
RESULT+="$x-rt "
FOUND=1
break
else
if [ "${name}" == "$x" ] || [ "${name}-rt" == "${x}" ]; then
RESULT+="$x "
FOUND=1
break
fi
fi
done
fi
else
for x in $TARGETS; do
if [ "${name}" == "$x" ]; then
RESULT+="$x "
FOUND=1
break
fi
done
fi
fi
done
fi
done
if [ "$RESULT" == " " ]; then
echo "$EMPTY_LIST"
else
echo "$RESULT"
fi
return 0
}
if [ $EDIT_FLAG -eq 1 ] || [ "$TARGETS" != "$EMPTY_TARGETS" ]; then
BUILD_AVOIDANCE_FLAG=0
fi
echo "BUILD_AVOIDANCE_FLAG=$BUILD_AVOIDANCE_FLAG"
echo "CLEAN_FLAG=$CLEAN_FLAG"
echo "EDIT_FLAG=$EDIT_FLAG"
if [ $BUILD_AVOIDANCE_FLAG -eq 1 ]; then
# Build Avoidance requested. Get URL of a usable context, if any.
export BUILD_AVOIDANCE_URL=$(get_build_avoidance_context)
fi
if [ "$TARGETS" != "$EMPTY_TARGETS" ]; then
TARGETS_STD="$(find_targets centos_pkg_dirs)"
BUILD_TYPE_SAVE="$BUILD_TYPE"
BUILD_TYPE="rt"
TARGETS_RT="$(find_targets centos_pkg_dirs_rt)"
BUILD_TYPE="installer"
TARGETS_INSTALLER="$(find_targets centos_pkg_dirs_installer)"
BUILD_TYPE="$BUILD_TYPE_SAVE"
echo "TARGETS_STD=$TARGETS_STD"
echo "TARGETS_RT=$TARGETS_RT"
echo "TARGETS_INSTALLER=$TARGETS_INSTALLER"
for x in $TARGETS; do
if [[ $TARGETS_STD == *" $x "* ]]
then
echo "found $x" >> /dev/null;
else
if [[ $TARGETS_RT == *" $x "* ]]
then
echo "found $x" >> /dev/null;
else
if [[ $TARGETS_INSTALLER == *" $x "* ]]
then
echo "found $x" >> /dev/null;
INSTALLER_BUILD=1
else
TARGETS_MISC+="$x "
fi
fi
fi
done
fi
echo "EXTRA_ARGS_COMMON='$EXTRA_ARGS_COMMON'"
echo "EXTRA_ARGS_SRPM='$EXTRA_ARGS_SRPM'"
echo "EXTRA_ARGS_RPM='$EXTRA_ARGS_RPM'"
echo "TARGETS='$TARGETS'"
echo "TARGETS_STD='$TARGETS_STD'"
echo "TARGETS_RT='$TARGETS_RT'"
echo "TARGETS_INSTALLER='$TARGETS_INSTALLER'"
echo "TARGETS_MISC='$TARGETS_MISC'"
if [ $CLEAN_FLAG -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] && [ $BUILD_AVOIDANCE_FLAG -eq 1 ] ; then
build_avoidance_clean
fi
if [ $STD_BUILD -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_STD" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
if [ $EDIT_FLAG -ne 1 ]; then
echo "${BUILD_PKGS_PARALLEL_DIR}/build-rpms-parallel --std --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $TARGETS_STD $TARGETS_MISC"
${BUILD_PKGS_PARALLEL_DIR}/build-rpms-parallel --std --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $TARGETS_STD $TARGETS_MISC || exit 1
fi
fi
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_STD" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
echo "${BUILD_PKGS_PARALLEL_DIR}/build-srpms-parallel --std --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $TARGETS_STD $TARGETS_MISC"
${BUILD_PKGS_PARALLEL_DIR}/build-srpms-parallel --std --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $TARGETS_STD $TARGETS_MISC || exit 1
fi
fi
if [ $RT_BUILD -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_RT" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
if [ $EDIT_FLAG -ne 1 ]; then
echo "${BUILD_PKGS_PARALLEL_DIR}/build-rpms-parallel --rt --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $TARGETS_RT $TARGETS_MISC"
${BUILD_PKGS_PARALLEL_DIR}/build-rpms-parallel --rt --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $TARGETS_RT $TARGETS_MISC || exit 1
fi
fi
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_RT" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
echo "${BUILD_PKGS_PARALLEL_DIR}/build-srpms-parallel --rt --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $TARGETS_RT $TARGETS_MISC"
${BUILD_PKGS_PARALLEL_DIR}/build-srpms-parallel --rt --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $TARGETS_RT $TARGETS_MISC || exit 1
fi
fi
if [ $INSTALLER_BUILD -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_INSTALLER" != "$EMPTY_TARGETS" ]; then
if [ $EDIT_FLAG -ne 1 ]; then
echo "${BUILD_PKGS_PARALLEL_DIR}/build-rpms-serial --installer --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $TARGETS_INSTALLER"
${BUILD_PKGS_PARALLEL_DIR}/build-rpms-serial --installer --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $TARGETS_INSTALLER || exit 1
fi
fi
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_INSTALLER" != "$EMPTY_TARGETS" ]; then
echo "${BUILD_PKGS_PARALLEL_DIR}/build-srpms-serial --installer --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $TARGETS_INSTALLER"
${BUILD_PKGS_PARALLEL_DIR}/build-srpms-serial --installer --clean $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $TARGETS_INSTALLER || exit 1
fi
fi
exit $?
fi
function launch_build()
{
local build_type=$1
shift
local logfile=$MY_WORKSPACE/build-$build_type.log
local rc
local targets
if [ "$build_type" == "std" ]; then
targets="$TARGETS_STD $TARGETS_MISC"
else
if [ "$build_type" == "rt" ]; then
targets="$TARGETS_RT $TARGETS_MISC"
else
if [ "$build_type" == "installer" ]; then
targets="$TARGETS_INSTALLER $TARGETS_MISC"
else
targets="$TARGETS"
fi
fi
fi
echo "Launching $build_type build, logging to $logfile"
if [ $APPEND_LOG_FLAG -eq 0 ] && [ -f $logfile ]; then
\rm $logfile
fi
echo -e "\n######## $(date): Launching build-srpms-parallel --$build_type $EXTRA_ARGS $@\n" | tee --append $logfile
echo "BUILD_AVOIDANCE_URL=$BUILD_AVOIDANCE_URL" | tee --append $logfile
if [ "x$BUILD_AVOIDANCE_URL" != "x" ]; then
echo "build_avoidance $build_type" | tee --append $logfile
build_avoidance $build_type 2>&1 | tee --append $logfile
fi
# No clean flag, call build-srpms-parallel followed by build-rpms-parallel
echo "${BUILD_PKGS_PARALLEL_DIR}/build-srpms-parallel --$build_type $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $targets" | tee --append $logfile
${BUILD_PKGS_PARALLEL_DIR}/build-srpms-parallel --$build_type $EXTRA_ARGS_COMMON $EXTRA_ARGS_SRPM $targets 2>&1 | tee --append $logfile
rc=${PIPESTATUS[0]}
if [ $rc -eq 0 ]; then
echo -e "\n######## $(date): build-srpm-parallel --$build_type was successful" | tee --append $logfile
else
echo -e "\n######## $(date): build-srpm-parallel --$build_type failed with rc=$rc" | tee --append $logfile
echo -e "\n$(date): build-srpm-parallel --$build_type failed with rc=$rc"
exit $rc
fi
if [ $EDIT_FLAG -ne 1 ]; then
echo -e "\n######## $(date): Launching build-rpms-parallel --$build_type $EXTRA_ARGS $@\n" | tee --append $logfile
echo "${BUILD_PKGS_PARALLEL_DIR}/build-rpms-parallel --$build_type $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $targets" | tee --append $logfile
${BUILD_PKGS_PARALLEL_DIR}/build-rpms-parallel --$build_type $EXTRA_ARGS_COMMON $EXTRA_ARGS_RPM $targets 2>&1 | tee --append $logfile
rc=${PIPESTATUS[0]}
if [ $rc -eq 0 ]; then
echo -e "\n######## $(date): build-rpm-parallel --$build_type was successful" | tee --append $logfile
else
echo -e "\n######## $(date): build-rpm-parallel --$build_type failed with rc=$rc" | tee --append $logfile
echo -e "\n$(date): build-rpm-parallel --$build_type failed with rc=$rc"
exit $rc
fi
fi
echo -e "\n$(date): $build_type complete\n"
#exit $rc
}
function progbar()
{
while :; do
for s in / - \\ \|; do
printf "\r$s"
sleep .5
done
done
}
# Create $MY_WORKSPACE if it doesn't exist already
mkdir -p "${MY_WORKSPACE}"
if [ $? -ne 0 ]; then
echo "Failed to create directory '${MY_WORKSPACE}'"
exit 1
fi
echo "Capture build context"
git_context > "${MY_WORKSPACE}/CONTEXT"
if [ $STD_BUILD -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_STD" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
launch_build std
else
echo "Skipping 'std' build, no valid targets in list: '$TARGETS'"
fi
else
echo "Skipping 'std' build"
fi
if [ $RT_BUILD -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_RT" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
launch_build rt
else
echo "Skipping 'rt' build, no valid targets in list: $TARGETS"
fi
else
echo "Skipping 'rt' build"
fi
if [ $INSTALLER_BUILD -eq 1 ]; then
if [ "$TARGETS" == "$EMPTY_TARGETS" ] || [ "$TARGETS_INSTALLER" != "$EMPTY_TARGETS" ] || [ "$TARGETS_MISC" != "$EMPTY_TARGETS" ]; then
launch_build installer
else
echo "Skipping 'installer' build, no valid targets in list: $TARGETS"
fi
else
echo "Skipping 'installer' build"
fi
# Make sure REFERENCE_BUILD is set to something
if [ -z $REFERENCE_BUILD ]; then
REFERENCE_BUILD=0
fi
if [ $REFERENCE_BUILD -eq 1 ]; then
echo "Saving reference context"
build_avoidance_save_reference_context
fi
echo "All builds were successful"
exit 0