File build of Package build
#!/bin/bash
# Script to build a package. It uses init_buildsystem to setup a chroot
# building tree. This script needs a directory as parameter. This directory
# has to include sources and a recipe file.
#
# BUILD_ROOT here the packages will be built
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
# Copyright (c) 2022 Andreas Stieger <Andreas.Stieger@gmx.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
# some VMs do not allow to specify the init process...
if test "$0" = /sbin/init ; then
exec /.build/build "$@"
fi
BUILD_CONF=/etc/build.conf
# ignore BUILD_DIR if we have a config
test -e "$BUILD_CONF" && BUILD_DIR=/usr/lib/build
test -z "$BUILD_DIR" -a -e /.build/build.data -a -z "$BUILD_IGNORE_2ND_STAGE" && BUILD_DIR=/.build
test -z "$BUILD_DIR" && BUILD_DIR=/usr/lib/build
test -z "$BUILD_ROOT" && BUILD_ROOT=/var/tmp/build-root
test -z "$CONFIG_DIR" && CONFIG_DIR="$BUILD_DIR/configs"
export BUILD_ARCH BUILD_HOST_ARCH BUILD_ROOT BUILD_RPMS BUILD_DIR BUILD_DEBUG
export BUILD_DIST ABUILD_UID ABUILD_GID
icecream=0
definesnstuff=()
repos=()
old_packages=()
# slurp in vm support
. "$BUILD_DIR/build-vm"
# slurp in recipe support
. "$BUILD_DIR/build-recipe"
# slurp in package binary support
. "$BUILD_DIR/build-pkg"
# slurp in validation support
. "$BUILD_DIR/build-validate-params"
# need to restore build root owner for non-root builds
browner=
# Default uid:gid for the build user
ABUILD_UID=399
ABUILD_GID=399
BUILD_OPTIONS_PARSED=
DO_INIT=true
DO_INIT_TOPDIR=true
DO_LINT=
DO_CHECKS=true
CLEAN_BUILD=
GENBUILDREQS_CLEAN_BUILD=
RECIPEFILES=()
RECIPEPATH=
SRCDIR=
BUILD_JOBS=
BUILD_THREADS=
ABUILD_TARGET=
CREATE_BASELIBS=
USEUSEDFORBUILD=
LIST_STATE=
RUNNING_IN_VM=
RPMLIST=
RELEASE=
REASON=
NOROOTFORBUILD=
LOGFILE=
KILL=
DO_WIPE=
SEND_SYSRQ=
CHANGELOG=
BUILD_DEBUG=
INCARNATION=
DISTURL=
LINKSOURCES=
OVERLAY=
RSYNCSRC=
RSYNCDEST=
RSYNCDONE=
SIGNDUMMY=
DO_STATISTICS=
RUN_SHELL=
RUN_SHELL_AFTER_FAIL=
RUN_SHELL_CMD=
CCACHE=
CCACHE_ARCHIVE=
CCACHE_CREATE_ARCHIVE=
CCACHE_TYPE=
CCACHE_CLEAN=
DLNOSIGNATURE=
BUILD_FLAVOR=
OBS_PACKAGE=
OBSURL=
NO_TIMESTAMPS=
CACHE_DIR=
BUILD_DIST_TMP=
BUILD_SUCCEEDED=
COPY_SOURCES_ASIS=
RECIPE_BUILD_START_TIME=
CCACHE_SETUP_START_TIME=
# set all verbose modes to off by default
BUILD_VERBOSE_VM=
# This is for insserv
export YAST_IS_RUNNING=instsys
# https://github.com/systemd/systemd/blob/master/docs/ENVIRONMENT.md
export SYSTEMD_OFFLINE=1
unset LANGUAGE
unset LANG
export LC_ALL=POSIX
umask 022
echo_help () {
cat << EOT
Some comments for build
-----------------------
With build you can create binary packages. They will be built in a chroot
system. This chroot system will be setup automatically. Normally you can
simply call build with a spec file as parameter - nothing else has to be
set.
If you want to set the directory where the chroot system will be setup
(at the moment it uses $BUILD_ROOT),
simply set the the environment variable BUILD_ROOT.
Example:
export BUILD_ROOT=/var/tmp/mybuildroot
Normally build builds the complete package including src.rpm (rpmbuild -ba).
If you want to let build only make the binary package, simply set
export BUILD_RPM_BUILD_STAGE=-bb
(or -bc, -bp, -bi, ... see "Maximum RPM" for more details [*]).
When the build command succeeds, the rpm files can be found under
$BUILD_ROOT/usr/src/packages/RPMS/
Known Parameters:
--help You already got it :)
--kill Instead of starting a build kill the one currently
running.
--shell Instead of starting a build start a root shell in
the build root.
--shell-cmd CMD
Run the command CMD instead of giving a root shell
--shell option is implicit set.
--sysrq $ Sends a single specifed char as sysrq to the running
kernel of the build.
--clean Delete old build root before initializing it
--wipe Completely removes build environment and exits.
--no-init Skip initialization of build root and start with build
immediately.
--no-checks Do not run checks (postbuild and %check)
--logfile logfile
Capture build output to logfile. Defaults to
.build.log in the build root for non-VM builds.
--no-timestamps
Hide the time prefix in output and logfile.
--repo PATH_OR_URL
Use package repository at PATH_OR_URL. Supported formats
are rpm-md, yast2, debian, and arch linux.
Alternatively zypp://NAME specifies the zypp
repository NAME. The repo must be refreshed with zypp
so package meta data is available locally. With emtpy
NAME all enabled repositories are used.
--rpms path1:path2:...
Specify path where to find the RPMs for the build system
--arch arch1:arch2:...
Specify what architectures to select from the RPMs
--verify Run verify when initializing the build root
--extra-packs pack
-X pack
Also install package 'pack'
--root rootdir
Use 'rootdir' to setup chroot environment
--cachedir cachedir
Use 'cachedir' to cache remote repo's packages. The
default cache dir is /var/cache/build, every repo
given by --repo corresponds to a subdir named
as md5sum of its repo url, for example:
/var/cache/build/3e8ea9b47808629414a0cebc33ea285e
--oldpackages oldpackagesdir
Define a directory with a former build
--baselibs Create -32bit/-64bit/-x86 rpms for other architectures
--list-state
List rpms that would be used to create a fresh build root.
Does not create the build root or perform a build.
--dist dist
Distribution to use
--with X
Enable feature X for build
--without X
Disable feature X for build
--define 'X Y'
Define macro X with value Y
--release RELEASE
Override the Release line in the spec file
--stage STAGE
Set stage for rpmbuild. Defaults to 'a'. Append a trailing '='
to only run the specified stage. Append a trailing '+' to run
the specified stage and all stages coming after it. With no
suffix, stages up to and included the specified stage are run.
--target platform
Set target platform for rpmbuild
--jobs N Use N parallel processes during build.
Sets %jobs and %_smp_mflags macros and
defines the number of CPUs to use for
VMs.
--threads N sets number of threads for VM
--ccache
Use ccache to speed up rebuilds
--ccache=sccache
Use sccache to speed up rebuilds
--ccache-archive /path/to/ccache.tar
Path to archive of ccache directory content.
Its contents will be extracted to /.ccache
Implies --ccache.
--icecream N
Use N parallel build jobs with icecream
--overlay OVERLAY
Copy overlay filesystem to buildroot after installing
all RPMs. This must be a valid directory.
--rsync-src RSYNCSRC
Copy overlay folder (RSYNCSRC) to a folder (RSYNCDEST)
inside the buildroot using rsync.
It will "%define RSYNCDONE 1" for handling %setup in your
specfile. E.g.:
%prep
%if 0%{?RSYNCDONE}
%setup -n aaa_base -T -D -b 5 -b 7
%else
%setup -n aaa_base -b 5 -b 7
%endif
--rsync-dest RSYNCDEST
Copy overlay folder (RSYNCSRC) to a folder (RSYNCDEST)
inside the buildroot using rsync.
--uid uid:gid
Specify the uid and gid to use for the abuild user.
This is useful if you are hacking in the buildroot.
This must be set to the same value if the buildroot is re-used.
--statistics
monitor used resources during build inside VM
--kvm
Use KVM to secure build process. Your hardware needs to support
virtualization
--xen
Use XEN to secure build process, you to run in a XEN Dom0 environment.
--lxc
Use Linux Containers to isolate the process. This may not be 100% safe.
--openstack
Cloud build
--ec2
Cloud build
--emulator
Use any generic emulator to isolate the build process. You need to write
an emulator/emulator.sh script and put it next to the build script sources.
--emulator-script SCRIPT
specify another emulator instead of emulator.sh
--verbose CLASS
Verbose output, CLASS can be 'all' or a specific one:
vm: includes kernel and initrd messages
--vm-type TYPE
Use virtual machine instead of chroot
TYPE is one of xen|kvm|uml|qemu|lxc|zvm|openstack|ec2|docker|pvm|nspawn
--vm-args ARGS
Pass extra arguments to virtual machine
To pass multiple arguments, separate them with spaces
Use regular shell quotes if arguments contain spaces
--vm-worker GUEST
GUEST is a z/VM build worker controlled by the controlling
z/VM build machine.
--vm-worker-nr N
Each worker in z/VM needs a uniq number. This is needed to
calculate uniq device addresses for root and swap device.
--vm-region NAME
EC2 only: defines amazon control server
--vm-server NAME
openstack only: defines control server name
--vm-disk FILE
Use FILE as disk for virtual machine.
Defaults to \$BUILD_ROOT.img if unset
--vm-swap FILE
Use FILE as swap space for virtual machine. The swap space is
also used for retrieving packages from the VM so its size must
be sufficiently large
--vm-disk-size SIZEINMB
--vm-swap-size SIZEINMB
--vm-disk-filesystem TYPE
Defaults for automatic setup of VM root/swap files.
May get overruled by build config vmfstype build flag.
--vm-disk-filesystem-options OPTIONS
nodirindex: disable dir indexing on ext filesystems. Slower,
but more reproducible builds
--vm-use-mkfs-copyin
Avoid mounting in the preinstall phase for VM builds. Instead,
copy files into the filesystem during filesystem creation time.
Currently limited to the ext filesystems.
--vm-memory SIZEINMB
Set amount of RAM for VMs
--vm-hugetlbfs HUGETLBFSPATH
Use hugetlb for memory management, path to mounted hugetlbfs.
--vm-kernel FILE
--vm-initrd FILE
--vm-cmdline STRING
Kernel and initrd to use for VM (kvm and qemu only)
Cmdline to specify additional arguments
--vm-user USERNAME
User name to run qemu/kvm process
--vm-telnet PORT
Forward the PORT to a telnet session inside of the VM.
Specify the needed extra packages via -x parameter, usually:
--vm-telnet 1234 -x telnet-server -x net-tools
And connect from the host via
telnet 1234
The telnet server is started after all packages got installed.
--vm-network
Enable network inside of VM with the default qemu SLIRP user network.
WARNING: this breaks reproducibility and allows to attack your network
when building untrusted content.
--vm-net OPTION
--vm-netdev OPTION
--vm-device OPTION
KVM only: Attach kvm option
Available options are -net, -netdev, -device
(This options in kvm can not guarantee reproducible builds)
--debuginfo
Enable creation of debuginfo packages
--buildflavor FLAVOR
Specify the flavor to build. For rpm builds, it replaces
the @BUILD_FLAVOR@ macro in the spec file.
--changelog
Append the rpm changelog from a SUSE .changes file to the spec file
--norootforbuild
Force building with user 'abuild', ignore the "needsrootforbuild"
hint from the recipe file
Remember to have fun!
[*] Maximum RPM: http://www.rpm.org/max-rpm/
EOT
}
usage () {
cleanup_and_exit 1 "Usage: `basename $0` [--no-init|--clean|--rpms path|--verify|--help] [dir-to-build|recipe-to-build]"
}
#
# cleanup_and_exit
# return values: 0 -> success, new packages built
# 1 -> error, build failed
# 2 -> successfull build, but no changes to former built packages
# 3 -> something wrong with build or the host, leads to a retry
# 4 -> something FATAL with build or the host, leads to a retry, but do not build on this host anymore
#
cleanup_and_exit () {
trap EXIT
test -z "$1" && set 0
if test -n "$2" ; then
if test "$1" -ne 0 ; then
echo "$2" >&2
else
echo "$2"
fi
fi
test -n "$BUILD_DIST_TMP" && rm -f "$BUILD_DIST_TMP"
if test -z "$BUILD_OPTIONS_PARSED" ; then
# if we have not yet parsed the options we do
# not know the correct build root. just exit.
exit $1
fi
rm -f $BUILD_ROOT/exit
# run a shell in failure case if wanted by user
if test -n "$RUN_SHELL_AFTER_FAIL" -a "$BUILD_SUCCEEDED" = false -a "$1" = 1 ; then
unset BUILD_SUCCEEDED
run_shell $1
fi
# add build time statistics
recipe_build_time_statistics
# Never inside of VM
# but for chroot or the filesystem hosting the root file
if test -z "$RUNNING_IN_VM" ; then
# check for disk full for an automatic build retry
if test "$1" -eq 1 -a -x /bin/df ; then
echo
echo "$HOST failed \"build $RECIPEFILE\" at `date --utc`."
echo
# okay, it failed, but maybe because disk space?
if df $BUILD_ROOT 2>/dev/null | grep -q "100%"; then
df $BUILD_ROOT 2>/dev/null
echo
echo "$HOST ran out of disk space. Please try again."
echo
set 3
fi
fi
fi
if test -z "$VM_TYPE" -o -n "$RUNNING_IN_VM" ; then
# run recipe cleanup code
test -n "$BUILDTYPE" && recipe_cleanup
fi
# shutdown
if test -n "$RUNNING_IN_VM" ; then
echo "$1" > /.build/_exitcode
test -n "$browner" && chown "$browner" $BUILD_ROOT
vm_shutdown "$1"
else
buildroot_umount /proc/sys/fs/binfmt_misc
buildroot_umount /proc
buildroot_umount /sys
buildroot_umount /dev/pts
buildroot_umount /dev/shm
test -n "$VM_ROOT" -a "$VM_ROOT" != 1 && umount $BUILD_ROOT 2>/dev/null || true
test -n "$VM_TYPE" && vm_cleanup
fi
exit $1
}
fail_exit() {
cleanup_and_exit 1
}
shellquote() {
for arg ; do
arg=${arg//\\/\\\\}
arg=${arg//\$/\\\$}
arg=${arg//\"/\\\"}
arg=${arg//\`/\\\`}
echo -n " \"$arg\""
done
}
# create a shell script from command line. Used for preserving arguments
# through /bin/su -c
toshellscript() {
echo "#!/bin/sh -x"
echo -n exec
shellquote "$@"
echo
}
ccache_unpack() {
local dir="$1"
local ty="$2"
echo "Unpacking $ty archive"
tar -xf "$CCACHE_ARCHIVE" -C "$dir/"
if test -s "$dir/.build.ccache.type" ; then
local t
read t < "$dir/.build.ccache.type"
if test "$ty" != "$t" ; then
echo "$ty archive is of type $t, cleaning cache"
rm -rf "$dir"
mkdir -p "$dir"
fi
rm -f "$dir/.build.ccache.type"
fi
}
ccache_pack() {
local dir="$1"
local ty="$2"
echo "... saving $ty archive"
rm -rf "$dir/.build.ccache.type"
local remove_files
test -n "$RUNNING_IN_VM" -a -n "$CCACHE_CLEAN" && remove_files="--remove-files"
echo "$ty" > "$dir/.build.ccache.type"
tar $remove_files -cf "$BUILD_ROOT/$TOPDIR/OTHER/_ccache.tar" -C "$dir/" .
rm -f "$dir/.build.ccache.type"
}
ccache_setup() {
CCACHE_SETUP_START_TIME=
if test -n "$CCACHE" -a "$CCACHE_TYPE" = sccache ; then
sccache_setup
return
fi
if test -n "$CCACHE" -a "$CCACHE_TYPE" = ccache ; then
CCACHE_SETUP_START_TIME=$SECONDS
if mkdir -p $BUILD_ROOT/var/lib/build/ccache/bin; then
for i in $(ls $BUILD_ROOT/usr/bin | grep -E '^(cc|gcc|[cg][+][+]|clang|clang[+][+])([-]?[.0-9])*$'); do
rm -f $BUILD_ROOT/var/lib/build/ccache/bin/$i
test -e $BUILD_ROOT/usr/bin/$i || continue
echo '#! /bin/sh' > $BUILD_ROOT/var/lib/build/ccache/bin/$i
echo "test -e /usr/bin/$i || exit 1" >> $BUILD_ROOT/var/lib/build/ccache/bin/$i
echo 'export PATH=/usr/lib/icecc/bin:/opt/icecream/bin:/usr/bin:$PATH' >> $BUILD_ROOT/var/lib/build/ccache/bin/$i
echo "ccache $i \"\$@\"" >> $BUILD_ROOT/var/lib/build/ccache/bin/$i
chmod 755 $BUILD_ROOT/var/lib/build/ccache/bin/$i
echo "Installed ccache wrapper as $BUILD_ROOT/var/lib/build/ccache/bin/$i"
done
fi
mkdir -p "$BUILD_ROOT/.ccache"
echo 'export PATH=/var/lib/build/ccache/bin:$PATH' > "$BUILD_ROOT"/etc/profile.d/build_ccache.sh
local cconf="$BUILD_ROOT"/etc/ccache.conf
if test -e $cconf; then
grep -q "^compression*" $cconf && sed -i "s:compression.*:compression = true:g" $cconf || echo "compression = true" >> $cconf
grep -q "^cache_dir*" $cconf && sed -i "s:cache_dir.*:cache_dir = /.ccache:g" $cconf || echo "cache_dir = /.ccache" >> $cconf
else
echo "compression = true" >> $cconf
echo "cache_dir = /.ccache" >> $cconf
fi
test -n "$CCACHE_ARCHIVE" -a -e "$CCACHE_ARCHIVE" && ccache_unpack "$BUILD_ROOT/.ccache" ccache
chown -hR "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT/.ccache"
else
rm -f "$BUILD_ROOT"/var/lib/build/ccache/bin/{gcc,g++,cc,c++,clang,clang++}
fi
}
ccache_wrapup() {
if test -n "$CCACHE" -a "$CCACHE_TYPE" = sccache ; then
sccache_wrapup
return
fi
if test -n "$CCACHE" -a "$CCACHE_TYPE" = ccache ; then
if test -n "$CCACHE_CLEAN" ; then
echo "... cleaning ccache"
test_cmd="ccache -h | grep -c evict-older-than"
clean_cmd="ccache --evict-older-than $(( $SECONDS - $CCACHE_SETUP_START_TIME ))s"
chroot $BUILD_ROOT su -c "$test_cmd && $clean_cmd" - $BUILD_USER
fi
test -n "$CCACHE_CREATE_ARCHIVE" && ccache_pack "$BUILD_ROOT/.ccache" ccache
fi
}
sccache_setup() {
if test -n "$CCACHE" -a "$CCACHE_TYPE" = sccache ; then
CCACHE_SETUP_START_TIME=$SECONDS
# This first redir clears the file.
echo 'export CARGO_INCREMENTAL=false' > "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
echo 'export RUSTC_WRAPPER=sccache' >> "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
echo 'export CC="sccache cc"' >> "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
echo 'export CXX="sccache c++"' >> "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
if test "$CCACHE_ARCHIVE" != "${CCACHE_ARCHIVE#redis://}" ; then
echo "export SCCACHE_REDIS=${CCACHE_ARCHIVE}" >> "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
else
echo 'export SCCACHE_DIR="/.sccache"' >> "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
echo 'export SCCACHE_CACHE_SIZE="1280M"' >> "$BUILD_ROOT"/etc/profile.d/build_sccache.sh
mkdir -p "$BUILD_ROOT/.sccache"
test -n "$CCACHE_ARCHIVE" -a -e "$CCACHE_ARCHIVE" && ccache_unpack "$BUILD_ROOT/.sccache" sccache
chown -hR "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT/.sccache"
fi
# Display sccache status at the start of the build.
chroot $BUILD_ROOT su -c "sccache -s" - $BUILD_USER
fi
}
sccache_wrapup() {
if test -n "$CCACHE" -a "$CCACHE_TYPE" = sccache ; then
# Display sccache statistics post build.
chroot $BUILD_ROOT su -c "sccache -s" - $BUILD_USER
# Pack archive unless redis was used
if test -n "$CCACHE_CREATE_ARCHIVE" ; then
if test "$CCACHE_ARCHIVE" = "${CCACHE_ARCHIVE#redis://}" ; then
ccache_pack "$BUILD_ROOT/.sccache" sccache
fi
fi
fi
}
setupicecream() {
local icecreamdir=/var/run/icecream
if test "$(readlink "$BUILD_ROOT/var/run")" = /run ; then
icecreamdir=/run/icecream
fi
if test "$icecream" -eq 0 ; then
rm -rf "$BUILD_ROOT$icecreamdir"
rm -f "$BUILD_ROOT/etc/profile.d/build_icecream.sh"
return 0
fi
if ! chroot "$BUILD_ROOT" rpm -q icecream >/dev/null 2>/dev/null; then
echo "*** icecream package not installed ***"
return 1
fi
echo "using icecream with $icecream jobs"
if test -z "$CCACHE" ; then
echo 'export PATH=/usr/lib/icecc/bin:/opt/icecream/bin:$PATH' > "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
else
echo 'export CCACHE_PATH=/usr/lib/icecc/bin:/opt/icecream/bin' > "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
fi
local icecc_vers=(`shopt -s nullglob; echo $BUILD_ROOT$icecreamdir/*.tar.{bz2,gz}`)
icecc_vers=${icecc_vers//$BUILD_ROOT/}
# XXX use changelog like autobuild does instead?
# only run create-env if compiler or glibc changed
if test -z "$icecc_vers" \
-o ! -e "$BUILD_ROOT/$icecc_vers" \
-o "$BUILD_ROOT/usr/bin/gcc" -nt "$BUILD_ROOT/$icecc_vers" \
-o "$BUILD_ROOT/usr/bin/g++" -nt "$BUILD_ROOT/$icecc_vers" \
-o "$BUILD_ROOT/usr/bin/as" -nt "$BUILD_ROOT/$icecc_vers" \
-o "$BUILD_ROOT/lib/libc.so.6" -nt "$BUILD_ROOT/$icecc_vers"
then
rm -rf "$BUILD_ROOT$icecreamdir"
mkdir -p "$BUILD_ROOT$icecreamdir"
if test -e "$BUILD_ROOT"/usr/bin/create-env ; then
createenv=/usr/bin/create-env
elif test -e "$BUILD_ROOT"/usr/lib/icecc/icecc-create-env ; then
createenv="/usr/lib/icecc/icecc-create-env /usr/bin/gcc /usr/bin/g++" # XXX
elif test -e "$BUILD_ROOT"/usr/lib64/icecc/icecc-create-env ; then
createenv="/usr/lib64/icecc/icecc-create-env /usr/bin/gcc /usr/bin/g++" # XXX
else
echo "create-env not found"
return 1
fi
echo "creating new env in '$icecreamdir'"
chroot $BUILD_ROOT bash -c "cd $icecreamdir; $createenv" || cleanup_and_exit 1
icecc_vers=(`shopt -s nullglob; echo $BUILD_ROOT/$icecreamdir/*.tar.{bz2,gz}`)
icecc_vers=${icecc_vers//$BUILD_ROOT/}
echo "created icecream environment $icecc_vers"
else
echo "reusing existing icecream environment $icecc_vers"
fi
if test -n "$icecc_vers" ; then
echo "export ICECC_VERSION=$icecc_vers" >> "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
fi
}
setmemorylimit() {
if test -n "$VM_ROOT" -o -n "$RUNNING_IN_VM" ; then
return
fi
local mem
local limit
while read mem; do
case "$mem" in
MemTotal:*)
set -- $mem
eval "limit=\$(($2/3*2))"
;;
SwapTotal:*)
set -- $mem
eval "limit=\$(($2/3*2+$limit))"
;;
esac
done < <(cat /proc/meminfo) # cat for proc stuff
ulimit -d $limit
echo "Memory limit set to ${limit}KB"
}
create_baselibs() {
local pkgs=()
local line
BASELIBS_CFG=
if test "$BUILDTYPE" == arch || test "$BUILDTYPE" = collax ; then
return
fi
if test "$BUILDTYPE" == dsc ; then
pkgs=($DEBS)
else # spec and kiwi
if test -e $BUILD_ROOT$TOPDIR/SOURCES/baselibs.conf ; then
BASELIBS_CFG="-c $TOPDIR/SOURCES/baselibs.conf"
fi
if test -e $BUILD_ROOT/usr/lib/build/baselibs_global.conf; then
BASELIBS_GLOBAL="-c /usr/lib/build/baselibs_global.conf"
fi
pkgs=($RPMS)
fi
# don't use -R as extracted sources, build root etc might be below $TOPDIR
chown "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT$TOPDIR"/* "$BUILD_ROOT$TOPDIR"/RPMS/* || true
local mkbaselibs="/usr/lib/build/mkbaselibs"
local whichone=''
# $BUILD_DIR is set to /.build when using a vm. So we need to
# hardcode /usr/lib/build instead of $BUILD_DIR to prefer
# mkbaselibs from the distro.
if test -f $BUILD_ROOT$mkbaselibs; then
if test -z "$BASELIBS_CFG" -a -e $BUILD_ROOT/usr/lib/build/baselibs.conf ; then
BASELIBS_CFG="-c /usr/lib/build/baselibs.conf"
fi
else
if test "$CREATE_BASELIBS" = 'internal'; then
echo "Warning: mkbaselibs missing in build root, skipping baselibs"
return
fi
# use external version
whichone=" (external)"
mkbaselibs="/.mkbaselibs/mkbaselibs"
rm -rf "$BUILD_ROOT/.mkbaselibs"
mkdir -p "$BUILD_ROOT/.mkbaselibs"
cp -f $BUILD_DIR/mkbaselibs $BUILD_ROOT/.mkbaselibs/
if test "$BUILDTYPE" == "dsc" ; then
cp -f $BUILD_DIR/baselibs_global-deb.conf $BUILD_ROOT/.mkbaselibs/baselibs_g.conf
cp -f $BUILD_ROOT$TOPDIR/SOURCES/baselibs-deb.conf $BUILD_ROOT/.mkbaselibs/baselibs-deb.conf
BASELIBS_CFG="-c /.mkbaselibs/baselibs-deb.conf"
else
cp -f $BUILD_DIR/baselibs_global.conf $BUILD_ROOT/.mkbaselibs/baselibs_g.conf
if test -z "$BASELIBS_CFG" -a -e $BUILD_DIR/baselibs.conf; then
cp -f $BUILD_DIR/baselibs.conf $BUILD_ROOT/.mkbaselibs/baselibs.conf
BASELIBS_CFG="-c /.mkbaselibs/baselibs.conf"
fi
fi
if test -e $BUILD_ROOT/.mkbaselibs/baselibs_g.conf; then
BASELIBS_GLOBAL="-c /.mkbaselibs/baselibs_g.conf"
fi
fi
echo "... creating baselibs$whichone"
while read line; do
chroot $BUILD_ROOT su -c "$mkbaselibs $BASELIBS_GLOBAL $BASELIBS_CFG $line" - $BUILD_USER || cleanup_and_exit 1
done < <(IFS=$'\n'; echo "${pkgs[*]#$BUILD_ROOT}" | xargs -n 1024)
rm -rf "$BUILD_ROOT/.mkbaselibs"
}
copy_oldpackages() {
local i=0
local d
local dest
test -z "$RUNNING_IN_VM" || return 0
if test -z "$old_packages" ; then
rm -rf "$BUILD_ROOT"/.build.oldpackages*
return 0
fi
for d in "${old_packages[@]}"; do
dest="$BUILD_ROOT/.build.oldpackages"
test "$i" = 0 || dest="$dest$i"
if test -d "$d" -a "$d" != "$dest" ; then
rm -rf "$dest"
mkdir -p "$dest"
cp -L $d/* "$dest"
: $((++i))
fi
done
}
copy_sources() {
local include_directories
if test -n "$RUNNING_IN_VM" -o "$BUILDTYPE" = kiwi -o "$BUILDTYPE" = docker -o "$BUILDTYPE" = fissile -o "$BUILDTYPE" = podman ; then
include_directories=true
fi
if test -n "$RUNNING_IN_VM" -o -n "$COPY_SOURCES_ASIS" -o -n "$RPM_BUILD_IN_PLACE" ; then
( shopt -s nullglob ; cp -pRd "$1/".[^.]* "$1/"..?* "$1"/* "$2" )
elif test -n "$include_directories" ; then
cp -pRL "$1"/* "$2"
elif test -e "$1/.git" ; then
# check which directory belongs to the git repository and only copy those
type -p git >& /dev/null || cleanup_and_exit 1 "need git to check file status"
for i in "$1/".* "$1"/* ; do
local ii="${i##*/}"
test "$ii" = . -o "$ii" = .. -o "$ii" = .git && continue
if test -L "$i" -o -d "$i" -o "${ii#.}" != "$ii" ; then
if test -e "$i/.build.asset" || git -C "$1" --noglob-pathspecs ls-files --error-unmatch -- "$ii" >& /dev/null ; then
cp -pRd "$i" "$2"
continue
fi
test "${ii#.}" != "$ii" && continue
fi
cp -p "$i" "$2"
done
if test -f "$1/debian/control" ; then
echo "exporting debian orig tarballs"
$BUILD_DIR/export_debian_orig_from_git "$1" "$2/build.origtar" || cleanup_and_exit 1 "export_debian_orig_from_git failed"
fi
else
cp -p "$1"/* "$2"
fi
test -n "$RPM_BUILD_IN_PLACE" -a -z "$RUNNING_IN_VM" && cp -f "$RECIPEPATH" "$2"
}
mkdir_build_root() {
# strip trailing slash
test "$BUILD_ROOT" != / && BUILD_ROOT="${BUILD_ROOT%/}"
if test -d "$BUILD_ROOT" ; then
# check if it is owned by root
if test -z "$RUNNING_IN_VM" -a \! -O "$BUILD_ROOT" -a "`stat -c %u $BUILD_ROOT`" -ne 0 ; then
cleanup_and_exit 1 "BUILD_ROOT=$BUILD_ROOT must be owned by root. Exit..."
fi
else
test "$BUILD_ROOT" != "${BUILD_ROOT%/*}" && mkdir -p "${BUILD_ROOT%/*}"
if ! mkdir $BUILD_ROOT ; then
cleanup_and_exit 1 "can not create BUILD_ROOT=$BUILD_ROOT. Exit..."
fi
fi
if test ! -w "$BUILD_ROOT" ; then
cleanup_and_exit 4 "Error: BUILD_ROOT=$BUILD_ROOT not writeable, try --clean."
fi
rm -rf "$BUILD_ROOT/.build.packages"
if test -z "$VM_TYPE" -a -z "$RUNNING_IN_VM" ; then
# don't touch this in VM
rm -rf "$BUILD_ROOT/.build"
mkdir -p "$BUILD_ROOT/.build"
fi
}
copy_overlay() {
if test -d "$OVERLAY"; then
pushd $OVERLAY
echo "Copying overlay to BUILD_ROOT"
tar -cpf - . | (cd $BUILD_ROOT ; tar -xvf -)
popd
else
echo "OVERLAY ($OVERLAY) is no directory - skipping"
fi
}
run_rsync() {
if test -n "$RSYNCDEST" ; then
if test -d "$RSYNCSRC" ; then
if ! test -d "$BUILD_ROOT/$RSYNCDEST" ; then
echo "ATTENTION! Creating missing target directory ($BUILD_ROOT/$RSYNCDEST)."
mkdir -p $BUILD_ROOT/$RSYNCDEST
fi
echo "Running rsync ..."
rsync -av $RSYNCSRC/* $BUILD_ROOT/$RSYNCDEST/
chown -hR "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT/$RSYNCDEST"
RSYNCDONE=true
echo "... done"
else
echo "RSYNCSRC is not a directory - skipping"
fi
else
echo "RSYNCSRC given, but not RSYNCDEST - skipping"
fi
}
wipe_build_environment() {
if test -n "$VM_TYPE" ; then
vm_img_wipe
else
echo "Wiping build root: '$BUILD_ROOT'"
# unmount all mounts still in the build root path
for m in $(cat /proc/mounts | grep "$BUILD_ROOT" | awk '{ print $2 }'); do
if ! umount -n "$m" 2>/dev/null ; then
echo "Failed to umount "$m", cannot wipe buildroot"
exit 1
fi
done
rm -rf "$BUILD_ROOT"
fi
}
sysrq_running_build() {
test -z "$SRCDIR" || usage
if test -n "$VM_TYPE" ; then
vm_sysrq "$1"
else
cleanup_and_exit 1 "can not send a sysrq to chroot builds"
fi
}
kill_running_build() {
test -z "$SRCDIR" || usage
(set -C; > "$BUILD_ROOT/exit" || true) 2>/dev/null
if test -n "$VM_TYPE" ; then
# mark job as failed so that we don't extract packages
vm_set_buildstatus 1
vm_kill
else
if ! $BUILD_DIR/killchroot -s 9 $BUILD_ROOT ; then
cleanup_and_exit 1 "could not kill build in $BUILD_ROOT"
fi
fi
}
mount_stuff() {
if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
test -d $BUILD_ROOT/dev/shm || rm -f $BUILD_ROOT/dev/shm
mkdir -p $BUILD_ROOT/proc
mkdir -p $BUILD_ROOT/sys
mkdir -p $BUILD_ROOT/dev/pts
mkdir -p $BUILD_ROOT/dev/shm
mount -n -tproc none $BUILD_ROOT/proc
mount -n -tsysfs none $BUILD_ROOT/sys
mount -n -tdevpts -omode=0620,ptmxmode=0666,gid=5 none $BUILD_ROOT/dev/pts
mount -n -ttmpfs none $BUILD_ROOT/dev/shm
fi
}
umount_stuff() {
if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
buildroot_umount /proc/sys/fs/binfmt_misc
buildroot_umount /proc
buildroot_umount /sys
buildroot_umount /dev/pts
buildroot_umount /dev/shm
fi
}
#### main ####
trap fail_exit EXIT
. $BUILD_DIR/common_functions || exit 1
detect_cache_dir
shopt -s nullglob
export PATH=$BUILD_DIR:/sbin:/usr/sbin:/bin:/usr/bin:$PATH
if vm_detect_2nd_stage ; then
set "/.build-srcdir/$RECIPEFILE"
export PATH=/.build:$PATH
fi
export HOST
needarg() {
if test -z "$ARG" ; then
cleanup_and_exit 1 "$PARAM needs an agrument"
fi
}
run_shell() {
local ex="$1"
echo "Executing interactive shell..."
if test -n "$RUN_SHELL_CMD"; then
chroot $BUILD_ROOT "$RUN_SHELL_CMD"
cleanup_and_exit ${ex:-$?}
else
chroot $BUILD_ROOT su - $BUILD_USER
cleanup_and_exit ${ex:-$?}
fi
}
validate_init "$BUILD_CONF"
while test -n "$1"; do
PARAM="$1"
ARG="$2"
test "$ARG" = "${ARG#-}" || ARG=
shift
case $PARAM in
*-*=*)
ARG=${PARAM#*=}
PARAM=${PARAM%%=*}
set -- "----noarg=$PARAM" "$@"
;;
esac
case ${PARAM/#--/-} in
-help|-h)
echo_help
cleanup_and_exit
;;
-noinit|-no-init)
test "$DO_INIT" = false && DO_INIT_TOPDIR=false
DO_INIT=false
;;
-nochecks|-no-checks)
DO_CHECKS=false
;;
-clean)
test "$CLEAN_BUILD" = '--clean' && GENBUILDREQS_CLEAN_BUILD='--clean'
CLEAN_BUILD='--clean'
CCACHE_CLEAN="$CLEAN_BUILD"
;;
-wipe)
DO_WIPE=true
;;
-kill)
KILL=true
;;
-rpms)
needarg
BUILD_RPMS="$ARG"
shift
;;
-arch)
needarg
BUILD_ARCH="$ARG"
shift
;;
-hostarch|-host-arch)
needarg
BUILD_HOST_ARCH="$ARG"
shift
;;
-verify)
export VERIFY_BUILD_SYSTEM=true
;;
-target)
needarg
ABUILD_TARGET="$ARG"
shift
;;
-jobs)
needarg
BUILD_JOBS="$ARG"
shift
;;
-threads)
needarg
BUILD_THREADS="$ARG"
shift
;;
-extrapacks|-extra-packs|-X)
needarg
BUILD_EXTRA_PACKS="$BUILD_EXTRA_PACKS $ARG"
shift
;;
-lint)
# OBSOLETE: just keeping it for compability
DO_LINT=true
;;
-baselibs)
CREATE_BASELIBS=true
;;
-baselibs-internal)
CREATE_BASELIBS=internal
;;
-root)
needarg
BUILD_ROOT="$ARG"
shift
;;
-cachedir)
needarg
CACHE_DIR="$ARG"
shift
;;
-oldpackages)
needarg
old_packages=("${old_packages[@]}" "$ARG")
shift
;;
-dist)
needarg
BUILD_DIST="$ARG"
shift
;;
-release)
needarg
RELEASE="$ARG"
shift
;;
-logfile)
needarg
LOGFILE="$ARG"
shift
;;
-no-timestamps)
NO_TIMESTAMPS=true
;;
-reason)
needarg
REASON="$ARG"
shift
;;
-norootforbuild)
NOROOTFORBUILD=true
;;
-useusedforbuild)
USEUSEDFORBUILD="--useusedforbuild"
;;
-configdir)
needarg
CONFIG_DIR="$ARG"
shift
;;
-list*state)
LIST_STATE=true
;;
-define|-with|-without)
needarg
PARAM="-${PARAM/#--/-}"
definesnstuff[${#definesnstuff[@]}]="$PARAM"
definesnstuff[${#definesnstuff[@]}]="$ARG"
shift
;;
-repository|-repo)
needarg
repos[${#repos[@]}]="--repository"
repos[${#repos[@]}]="$ARG"
shift
;;
-icecream)
needarg
icecream="$ARG"
test "$icecream" -gt 0 && BUILD_JOBS="$ARG"
shift
;;
-ccache)
CCACHE=true
if test "$1" != "${1#--noarg=}" ; then
needarg
CCACHE_TYPE="$ARG"
shift
fi
;;
-ccache-type)
needarg
CCACHE_TYPE="$ARG"
shift
;;
-pkg-ccache|-ccache-archive)
needarg
CCACHE_ARCHIVE="$ARG"
shift
CCACHE=true
;;
-ccache-create-archive)
CCACHE_CREATE_ARCHIVE=true
;;
-sccache)
CCACHE=true
CCACHE_TYPE=sccache
shift
;;
-sccache-uri|-sccache-archive)
needarg
CCACHE_ARCHIVE="$ARG"
shift
CCACHE=true
CCACHE_TYPE=sccache
;;
-statistics)
DO_STATISTICS=1
;;
-debug|-debuginfo)
BUILD_DEBUG=1
;;
-incarnation)
needarg
INCARNATION=$ARG
shift
;;
-disturl)
needarg
DISTURL=$ARG
shift
;;
-linksources)
LINKSOURCES=true
;;
-changelog)
CHANGELOG=true
;;
-overlay)
needarg
OVERLAY=$ARG
shift
;;
-rsync-src)
needarg
RSYNCSRC=$ARG
shift
;;
-rsync-dest)
needarg
RSYNCDEST=$ARG
shift
;;
-verbose)
needarg
case "$ARG" in
all)
BUILD_VERBOSE_VM=true
;;
vm)
BUILD_VERBOSE_VM=true
;;
*)
echo "WARNING: unknown verbose option $ARGS"
;;
esac
shift
;;
-uid)
needarg
if test -n "${ARG//[0-9:]/}" ; then
cleanup_and_exit 1 "--uid argument must be uid:gid"
fi
ABUILD_UID=${ARG%:*}
ABUILD_GID=${ARG#*:}
shift
;;
-rpmlist)
needarg
RPMLIST="--rpmlist $ARG"
BUILD_RPMS=
shift
;;
-sysrq)
needarg
SEND_SYSRQ="${ARG:0:1}"
shift
;;
-shell)
RUN_SHELL=1
;;
-shell-after-fail)
RUN_SHELL_AFTER_FAIL=1
;;
-shell-cmd)
needarg
RUN_SHELL=1
RUN_SHELL_CMD="$ARG"
shift
;;
-signdummy)
SIGNDUMMY=1
;;
-nosignature)
DLNOSIGNATURE="--nosignature"
;;
-obsmultibuild|-obs-multibuild|-buildflavor|-build-flavor)
needarg
BUILD_FLAVOR=$ARG
shift
;;
-obspackage|-obs-package)
needarg
OBS_PACKAGE=$ARG
shift
;;
-obs)
needarg
OBSURL=$ARG
shift
;;
-copy-sources-asis)
COPY_SOURCES_ASIS=true
;;
---noarg)
cleanup_and_exit 1 "$ARG does not take an argument"
;;
-*)
if vm_parse_options "$@" ; then
set -- "${nextargs[@]}"
elif recipe_parse_options "$@" ; then
set -- "${nextargs[@]}"
else
cleanup_and_exit 1 "Unknown option '$PARAM'. Exit."
fi
;;
*)
RECIPEFILES[${#RECIPEFILES[@]}]="$PARAM"
# skip validation
PARAM=
;;
esac
if test -n "$PARAM" ; then
validate_param "$PARAM" "$ARG"
fi
done
# validate params coming from the environment
test -n "$BUILD_ARCH" && validate_param "--arch" "$BUILD_ARCH" BUILD_ARCH
test -n "$BUILD_HOST_ARCH" && validate_param "--hostarch" "$BUILD_HOST_ARCH" BUILD_HOST_ARCH
test -n "$BUILD_RPMS" && validate_param "--rpms" "$BUILD_RPMS" BUILD_RPMS
test -n "$BUILD_EXTRA_PACKS" && validate_param "--extrapacks" "$BUILD_EXTRA_PACKS" BUILD_EXTRA_PACKS
test -n "$BUILD_DIST" && validate_param "--dist" "$BUILD_DIST" BUILD_DIST
test -n "$VERIFY_BUILD_SYSTEM" && validate_param "--verify" "$VERIFY_BUILD_SYSTEM" VERIFY_BUILD_SYSTEM
test -n "$BUILD_RPM_BUILD_STAGE" && validate_param "--stage" "$BUILD_RPM_BUILD_STAGE" BUILD_RPM_BUILD_STAGE
test "$BUILD_ROOT" != /var/tmp/build-root && validate_param "--root" "$BUILD_ROOT" BUILD_ROOT
test "$CONFIG_DIR" != "$BUILD_DIR/configs" && validate_param "--configdir" "$CONFIG_DIR" CONFIG_DIR
# validate the buildroot
validate_buildroot "$BUILD_ROOT"
if test -n "$VM_TYPE" -a -z "$RUNNING_IN_VM" ; then
vm_verify_options
vm_set_defaults
fi
initbuildsysstuff=()
if test -n "$BUILD_FLAVOR" ; then
initbuildsysstuff[${#initbuildsysstuff[@]}]="--buildflavor"
initbuildsysstuff[${#initbuildsysstuff[@]}]="$BUILD_FLAVOR"
fi
if test -n "$OBS_PACKAGE" ; then
initbuildsysstuff[${#initbuildsysstuff[@]}]="--obspackage"
initbuildsysstuff[${#initbuildsysstuff[@]}]="$OBS_PACKAGE"
fi
if test -n "$OBSURL" ; then
initbuildsysstuff[${#initbuildsysstuff[@]}]="--obs"
initbuildsysstuff[${#initbuildsysstuff[@]}]="$OBSURL"
fi
if test -n "$RPM_BUILD_IN_PLACE"; then
initbuildsysstuff[${#initbuildsysstuff[@]}]="--define"
initbuildsysstuff[${#initbuildsysstuff[@]}]="_build_in_place 1"
fi
if test -n "$DO_WIPE" ; then
wipe_build_environment
cleanup_and_exit
fi
if test -n "$KILL" ; then
kill_running_build
cleanup_and_exit
fi
if test -n "$SEND_SYSRQ" ; then
sysrq_running_build "$SEND_SYSRQ"
cleanup_and_exit
fi
# done option parsing
BUILD_OPTIONS_PARSED=true
if test -n "$CLEAN_BUILD" ; then
DO_INIT=true
DO_INIT_TOPDIR=true
fi
if test -n "$CCACHE" ; then
test -z "$CCACHE_TYPE" && CCACHE_TYPE=ccache
# automatically use ccache archive from an old build
if test -z "$CCACHE_ARCHIVE" -a -n "${old_packages[0]}" -a -e "${old_packages[0]}/_ccache.tar" ; then
CCACHE_ARCHIVE="${old_packages[0]}/_ccache.tar"
fi
fi
if test -z "$RPMLIST" -a -z "$RUNNING_IN_VM" ; then
if test -z "$repos" -a -z "$BUILD_RPMS" -a "$BUILD_DIST" = "${BUILD_DIST#obs:/}"; then
repos=(--repository 'zypp://')
fi
else
repos=()
fi
set_build_arch
if test "$DO_INIT" = false -a -n "$RUN_SHELL" -a -z "$VM_TYPE"; then
mount_stuff
BUILD_USER=root
test -n "$NOROOTFORBUILD" && BUILD_USER=abuild
chroot $BUILD_ROOT su - $BUILD_USER
cleanup_and_exit $?
fi
expand_recipe_directories
if test -n "$LIST_STATE" ; then
BUILD_ROOT=`mktemp -d /var/tmp/build-list-state-XXXXXX`
test -d "$BUILD_ROOT" || cleanup_and_exit 3
RECIPEPATH=$RECIPEFILES # only one specified anyways
test "$RECIPEPATH" != "${RECIPEPATH%.src.rpm}" && recipe_unpack_srcrpm "$RECIPEPATH"
init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --list-state "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $DLNOSIGNATURE $USEUSEDFORBUILD $RECIPEPATH $BUILD_EXTRA_PACKS
ERR=$?
rm -rf "$BUILD_ROOT"
cleanup_and_exit $ERR
fi
# do vm setup if needed
if test -z "$RUNNING_IN_VM" -a -n "$VM_TYPE" -a -n "$VM_ROOT" ; then
vm_setup
fi
mkdir_build_root
if test "$BUILD_ROOT" = / ; then
browner="$(stat -c %u /)"
fi
rm -f $BUILD_ROOT/exit
if test -z "$VM_ROOT" -a -z "$LOGFILE" ; then
if test -z "$RUNNING_IN_VM"; then
LOGFILE="$BUILD_ROOT/.build.log"
else
# lxc, docker and nspawn are special cases: vm shares logfile with host
case "$VM_TYPE" in
lxc|docker|nspawn)
;;
*)
LOGFILE="$BUILD_ROOT/.build.log"
;;
esac
fi
fi
if test -n "$LOGFILE" -a -z "$RUN_SHELL" ; then
echo "logging output to $LOGFILE..."
rm -f "$LOGFILE" "$LOGFILE.pid"
touch $LOGFILE
# set start time, to be substracted for build log timestamps
STARTTIME=`perl -e 'print time()'`
if test -n "$RUN_SHELL_AFTER_FAIL" ; then
# we may run a shell, so no stdout wrapper
:
elif test -n "$RUNNING_IN_VM" -o -n "$NO_TIMESTAMPS" ; then
# no additional timestamps in inner vm build system
exec 1> >(echo "$BASHPID" > $LOGFILE.pid ; exec -a 'build logging' tee -a $LOGFILE) 2>&1
elif test -n "$VM_ROOT" ; then
# external run of virtualization build
exec 1> >(exec -a 'build logging' perl -e 'open(F,">>",$ARGV[0])||die("$ARGV[0]: $!\n");$|=1;select(F);$|=1;while(<STDIN>){my $p=sprintf("[%5ds] ", time()-'$STARTTIME');print STDOUT $p.$_;s/^\r//s;s/\r\n/\n/gs;print F $p.$_}' $LOGFILE) 2>&1
else
# plain chroot
exec 1> >(exec -a 'build logging' perl -e 'open(F,">>",$ARGV[0])||die("$ARGV[0]: $!\n");$|=1;select(F);$|=1;while(<STDIN>){my $p=sprintf("[%5ds] ", time()-'$STARTTIME');print STDOUT $p.$_;print F $p.$_}' $LOGFILE) 2>&1
fi
fi
setmemorylimit
case $BUILD_DIST in
obs:/*)
test -n "$OBSURL" || cleanup_and_exit 1 "Please use the --obs option to specify the url of the obs instance"
BUILD_DIST_TMP=$(mktemp)
$BUILD_DIR/queryobs config --obs "$OBSURL" "$BUILD_DIST" > "$BUILD_DIST_TMP"
if test -z "$repos" ; then
for repo in $($BUILD_DIR/queryobs expandpath --obs "$OBSURL" "$BUILD_DIST") ; do
repos[${#repos[@]}]="--repository"
repos[${#repos[@]}]="$repo"
done
fi
BUILD_DIST="$BUILD_DIST_TMP"
;;
esac
#
# say hello
#
test -z "$HOST" && HOST=`hostname`
if test -z "$RUNNING_IN_VM" ; then
echo Using BUILD_ROOT=$BUILD_ROOT
test -n "$BUILD_RPMS" && echo Using BUILD_RPMS=$BUILD_RPMS
echo Using BUILD_ARCH=$BUILD_ARCH
test -n "$VM_TYPE" && echo "Doing $VM_TYPE build${VM_ROOT:+ in $VM_ROOT}"
echo
fi
test "$BUILD_ARCH" = all && BUILD_ARCH=
BUILD_USER_ABUILD_USED=
MODULEMDFILE=
for RECIPEPATH in "${RECIPEFILES[@]}" ; do
if test -n "$RPM_BUILD_IN_PLACE" -a -n "$RPM_RECIPE_IN_SUBDIR" -a -z "$RUNNING_IN_VM" ; then
SRCDIR=${RECIPEPATH%/*}
SRCDIR=${SRCDIR%/*}
RECIPEFILE="${RECIPEPATH##*/}"
elif test -n "$RPM_BUILD_IN_PLACE" -a -z "$RUNNING_IN_VM" ; then
SRCDIR="$PWD"
RECIPEFILE="${RECIPEPATH##*/}"
elif test "$RECIPEPATH" != "${RECIPEPATH%/debian/control}" ; then
SRCDIR="${RECIPEPATH%/debian/control}"
RECIPEFILE="debian/control"
else
SRCDIR="${RECIPEPATH%/*}"
RECIPEFILE="${RECIPEPATH##*/}"
fi
if test "$RECIPEFILE" = "_slsa_provenance.json" -o "$RECIPEFILE" != "${RECIPEFILE%.slsa_provenance.json}" ; then
MYSRCDIR="$BUILD_ROOT/.build-srcdir"
rm -rf "$MYSRCDIR"
mkdir -p "$MYSRCDIR"
cd "$MYSRCDIR" || cleanup_and_exit 1
$BUILD_DIR/unpack_slsa_provenance "$RECIPEPATH" "$MYSRCDIR" || cleanup_and_exit 1 "Could not unpack slsa provenance file"
SRCDIR="$MYSRCDIR"
RECIPEFILE=
while read k ; do
case $k in
recipe=*) RECIPEFILE="${k#*=}" ;;
release=*) test -z "$RELEASE" && RELEASE="${k#*=}" ;;
debuginfo=*) BUILD_DEBUG=1 ;;
esac
done < .build.params
test -z "$RECIPEFILE" && cleanup_and_exit 1 "recipe not set in build parameters"
RECIPEPATH="$SRCDIR/$RECIPEFILE"
RPMLIST="--rpmlist $MYSRCDIR/.build.rpmlist"
BUILD_RPMS=
BUILD_DIST="$SRCDIR/.build.config"
repos=()
fi
recipe_set_buildtype
if test -z "$RUNNING_IN_VM" ; then
echo
echo "$HOST started \"build $RECIPEFILE\" at `date --utc`."
echo
test -n "$REASON" && echo "$REASON"
echo
TIME_START_TIME=$SECONDS # for statistics
fi
#
# first setup building directory...
#
cd "$SRCDIR"
if ! test -s "$RECIPEPATH" ; then
cleanup_and_exit 1 "$RECIPEFILE is empty. This should not happen..."
fi
MYSRCDIR="$SRCDIR"
# remember the modulemd file if we have one
test -s _modulemd.yml && MODULEMDFILE="$SRCDIR/_modulemd.yml"
test -s _modulemd.yaml && MODULEMDFILE="$SRCDIR/_modulemd.yaml"
test -s _modulemd.pst && MODULEMDFILE="$SRCDIR/_modulemd.pst"
# special hack to build from a .src.rpm (modifies MYSRCDIR)
test "$RECIPEFILE" != "${RECIPEFILE%.src.rpm}" && recipe_unpack_srcrpm "$RECIPEPATH"
echo "processing recipe $RECIPEPATH ..."
ADDITIONAL_PACKS=
test -z "$BUILD_EXTRA_PACKS" || ADDITIONAL_PACKS="$ADDITIONAL_PACKS $BUILD_EXTRA_PACKS"
test -z "$CREATE_BASELIBS" || ADDITIONAL_PACKS="$ADDITIONAL_PACKS build"
test -z "$CCACHE" || ADDITIONAL_PACKS="$ADDITIONAL_PACKS $CCACHE_TYPE"
test "$icecream" = 0 || ADDITIONAL_PACKS="$ADDITIONAL_PACKS icecream gcc-c++"
test -z "$DO_LINT" || ADDITIONAL_PACKS="$ADDITIONAL_PACKS rpmlint-Factory"
test "$VMDISK_FILESYSTEM" = xfs && ADDITIONAL_PACKS="$ADDITIONAL_PACKS libblkid1"
test "$VM_TYPE" = zvm && ADDITIONAL_PACKS="$ADDITIONAL_PACKS udev libcap2"
# we need to do this before the vm is started
if test -n "$CHANGELOG" -a -z "$RUNNING_IN_VM" -a -z "$RUN_SHELL" ; then
recipe_create_changelog "$RECIPEPATH"
fi
if test -n "$VM_TYPE" -a -z "$RUNNING_IN_VM" ; then
vm_first_stage
cleanup_and_exit
fi
if test "$DO_INIT" = true ; then
start_time=$SECONDS
#
# create legacy .buildenv file
#
test -z "$INCARNATION" && INCARNATION=0
echo "BUILD_INCARNATION=$INCARNATION" > $BUILD_ROOT/.buildenv
Q="'\''"
test -n "$DISTURL" && echo "BUILD_DISTURL='${DISTURL//"'"/$Q}'" >> $BUILD_ROOT/.buildenv
test "$BUILDTYPE" = preinstallimage && mkdir -p $BUILD_ROOT/.preinstall_image
CREATE_BUILD_BINARIES=
if recipe_needs_build_binaries "$RECIPEPATH" ; then
CREATE_BUILD_BINARIES=--create-build-binaries
fi
set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $DLNOSIGNATURE $USEUSEDFORBUILD $CREATE_BUILD_BINARIES $RPMLIST "$RECIPEPATH" $ADDITIONAL_PACKS
echo "$* ..."
start_time=$SECONDS
"$@" || cleanup_and_exit 1
check_exit
TIME_INSTALL=$(( $SECONDS - $start_time ))
unset start_time
# arbitrary limit of 10MB
if test $((`stat -f -c "%a*%S/1024/1024" $BUILD_ROOT`)) -lt 10; then
# ensure that old stat is not failing (RHEL4)
if df $BUILD_ROOT 2>/dev/null | grep -q "100%"; then
df -h $BUILD_ROOT
cleanup_and_exit 1 "build does not work on a completely full filesystem"
fi
fi
copy_oldpackages
fi
mount_stuff
# hack to process preinstallimages early
if test "$BUILDTYPE" = preinstallimage ; then
recipe_build
continue
fi
if test -z "$BUILD_DIST" -a -e "$BUILD_ROOT/.guessed_dist" ; then
read BUILD_DIST < $BUILD_ROOT/.guessed_dist
fi
#
# install dummy sign program if needed
#
test -f $BUILD_ROOT/usr/bin/sign_installed && mv $BUILD_ROOT/usr/bin/sign_installed $BUILD_ROOT/usr/bin/sign
if test -n "$SIGNDUMMY" ; then
test -f $BUILD_ROOT/usr/bin/sign && mv $BUILD_ROOT/usr/bin/sign $BUILD_ROOT/usr/bin/sign_installed
cp $BUILD_DIR/signdummy $BUILD_ROOT/usr/bin/sign
chmod 755 $BUILD_ROOT/usr/bin/sign
fi
#
# check if we want to build with the abuild user
#
BUILD_USER=abuild
if test -x $BUILD_ROOT/bin/rpm ; then
SUSE_VERSION=`chroot $BUILD_ROOT /bin/rpm --eval '%{?suse_version}' 2>/dev/null`
test -n "$SUSE_VERSION" -a "${SUSE_VERSION:-0}" -le 1020 && BUILD_USER=root
fi
if test "$BUILD_USER" = abuild ; then
grep -E '^#[[:blank:]]*needsrootforbuild[[:blank:]]*$' >/dev/null <$RECIPEPATH && BUILD_USER=root
else
grep -E '^#[[:blank:]]*norootforbuild[[:blank:]]*$' >/dev/null <$RECIPEPATH && BUILD_USER=abuild
fi
test -n "$NOROOTFORBUILD" && BUILD_USER=abuild
# appliance builds must run as root
if test "$BUILDTYPE" = kiwi ; then
imagetype=$(perl -I$BUILD_DIR -MBuild::Kiwi -e Build::Kiwi::show $RECIPEPATH imagetype)
test "$imagetype" = product || BUILD_USER=root
fi
# same with docker, fissile and livebuild builds
if test "$BUILDTYPE" = docker -o "$BUILDTYPE" = fissile -o "$BUILDTYPE" = podman -o "$BUILDTYPE" = livebuild ; then
BUILD_USER=root
fi
# fixup passwd/group
if test $BUILD_USER = abuild ; then
if ! grep -E '^abuild:' >/dev/null <$BUILD_ROOT/etc/passwd ; then
echo "abuild:x:${ABUILD_UID}:${ABUILD_GID}:Autobuild:/home/abuild:/bin/bash" >>$BUILD_ROOT/etc/passwd
echo 'abuild:*:::::::' >>$BUILD_ROOT/etc/shadow # This is needed on Mandriva 2009
echo 'abuild:*::' >>$BUILD_ROOT/etc/gshadow # This is needed on Ubuntu
echo "abuild:x:${ABUILD_GID}:" >>$BUILD_ROOT/etc/group
mkdir -p $BUILD_ROOT/home/abuild
chown "$ABUILD_UID:$ABUILD_GID" $BUILD_ROOT/home/abuild
else
if ! grep -E "^abuild:x?:${ABUILD_UID}:${ABUILD_GID}" >/dev/null <$BUILD_ROOT/etc/passwd ; then
echo "abuild user present in the buildroot ($BUILD_ROOT) but uid:gid does not match"
echo "buildroot currently using:"
grep -E "^abuild:" <$BUILD_ROOT/etc/passwd
echo "build script attempting to use:"
echo "abuild::${ABUILD_UID}:${ABUILD_GID}:..."
echo "build aborting"
cleanup_and_exit 1
fi
fi
if test -f $BUILD_ROOT/etc/shadow ; then
sed -i -e "s@^root::@root:*:@" $BUILD_ROOT/etc/shadow
fi
if test -f $BUILD_ROOT/etc/gshadow ; then
sed -i -e "s@^root::@root:*:@" $BUILD_ROOT/etc/gshadow
fi
BUILD_USER_ABUILD_USED=true
else
# building as root
ABUILD_UID=0
ABUILD_GID=0
if grep -E '^abuild:' >/dev/null <$BUILD_ROOT/etc/passwd ; then
rm -rf "$BUILD_ROOT/home/abuild"
sed -i -e '/^abuild:/d' $BUILD_ROOT/etc/passwd
sed -i -e '/^abuild:/d' $BUILD_ROOT/etc/group
if test -f $BUILD_ROOT/etc/shadow ; then
sed -i -e '/^abuild:/d' $BUILD_ROOT/etc/shadow
fi
if test -f $BUILD_ROOT/etc/gshadow ; then
sed -i -e '/^abuild:/d' $BUILD_ROOT/etc/gshadow
fi
fi
fi
if test -n "$RUNNING_IN_VM" ; then
vm_setup_network
fi
setupicecream
ccache_setup
test -n "$RUN_SHELL" && run_shell
# fill build directories with sources. Also sets TOPDIR
recipe_setup
RECIPEPATH=
# strip prefix from autogenerated files of source services.
# sorted by line length to let the latest run service win
perl -e 'print "$_\n" for sort { length($a) <=> length($b) } @ARGV' $BUILD_ROOT$TOPDIR/SOURCES/_service\:* | while read i ; do
mv "$i" "${i%/*}/${i##*:}"
done
RECIPEFILE="${RECIPEFILE##*:}"
# create .build.packages link
rm -f $BUILD_ROOT/.build.packages
ln -s ${TOPDIR#/} $BUILD_ROOT/.build.packages
# nasty hack to prevent rpath on known paths
# FIXME: do this only for suse
if test -d "$BUILD_ROOT/etc/profile.d" ; then
echo "export SUSE_IGNORED_RPATHS=/etc/ld.so.conf" > "$BUILD_ROOT/etc/profile.d/buildsystem.sh"
fi
cd $BUILD_ROOT$TOPDIR/SOURCES || cleanup_and_exit 1
for i in *.obscpio ; do
test -e "$i" || continue
echo "Unpacking $i ..."
echo "#!/bin/sh -e" > $BUILD_ROOT/.unpack.command
shellquote cd "$TOPDIR/SOURCES" >> $BUILD_ROOT/.unpack.command
echo >> $BUILD_ROOT/.unpack.command
echo -n 'cpio --extract --owner="'$BUILD_USER'" --unconditional --preserve-modification-time --make-directories <' >> $BUILD_ROOT/.unpack.command
shellquote "$i" >> $BUILD_ROOT/.unpack.command
echo >> $BUILD_ROOT/.unpack.command
shellquote rm -f "$i" >> $BUILD_ROOT/.unpack.command
echo >> $BUILD_ROOT/.unpack.command
chmod 0755 $BUILD_ROOT/.unpack.command
chroot $BUILD_ROOT su -c /.unpack.command - $BUILD_USER || cleanup_and_exit 1
rm -f $BUILD_ROOT/.unpack.command
done
# macros may be used by buildtime servies
recipe_setup_macros
if test -e _service; then
echo "Running build time source services..."
HOME=/root $BUILD_DIR/runservices --buildroot "$BUILD_ROOT" || cleanup_and_exit 1
fi
# get rid of old src dir, it is no longer needed and just wastes space
test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir && rm -rf "$MYSRCDIR"
# patch recipes
recipe_prepare
# hmmm
chown -hR "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT$TOPDIR"
echo -----------------------------------------------------------------
if test "$BUILD_USER" = root ; then
echo ----- building $RECIPEFILE
else
echo ----- building $RECIPEFILE "(user $BUILD_USER)"
fi
echo -----------------------------------------------------------------
echo -----------------------------------------------------------------
BUILD_SUCCEEDED=false
if test -n "$OVERLAY" ; then
copy_overlay
fi
if test -n "$RSYNCSRC" ; then
run_rsync
fi
RECIPE_BUILD_START_TIME=`date +%s`
GEN_BUILDREQS_PACKS=()
recipe_build
if test "$BUILD_SUCCEEDED" = genbuildreqs -a "$DO_INIT" = true -a -z "$RPMLIST" -a -z "$RUNNING_IN_VM" -a -n "${GEN_BUILDREQS_PACKS[*]}" ; then
# re-expand deps with GEN_BUILDREQS_PACKS extra packages
umount_stuff
set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $DLNOSIGNATURE $USEUSEDFORBUILD $CREATE_BUILD_BINARIES $RPMLIST "$MYSRCDIR/$RECIPEFILE" $ADDITIONAL_PACKS "${GEN_BUILDREQS_PACKS[@]}"
echo "$* ..."
"$@" || cleanup_and_exit 1
check_exit
mount_stuff
BUILD_SUCCEEDED=false
recipe_build
fi
if test "$BUILD_SUCCEEDED" = genbuildreqs ; then
recipe_cleanup
if test -n "$RUNNING_IN_VM" ; then
vm_exit_statistics
vm_wrapup_build OTHER
fi
cleanup_and_exit 9
fi
test "$BUILD_SUCCEEDED" = true || cleanup_and_exit 1
BUILD_SUCCEEDED=
recipe_build_time_statistics
recipe_gendiff
recipe_cleanup
test -d "$SRCDIR" && cd "$SRCDIR"
umount_stuff
done
if test -n "$RUNNING_IN_VM" ; then
vm_exit_statistics
fi
# mount /proc again for the post processing steps
if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
mount -n -tproc none $BUILD_ROOT/proc
fi
RPMS=`find $BUILD_ROOT/$TOPDIR/RPMS -type f -name "*.rpm" 2>/dev/null || true`
DEBS=`find $BUILD_ROOT/$TOPDIR/DEBS -type f "(" -name "*.deb" -o -name "*.ddeb" -o -name "*.udeb" ")" 2>/dev/null || true`
if test -n "$RPMS" -a -n "$BUILD_USER_ABUILD_USED" ; then
recipe_check_file_owners
fi
TIME_POSTCHECKS=0
TIME_RPMLINT=0
TIME_BUILDCMP=0
TIME_DELTARPMS=0
# set BUILD_SUCCEEDED to false again so that --shell-after-fail
# works if there is an check/rpmlint error
BUILD_SUCCEEDED=false
###### Post build checks
TIME_POSTCHECKS=$SECONDS
# RPM specific post checks are in /usr/lib/build/checks
if test -n "$RPMS" -a -d "$BUILD_ROOT/usr/lib/build/checks" ; then
# workaround for broken 13.1 check scripts which umount /proc
if test -n "$RUNNING_IN_VM" -a "$BUILD_ROOT" = / ; then
umount -n $BUILD_ROOT/proc/sys/fs/binfmt_misc 2>/dev/null
fi
# find package name
export PNAME=
for SRPM in $BUILD_ROOT/$TOPDIR/SRPMS/*src.rpm ; do
test -f "$SRPM" && PNAME=`env LC_ALL=C rpm --macros=/dev/null --nodigest --nosignature -qp --qf "%{NAME}" $SRPM`
done
if test -z "$PNAME" ; then
for SRPM in $RPMS ; do
test -f "$SRPM" && PNAME=`rpm --nodigest --nosignature -qp --qf "%{SOURCERPM}" $SRPM`
done
PNAME="${PNAME%-*-*.*.rpm}"
fi
for CHECKSCRIPT in $BUILD_ROOT/usr/lib/build/checks/* ; do
echo "... running ${CHECKSCRIPT##*/}"
BUILD_ROOT=/ HOME=/root chroot "$BUILD_ROOT" "/usr/lib/build/checks/${CHECKSCRIPT##*/}" || cleanup_and_exit 1
done
# workaround for broken 13.1 check scripts which umount /proc
test -e "$BUILD_ROOT/proc/self" || mount -n -tproc none $BUILD_ROOT/proc
fi
# Generic post-build-checks are in /usr/lib/build/post-build-checks
for CHECKSCRIPT in $BUILD_ROOT/usr/lib/build/post-build-checks/* ; do
if test -x "$CHECKSCRIPT"; then
echo "... running ${CHECKSCRIPT##*/}"
BUILD_ROOT=/ HOME=/root chroot "$BUILD_ROOT" "/usr/lib/build/post-build-checks/${CHECKSCRIPT##*/}" || cleanup_and_exit 1
fi
done
###### End Post build checks
TIME_POSTCHECKS=$(( $SECONDS - $TIME_POSTCHECKS ))
# checkscripts may have deleted some binaries
RPMS=`find $BUILD_ROOT/$TOPDIR/RPMS -type f -name "*.rpm" 2>/dev/null || true`
DEBS=`find $BUILD_ROOT/$TOPDIR/DEBS -type f -name "*.deb" 2>/dev/null || true`
if test -n "$RPMS" -a "$DO_CHECKS" != false ; then
TIME_RPMLINT=$SECONDS
recipe_run_rpmlint
TIME_RPMLINT=$(( SECONDS - $TIME_RPMLINT ))
fi
BUILD_SUCCEEDED=
if test -n "$CCACHE" ; then
ccache_wrapup
fi
if test \( -n "$RPMS" -o -n "$DEBS" \) -a -n "$CREATE_BASELIBS"; then
create_baselibs
fi
for SCRIPT in $BUILD_ROOT/usr/lib/build/post-mkbaselibs-checks/* ; do
if test -x "$SCRIPT"; then
echo "... running ${SCRIPT##*/}"
BUILD_ROOT=/ HOME=/root chroot "$BUILD_ROOT" "/usr/lib/build/post-mkbaselibs-checks/${SCRIPT##*/}" || cleanup_and_exit 1
fi
done
if test -n "$MODULEMDFILE" ; then
mkdir -p "$BUILD_ROOT/$TOPDIR/OTHER"
find "$BUILD_ROOT/$TOPDIR/RPMS" "$BUILD_ROOT/$TOPDIR/SRPMS" -type f -name "*.rpm" | sort | $BUILD_DIR/writemodulemd ${DISTURL:+--disturl "$DISTURL"} "$MODULEMDFILE" - > "$BUILD_ROOT/$TOPDIR/OTHER/_modulemd.yaml"
test -s "$BUILD_ROOT/$TOPDIR/OTHER/_modulemd.yaml" || rm -f "$BUILD_ROOT/$TOPDIR/OTHER/_modulemd.yaml"
fi
exitcode=0
# post build work
# TODO: don't hardcode. instead run scripts in a directory as it's done for the checks
if test -n "$RPMS" -a -d "$BUILD_ROOT/.build.oldpackages" ; then
TIME_BUILDCMP=$SECONDS
recipe_compare_oldpackages
TIME_BUILDCMP=$(( $SECONDS - $TIME_BUILDCMP ))
# no need to create deltas if the build is the same
if test ! -e $BUILD_ROOT/.build/.same_result_marker ; then
TIME_DELTARPMS=$SECONDS
recipe_create_deltarpms
TIME_DELTARPMS=$(( $SECONDS - $TIME_DELTARPMS ))
fi
fi
if test -n "$RUNNING_IN_VM" ; then
vm_wrapup_build $(recipe_resultdirs) OTHER
else
if test "$BUILDTYPE" = "preinstallimage" ; then
preinstallimage_compress "$BUILD_ROOT/$TOPDIR/OTHER"
fi
fi
echo
echo "$HOST finished \"build $RECIPEFILE\" at `date --utc`."
echo
cleanup_and_exit "$exitcode"