|
#!/bin/bash
|
|
#
|
|
# --- ROCK-COPYRIGHT-NOTE-BEGIN ---
|
|
#
|
|
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
|
|
# Please add additional copyright information _after_ the line containing
|
|
# the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
|
|
# the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
|
|
#
|
|
# ROCK Linux: rock-src/scripts/Build-Target
|
|
# ROCK Linux is Copyright (C) 1998 - 2006 Clifford Wolf
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version. A copy of the GNU General Public
|
|
# License can be found at Documentation/COPYING.
|
|
#
|
|
# Many people helped and are helping developing ROCK Linux. Please
|
|
# have a look at http://www.rocklinux.org/ and the Documentation/TEAM
|
|
# file for details.
|
|
#
|
|
# --- ROCK-COPYRIGHT-NOTE-END ---
|
|
#
|
|
# Run this command from the ROCK directory as ./scripts/Build-Target
|
|
# after running the ./scripts/Config and ./scripts/Download commands.
|
|
#
|
|
# It compiles/builds all the packages and stores them as tar balls suitable
|
|
# for distribution.
|
|
#
|
|
# This script is the ROCK work-horse. It builds in a chroot environment
|
|
# (stage 2..9) and goes through a number of build stages:
|
|
#
|
|
|
|
config=default
|
|
build_only_this_job=
|
|
stages=0123456789
|
|
daemon_mode=0
|
|
options="$*"
|
|
tasks=0
|
|
|
|
while [ "$1" ] ; do
|
|
case "$1" in
|
|
-cfg) config=$2 ; shift ; shift ;;
|
|
-stages) stages=$2 ; shift ; shift ;;
|
|
-tasks) tasks=$2 ; shift ; shift ;;
|
|
-job) build_only_this_job=$2 ; shift ; shift ;;
|
|
-daemon) daemon_mode=1 ; shift ;;
|
|
-nodaemon) daemon_mode=0 ; shift ;;
|
|
*) echo "Usage: $0 [ -daemon ] [ -tasks <N> ] [ -cfg <config> ]" \
|
|
"[ -stages <list> ] [ -job <stage>-<package> ]"
|
|
echo
|
|
echo " Compile/build all packages for a given configuration and store them as tar"
|
|
echo " balls suitable for distribution."
|
|
echo " This script is the ROCK work-horse. It builds in a chroot environment"
|
|
echo " (stage 2..9) and goes through a number of build stages."
|
|
echo " Run this command from the ROCK directory as ./scripts/Build-Target after"
|
|
echo " running the ./scripts/Config and ./scripts/Download commands."
|
|
echo
|
|
echo " -cfg <config> the build configuration to use; defaults to 'default'"
|
|
echo " -tasks <N> run <N> Build-Job daemons (for cluster builds)"
|
|
echo " -daemon run as daemon in the background"
|
|
echo " -stages <list> only build the stages listed in the parameter"
|
|
echo " -job <stage>-<package> build only one job: the given package"
|
|
echo " in the given stage"
|
|
exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [ $tasks -gt 1 ] ; then
|
|
. config/$config/config
|
|
if [ "$ROCKCFG_PARALLEL" = 0 ] ; then
|
|
echo_error "You have not configured this to be a cluster build!"
|
|
echo_error "Please remove -tasks $tasks or configure this for cluster build"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ "$daemon_mode" = 1 ] ; then
|
|
. config/$config/config
|
|
echo "Running $0 in the background (messages go to logfile only).."
|
|
echo "Logfile: build/$ROCKCFG_ID/ROCK/logs/build_target.log"
|
|
nohup $0 $options -nodaemon > /dev/null 2> /dev/null < /dev/null &
|
|
exit 0
|
|
fi
|
|
|
|
. scripts/parse-config
|
|
. scripts/functions
|
|
|
|
# so we can disable stuff not available in Build-Target
|
|
export ROCK_BUILD_TARGET=1
|
|
|
|
build_root="$base/build/$ROCKCFG_ID"
|
|
build_rock="$base/build/$ROCKCFG_ID/ROCK"
|
|
build_logs="$build_rock/logs" ; mkdir -p "${build_logs}"
|
|
build_pkgs="$build_rock/pkgs" ; mkdir -p "${build_root}"
|
|
|
|
if [ "$ROCKCFG_PARANOIA_CHECK" = 1 ] ; then
|
|
./scripts/Check-System -paranoia || exit 1
|
|
else
|
|
./scripts/Check-System || exit 1
|
|
fi
|
|
|
|
# Package Build loop - executed by build-target
|
|
#
|
|
pkgloop() {
|
|
if [ "$ROCKCFG_NOBROKENDEPS" = 1 ]; then
|
|
nobrokendeps="-nobrokendeps"
|
|
else
|
|
nobrokendeps=""
|
|
fi
|
|
if [ "$ROCKCFG_RETRY_BROKEN" -eq 1 -a \
|
|
-z "$build_only_this_job" -a \
|
|
"`ls ${build_root}/var/adm/logs/*.err 2> /dev/null`" ] ; then
|
|
echo_header "Removing old error logs ..."
|
|
for x in ${build_root}/var/adm/logs/*.err ; do
|
|
echo_status "Removing ${x#$build_root/} ..."
|
|
rm -f $x
|
|
done
|
|
fi
|
|
if [ -z "$build_only_this_job" -a \
|
|
"`ls ${build_root}/var/adm/logs/*.out 2> /dev/null`" ] ; then
|
|
echo_header "Removing old output logs ..."
|
|
for x in ${build_root}/var/adm/logs/*.out ; do
|
|
echo_status "Removing ${x#$build_root/} ..."
|
|
rm -f $x
|
|
done
|
|
fi
|
|
|
|
if [ "$ROCKCFG_PARALLEL" = 1 -a -z "$build_only_this_job" ]
|
|
then
|
|
qdir="$base/build/$ROCKCFG_ID/ROCK/queue"
|
|
mkdir -p $qdir; rm -f $qdir/*
|
|
|
|
|
|
newqueue=1 ; printstatus=1 ; printstatus_counter=30
|
|
finished=0 ; touch $qdir/queue.txt
|
|
|
|
if [ -z "$ROCKCFG_PARALLEL_ADDJOB" ] ; then
|
|
touch $qdir/use_build_job_daemon
|
|
if [ $tasks = 0 ]; then
|
|
echo "
|
|
Job Queue for parallel (cluster) build created.
|
|
|
|
You have not configured a command for adding jobs. So you need to use the
|
|
ROCK Linux built-in job queue. To do so, you need to login to your build
|
|
nodes and execute the command:
|
|
|
|
./scripts/Build-Job -cfg $config -daemon
|
|
"
|
|
else
|
|
echo "
|
|
Job Queue for parallel (cluster) build created. Now creating worker tasks..
|
|
"
|
|
for ((n=0; n<tasks; n++)); do
|
|
echo -n "[$n] "
|
|
./scripts/Build-Job -cfg $config -daemon
|
|
done
|
|
echo "
|
|
Parallel (cluster) build running...
|
|
"
|
|
fi
|
|
else
|
|
echo "
|
|
Job Queue for parallel (cluster) build created.
|
|
|
|
You have configured a command for adding jobs. So if everything is configured
|
|
in the right way, the nodes will automatically start building the jobs.
|
|
"
|
|
rm -f $qdir/use_build_job_daemon
|
|
fi
|
|
|
|
while
|
|
if [ -f $qdir/print_status ] ; then
|
|
rm -f $qdir/print_status
|
|
printstatus=1 ; printstatus_counter=0
|
|
fi
|
|
|
|
if [ "$printstatus" = 1 ] ; then
|
|
if [ $printstatus_counter -le 0 ] ; then
|
|
./scripts/Create-ParaStatus -cfg "$config"
|
|
printstatus=0 ; printstatus_counter=300
|
|
else
|
|
printstatus_counter=$(($printstatus_counter - 1))
|
|
fi
|
|
fi
|
|
|
|
for x in $qdir/*.msg ; do
|
|
if [ -f "$x" ] ; then
|
|
expand -t20 < $x ; rm -f $x
|
|
printstatus=1 ; newqueue=1
|
|
fi
|
|
done
|
|
|
|
if [ "$newqueue" = 1 ] ; then
|
|
./scripts/Create-PkgQueue \
|
|
-cfg $config -stages $stages \
|
|
$nobrokendeps | sort -r -n -k2 | \
|
|
if [ $ROCKCFG_PARALLEL_MAX -gt 0 ]
|
|
then head -n $ROCKCFG_PARALLEL_MAX
|
|
else cat ; fi > $qdir/queue.new
|
|
mv $qdir/queue.new $qdir/queue.txt
|
|
newqueue=0
|
|
|
|
while read next ; do
|
|
set $next ; qid="$1-$6"
|
|
if [ ! -f $qdir/$qid.job ] ; then
|
|
date "+%H:%M %Y-%m-%d: creating new job '$qid'" | expand -t20
|
|
echo "Job $qid waiting in the job queue (priority $2)" > $qdir/$qid.todo
|
|
printstatus=1
|
|
|
|
# we need to remove some variables that should be uniqe per node
|
|
dump_env | grep -v HOSTNAME= > $qdir/$qid.new
|
|
mv $qdir/$qid.new $qdir/$qid.job
|
|
if [ "$ROCKCFG_PARALLEL_ADDJOB" ] ; then
|
|
x="${ROCKCFG_PARALLEL_ADDJOB//\{\}/.\/scripts\/Build-Job -cfg $config $qid}" ; sh -c "$x"
|
|
fi
|
|
fi
|
|
done < $qdir/queue.txt
|
|
fi
|
|
|
|
if [ -s $qdir/queue.txt ] || \
|
|
[ "`ls $qdir/*.job 2>/dev/null`" ]
|
|
then
|
|
finished=0
|
|
else
|
|
finished=$(( $finished + 1 ))
|
|
newqueue=1
|
|
fi
|
|
|
|
[ $finished -le 3 ]
|
|
do
|
|
sleep 1
|
|
done
|
|
|
|
echo "All packages built."
|
|
sleep 2; rm -rf $qdir
|
|
else
|
|
if [ "$build_only_this_job" ] ; then
|
|
rm -f "${build_root}"/var/adm/logs/${build_only_this_job}.log"
|
|
rm -f "${build_root}"/var/adm/logs/${build_only_this_job}.err"
|
|
next="$( awk 'BEGIN { FS=" "; }
|
|
$0 ~ /[ =]'${build_only_this_job#*-}' / && \
|
|
$2 ~ /'${build_only_this_job%%-*}'/ \
|
|
{ $1="'${build_only_this_job%%-*}' 0";
|
|
print; exit; }' < config/$config/packages )"
|
|
[ "$next" ] && pkgloop_package $next
|
|
exit 0
|
|
else
|
|
while
|
|
next="`./scripts/Create-PkgQueue \
|
|
-cfg "$config" -stages $stages -single $nobrokendeps`"
|
|
[ "$next" ]
|
|
do
|
|
pkgloop_package $next
|
|
done
|
|
fi
|
|
fi
|
|
|
|
local pkglst=`mktemp` errors=0; rm -f src/invalid-files.lst
|
|
echo_header "Searching for old lingering files ..."
|
|
grep "^X" config/$config/packages | cut -d' ' -f5 | sed 's,.*=,,' |
|
|
if [ $ROCKCFG_PKGFILE_VER = 1 ] ; then
|
|
while read p; do
|
|
v=$( grep -h '^Package Name and Version:' build/$ROCKCFG_ID/var/adm/packages/$p:* \
|
|
build/$ROCKCFG_ID/var/adm/packages/$p 2> /dev/null | cut -f6,7 -d' ' | tr ' ' - | head -n1 )
|
|
echo "$p-$v"
|
|
done
|
|
else
|
|
cat
|
|
fi > $pkglst
|
|
for file in $( ls build/$ROCKCFG_ID/ROCK/pkgs/ ) ; do
|
|
x="$file"
|
|
[ "$x" = packages.db ] && continue
|
|
[ "$x" = packages.db.md5 ] && continue
|
|
[ "$x" = packages_stripped.db ] && continue
|
|
[ "$x" = packages_stripped.db.md5 ] && continue
|
|
[ $ROCKCFG_CREATE_GEM = 0 ] || x=${x%.gem}
|
|
[ $ROCKCFG_CREATE_TARBZ2 = 0 ] || x=${x%.tar.bz2}
|
|
y=$( echo $x | sed 's,:[^-]*,,' )
|
|
if ! grep -qx "$y" $pkglst; then
|
|
file="build/$ROCKCFG_ID/ROCK/pkgs/$file"
|
|
echo_error "$file [$x $y] should not be present" \
|
|
"(now in src/invalid-files.lst)!"
|
|
mkdir -p src; echo "$file" >> src/invalid-files.lst
|
|
errors=1
|
|
fi
|
|
done
|
|
for dir in build/$ROCKCFG_ID/var/adm/{cache,cksums,dependencies,descs,flists,md5sums,packages} ; do
|
|
for file in $( ls $dir ) ; do
|
|
if [ $ROCKCFG_PKGFILE_VER = 1 ] ; then x="${file%:*}-.*"; else x="${file%:*}"; fi
|
|
if ! grep -xq "$x" $pkglst ; then
|
|
echo_error "$dir/$file should not be present (now in src/invalid-files.lst)!"
|
|
mkdir -p src; echo "$dir/$file" >> src/invalid-files.lst
|
|
errors=1
|
|
fi
|
|
done
|
|
done
|
|
for file in $( ls build/$ROCKCFG_ID/var/adm/logs/ ) ; do
|
|
x="`echo $file | sed -e 's/^.-//' -e 's/\.log//' -e 's/\.err//' -e s'/\.out//'`"
|
|
if [ $ROCKCFG_PKGFILE_VER = 1 ] ; then x="$x-.*"; else x="$x"; fi
|
|
|
|
if ! grep -xq "$x" $pkglst ; then
|
|
file="build/$ROCKCFG_ID/var/adm/logs/$file"
|
|
echo_error "$file should not be present (now in src/invalid-files.lst)!"
|
|
mkdir -p src; echo "$file" >> src/invalid-files.lst
|
|
errors=1
|
|
fi
|
|
done
|
|
[ $errors = 0 ] && echo_status "No errors found."
|
|
rm $pkglst
|
|
}
|
|
|
|
# Process one line of output generated by Create-PkgQueue
|
|
#
|
|
pkgloop_package() {
|
|
for x in stagelevel pkg_depnr pkg_stages pkg_pri pkg_tree \
|
|
pkg_name pkg_ver pkg_prefix pkg_extra
|
|
do eval "$x=\$1" ; shift ; done
|
|
|
|
# Maybe this is a forked package
|
|
pkg_basename="${pkg_name%=*}"
|
|
pkg_name="${pkg_name#*=}"
|
|
|
|
[ "$build_only_this_job" -a \
|
|
"$stagelevel-$pkg_name" != "$build_only_this_job" ] && return
|
|
|
|
[ $(expr "$pkg_stages" : ".*$stagelevel.*") -eq 0 ] && return
|
|
pkg_laststage=$(echo "$pkg_stages" | sed "s,-,,g; s,.*\(.\),\1,")
|
|
|
|
cmd_root="-root auto"
|
|
[ $stagelevel -gt 1 ] && cmd_root="$cmd_root -chroot"
|
|
|
|
if [ "$pkg_prefix" != "/" ] ; then
|
|
cmd_prefix="-prefix $pkg_prefix"
|
|
else cmd_prefix="" ; fi
|
|
|
|
cmd_buildpkg="./scripts/Build-Pkg -$stagelevel -cfg $config -nopostinst"
|
|
cmd_buildpkg="$cmd_buildpkg $cmd_root $cmd_prefix $pkg_basename=$pkg_name"
|
|
|
|
# Execute action handler
|
|
pkgloop_action || [ "$ROCKCFG_ABORT_ON_ERROR" != 1 ] || exit 1
|
|
|
|
if [ -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err -a \
|
|
"$ROCKCFG_SENDMAIL" = 1 ]
|
|
then
|
|
{
|
|
cat << EOT
|
|
Subject: [ROCK Build-Target] $stagelevel-$pkg_name in $config failed
|
|
|
|
Building package $pkg_name failed in stage $stagelevel:
|
|
----
|
|
EOT
|
|
echo; tail -n 200 ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err; echo
|
|
} | $ROCKCFG_SENDMAIL_BIN $ROCKCFG_SENDMAIL_TO
|
|
fi
|
|
|
|
if [ ! -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.log -a \
|
|
! -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err ]
|
|
then
|
|
echo_header "Package build ended abnormally!"
|
|
echo_error "Usually a package build creates eighter a *.log"
|
|
echo_error "or a *.err file. Neither the 1st nor the 2nd is"
|
|
echo_error "there. So I'm going to create a *.err file now"
|
|
echo_error "and abort the build process."
|
|
touch ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err
|
|
exit 1
|
|
fi
|
|
|
|
if [ $pkg_laststage -eq $stagelevel ] && \
|
|
[ "$ROCKCFG_CREATE_TARBZ2" = 1 -o "$ROCKCFG_CREATE_GEM" = 1 ]
|
|
then
|
|
if [ -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err ]
|
|
then echo_error "Creation of binary package isn't possible,"
|
|
echo_error "because the package was not successfully"
|
|
echo_error "built in (at least) the current stage."
|
|
else
|
|
for spkg in $( cd ${build_root}/var/adm/packages/; ls ${pkg_name} ${pkg_name}:* 2>/dev/null )
|
|
do
|
|
echo_header "Creating binary package file for ${spkg}."
|
|
mkdir -p "${build_pkgs}"
|
|
|
|
if [ "$ROCKCFG_PKGFILE_VER" = 1 ]
|
|
then
|
|
v="-$( grep '^Package Name and Version:' \
|
|
${build_root}/var/adm/packages/$spkg | cut -f6,7 -d' ' | tr ' ' - )"
|
|
else
|
|
v=""
|
|
fi
|
|
|
|
echo_status "Building build/.../pkgs/`
|
|
`${spkg}${v}.tar.bz2"
|
|
( cd "$build_root/"
|
|
cut -f2- -d' ' var/adm/flists/$spkg | \
|
|
tar -cf- --no-recursion --files-from=- | bzip2
|
|
) > "${build_pkgs}/${spkg}${v}.tar.bz2.tmp"
|
|
|
|
if [ "$ROCKCFG_CREATE_GEM" = 1 ] ; then
|
|
echo_status "Building build/.../pkgs/`
|
|
`${spkg}${v}.gem"
|
|
mine -C "$build_root/var/adm" \
|
|
"${build_pkgs}/${spkg}${v}.tar.bz2.tmp" \
|
|
$spkg "$build_pkgs/${spkg}${v}.gem"
|
|
fi
|
|
|
|
if [ "$ROCKCFG_CREATE_TARBZ2" = 1 ] ; then
|
|
mv "$build_pkgs/${spkg}${v}.tar.bz2.tmp" \
|
|
"$build_pkgs/${spkg}${v}.tar.bz2"
|
|
else
|
|
echo_status "Removing temporary tar.bz2."
|
|
rm -f "$build_pkgs/${spkg}${v}.tar.bz2.tmp"
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Action executed by pkgloop(). This function may be redefined
|
|
# before calling pkgloop().
|
|
#
|
|
pkgloop_action() {
|
|
$cmd_buildpkg
|
|
}
|
|
|
|
# Try to umount any directories mounted by Build-Pkg -chroot
|
|
# if we are the last process using them.
|
|
#
|
|
build_target_exit() {
|
|
exec 201> /dev/null
|
|
exec 1>&0 2>&0
|
|
|
|
echo_header "Running Build-Target cleanup procedure"
|
|
|
|
echo_status "Killing lingering processes and removing parallel build queue."
|
|
rm -rf $build_rock/queue
|
|
fuser -k ${build_logs}/*.log &> /dev/null
|
|
sleep 2
|
|
|
|
echo_status "Umounting lingering mounts in build/$ROCKCFG_ID."
|
|
umount -d -f $build_rock/{loop,config,download} 2> /dev/null
|
|
umount -d -f -l $build_rock/{loop,config,download} 2> /dev/null
|
|
umount -d -f $build_root/proc 2> /dev/null
|
|
umount -d -f -l $build_root/proc 2> /dev/null
|
|
|
|
echo_status "READY."
|
|
echo
|
|
}
|
|
|
|
# must trap outside the group command
|
|
trap 'build_target_exit' EXIT
|
|
|
|
{
|
|
ln -sf build_target_$$.log ${build_logs}/build_target.log
|
|
./scripts/Build-Tools -1 -cfg $config
|
|
. ./target/$ROCKCFG_TARGET/build.sh
|
|
echo_header "Finished building this target."
|
|
echo_status "Going to run cleanup procedure now.."
|
|
} 2>&1 201>> "${build_logs}/build_target_$$.log" | \
|
|
tee -a "${build_logs}/build_target_$$.log"
|
|
|
|
if [ "$ROCKCFG_SENDMAIL" = 1 ]; then
|
|
$ROCKCFG_SENDMAIL_BIN $ROCKCFG_SENDMAIL_TO << EOT
|
|
Subject: [ROCK Build-Target] $config finished.
|
|
|
|
Finished building $config.
|
|
EOT
|
|
fi
|
|
|