#!/usr/bin/env bash # # --- T2-COPYRIGHT-NOTE-BEGIN --- # T2 SDE: scripts/Build-Target # Copyright (C) 2004 - 2024 The T2 SDE Project # Copyright (C) 1998 - 2003 ROCK Linux Project # # This Copyright note is generated by scripts/Create-CopyPatch, # more information can be found in the files COPYING and README. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2. # --- T2-COPYRIGHT-NOTE-END --- # # Run this command from the T2 SDE base directory as scripts/Build-Target # after running the scripts/Config and the now optional # scripts/Download commands. # # It compiles/builds all the packages and stores their binary package # ssuitable for distribution. # # This script (and Build-Pkg) is T2 SDE's work-horse. It builds in a # chroot environment (stage 0..2) and goes through a number of build # stages (stage 3..9). # config=default build_only_this_job= daemon_mode=0 autodownload=1 options="$*" downloadopt="-q" verbose= xtrace= noclearsrc= while [ $# -gt 0 ]; do case "$1" in -cfg) config=$2; shift ;; -job) build_only_this_job=$2; shift ;; -daemon) daemon_mode=1 ;; -nodaemon) daemon_mode=0 ;; -nodownload) autodownload=0 ;; -noclearsrc) noclearsrc="-noclearsrc" ;; -xtrace) xtrace="-xtrace" ;; -v) verbose="-v" ;; [0-9]-*) build_only_this_job=$1 ;; *) echo "Usage: $0 [ -daemon ] [ -nodownload ] [ -noclearsrc ] [ -cfg config ]" \ "[ -job - ]"; exit 1 ;; esac shift done if [ "$daemon_mode" = 1 ]; then . config/$config/config echo "Running $0 in the background (messages go to logfile only)" echo "Logfile: build/$SDECFG_ID/TOOLCHAIN/logs/build_target.log" nohup $0 $options -nodaemon > /dev/null 2> /dev/null < /dev/null & exit 0 fi . scripts/parse-config . scripts/functions.in build_root="$base/build/$SDECFG_ID" build_toolchain="$base/build/$SDECFG_ID/TOOLCHAIN" build_logs="$build_toolchain/logs"; mkdir -p "${build_logs}" build_pkgs="$build_toolchain/pkgs"; mkdir -p "${build_root}" if [ "$SDECFG_PARANOIA_CHECK" = 1 ]; then scripts/Check-System || exit 1 fi # Package Build loop - executed by build-target # pkgloop() { local x= y= if [ "$SDECFG_NOBROKENDEPS" = 1 ]; then nobrokendeps="-nobrokendeps" else nobrokendeps="" fi if [ -z "$build_only_this_job" ]; then if [ "`ls ${build_root}/var/adm/logs/*.err 2> /dev/null`" ]; then echo_header "Removing old error logs ..." for y in 0 1 2 3 4 5 6 7 8 9; do if [ "$SDECFG_RETRY_BROKEN" -eq 1 -o $y -le $SDECFG_CONTINUE_ON_ERROR_AFTER ]; then for x in ${build_root}/var/adm/logs/$y-*.err; do if [ -f $x ]; then echo_status "Removing ${x#$build_root/} ..." rm -f $x fi done fi done fi if [ "`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 while next="`scripts/Create-PkgQueue \ -cfg "$config" -single $nobrokendeps`" [ "$next" ] do pkgloop_package $next done else 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=" "; } $5 == "'${build_only_this_job#*-}'" && $2 ~ /'${build_only_this_job%%-*}'/ \ { $1="'${build_only_this_job%%-*}' 0"; print; exit; }' < config/$config/packages)" if [ ! "$next" ]; then echo_error "No job matching job spec: $build_only_this_job" exit 1 fi pkgloop_package $next exit 0 fi # wait for background compression jobs to finish for j in $(jobs -p); do wait $j; done local pkglst=`mktemp` errors=0; rm -f src/invalid-files.lst echo_header "Searching for old lingering files ..." sed '/^[^X]/d; s,.*=,,' config/$config/packages | cut -d' ' -f5 | if [ $SDECFG_PKGFILE_VER = 1 ]; then while read p; do v=$(grep '^Package Name and Version:' \ build/$SDECFG_ID/var/adm/packages/$p \ 2>/dev/null | cut -f6 -d' ') echo "$p-$v" done else cat fi > $pkglst for file in $(ls build/$SDECFG_ID/TOOLCHAIN/pkgs/ 2> /dev/null); do x="$file" case $SDECFG_PKGFILE_TYPE in tar.*) x=${x%.$SDECFG_PKGFILE_TYPE} ;; none) : ;; esac if ! grep -qx "$x" $pkglst && ! test "$x" = packages.db; then file="build/$SDECFG_ID/TOOLCHAIN/pkgs/$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 for dir in build/$SDECFG_ID/var/adm/{cache,dependencies,descs,flists,md5sums,packages}; do for file in $(ls $dir 2> /dev/null); do if [ $SDECFG_PKGFILE_VER = 1 ]; then x="$file-" else x="$file" fi if ! grep -q "$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/$SDECFG_ID/var/adm/logs/); do x="`echo $file | sed -e 's/^.-//' -e 's/\.log//' -e 's/\.err//' -e s'/\.out//'`" if [ $SDECFG_PKGFILE_VER = 1 ]; then x=$x- else x=$x fi if ! grep -q "$x" $pkglst; then file="build/$SDECFG_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 "None found." rm $pkglst } # Process one line of output generated by Create-PkgQueue # pkgloop_package() { stagelevel="$1" pkg_depnr="$2" pkg_stages="$3" pkg_pri="$4" pkg_tree="$5" pkg_name="$6" pkg_ver="$7" pkg_prefix="$8" pkg_extra="$9" [ "$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 2 ] && cmd_root="$cmd_root -chroot" if [ "$pkg_prefix" != "/" ]; then cmd_prefix="-prefix $pkg_prefix" else cmd_prefix=""; fi if [ "$autodownload" == 1 ]; then scripts/Download -cfg $config $downloadopt $pkg_name fi cmd_buildpkg="scripts/Build-Pkg -$stagelevel -cfg $config $verbose" cmd_buildpkg="$cmd_buildpkg $noclearsrc $xtrace $cmd_root $cmd_prefix $pkg_name" # Execute action handler if ! pkgloop_action && [ $stagelevel -le $SDECFG_CONTINUE_ON_ERROR_AFTER ]; then exit 1 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 either a *.log" echo_error "or a *.err file. As neither is there, creating a" echo_error "*.err file and aborting the build process." touch ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err exit 1 fi if [ $stagelevel -gt 0 -a $pkg_laststage -eq $stagelevel -a \ "$SDECFG_PKGFILE_TYPE" != none ] then if [ -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err ] then echo_error "Creation of binary package isn't possible, \ because the package was not" echo_error "built successfully in (at least) the current \ stage." else mkdir -p "${build_pkgs}" local file=${pkg_name} if [ "$SDECFG_PKGFILE_VER" = 1 ]; then v="$(grep '^Package Name and Version:' \ ${build_root}/var/adm/packages/$pkg_name | cut -f6 -d' ')" file="$file-$v" fi [[ $SDECFG_PKGFILE_TYPE = tar.* ]] && file=$file.$SDECFG_PKGFILE_TYPE local compressor=${SDECFG_PKGFILE_TYPE#tar.} case $compressor in br) compressor=brotli ;; gz) compressor=gzip ;; bz2) compressor=bzip2 ;; lzo) compressor=lzop ;; zst) [ "$arch_sizeof_char_p" = 8 ] && compressor="zstd -T0 --ultra -20" || compressor="zstd -T0 -19" ;; # lzma, xz et al. are named after the extension gem) compressor=bzip2 file=$file.tar.bz2 ;; esac echo_status "Creating ${build_pkgs#$base/}/$file" ( # sort var/adm before the rest - so they can be extracted, quickly (cd "$build_root/" (grep ' var/adm' var/adm/flists/$pkg_name grep -v ' var/adm' var/adm/flists/$pkg_name) | cut -f2- -d' ' | tar -cf- --no-recursion --files-from=- | $compressor ) > ${build_pkgs}/$file.tmp mv ${build_pkgs}/$file{.tmp,} if [ "$SDECFG_PKGFILE_TYPE" = gem ]; then mine -C "$build_root/var/adm" $build_pkgs/$file $pkg_name \ $build_pkgs/${file%.tar.bz2}.gem.tmp mv $build_pkgs/${file%.tar.bz2}.gem{.tmp,} echo_status "Removing temporary tar.bz2." rm -f $build_pkgs/$file fi ) & 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. # umount_chroot() { local ret=$? exec 201> /dev/null if ! (cd ${build_logs}; fuser *.log > /dev/null 2>&1); then echo_status "Unmounting loop mounts ..." umount -d -f $build_toolchain/{loop,config,download} 2> /dev/null umount -d -f -l $build_toolchain/{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 fi return $ret } # must trap outside the group command trap 'umount_chroot' EXIT { ln -sf build_target_$$.log ${build_logs}/build_target.log scripts/Build-Tools -1 -cfg $config _built=0 for x in $(get_expanded target/%/build.sh $targetchain); do if [ -f $x ]; then . $x _built=1 break fi done [ $_built = 1 ] || echo_warning "No target/*/build.sh controlling the build!" } 2>&1 201>> "${build_logs}/build_target_$$.log" #| tee -a "${build_logs}/build_target_$$.log"