# --- T2-COPYRIGHT-NOTE-BEGIN --- # T2 SDE: scripts/functions.in # 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 --- . scripts/core-functions.in # This function returns a "uniqe id" as output # get_unique() { local hostsum=`hostname 2>/dev/null | sed 's/[()]/_/g; s/\..*//'` if [ -z "$hostsum" -a -x /sbin/ip ]; then hostsum=`/sbin/ip link show eth0 | sed -e '/link\//!d' \ -e 's,.*link[^ ]* \([^ ]*\) .*,\1,' \ -e 's/://g'` fi if [ -z "$hostsum" -a -f /sbin/ifconfig ]; then hostsum=`/sbin/ifconfig eth0 | sed -e '/HWaddr/!d' -e 's/.* HWaddr \([^ ]*\)/\1/'` fi if [ -z "$hostsum" -a -x /usr/bin/hostid ]; then hostsum=`/usr/bin/hostid` fi date "+%Y%m%d.%H%M%S.$$.$hostsum" # "+%s.$$.$hostsum" } # this functions expands an string replacing % with all possible values # listed after case "$BASH_VERSION" in # damn workaround for different syntax in both versions 2*) get_expanded() { local string="$1"; shift while [ $# -gt 0 ]; do echo "${string//\\%/$1}" shift done } ;; *) get_expanded() { local string="$1"; shift while [ $# -gt 0 ]; do echo "${string//\%/$1}" shift done } ;; esac # atstage ... # returns true if the build is on a stage related to the given name # atstage() { local x= for x; do case "$x" in toolchain) [ $stagelevel -gt 0 ] || return 0 ;; cross*) [ $stagelevel -lt 1 -o $stagelevel -gt 2 ] || return 0 ;; rebuild) [ $stagelevel -ne 9 ] || return 0 ;; native) [ $stagelevel -lt 3 ] || return 0 ;; *) echo "atstage: '$x' stagename is not supported." >&2 break ;; esac done return 1 } # hasflag FLAG # hasflag() { local desc_F=" $desc_F " # surounding spaces for match below local arch2 [ "$arch_sizeof_char_p" = 4 ] && arch2=arch32 || arch2=arch64 [ "$desc_F" != "${desc_F/ $1 }" -o \ "$desc_F" != "${desc_F/ $1.$arch }" -o "$desc_F" != "${desc_F/ $1.$arch2 }" -o \ "$desc_F" != "${desc_F/ $1.$SDECFG_LIBC }" -o \ "$desc_F" != "${desc_F/ $1.$SDECFG_DEFAULT_CC }" ] } # Hook variables # unset hook_functions hook_fcounter declare -a hook_functions='()' hook_fcounter=0 # This function adds a code fragment to a named hook with the named priority # # hook_add hook_name priority code # hook_add() { hook_functions[hook_fcounter]="$3" # declare -a hookidx_$1 eval "hookidx_$1[\${#hookidx_$1[@]}]=\"$2 $hook_fcounter\"" eval "((hookdirty_$1++))" || true; ((hook_fcounter++)) || true } # This function executes all code fragments from the named hook # # hook_eval hook_name # hook_eval() { while read pri fnr; do [ "$pri" ] && eval "${hook_functions[fnr]}" done < <(IFS=$'\n'; eval "echo \"\${hookidx_$1[*]}\"" | sort) eval "unset hookdirty_$1" } # This function prints all hooks and their current contents # # hook_dump # hook_dump() { for hook in ${!hookidx_*}; do hook=${hook#hookidx_} echo; echo "Contents of hook $hook:" while read pri fnr; do echo; echo " $pri ($fnr)" echo "${hook_functions[fnr]}" | sed 's,^, ,' done < <(IFS=$'\n' eval "echo \"\${hookidx_$hook[*]}\"" | sort) if eval "[ -n \"\$hookdirty_\$hook\" ]"; then echo; echo -n " Hook is marked as dirty: " eval "echo \"\${hookdirty_$hook}\"" fi done echo } # This function can be used to duplicate a shell-function. E.g. when # overwriting a shell-function but the old one should stay available under # a new name: # # copy_function set_confopt set_confopt_foobar_old # # set_confopt() { # .... # set_confopt_foobar_old "$@" # .... # } # copy_function() { eval "$(declare -f $1 | sed "1 s,$1,$2,")" } # | column_clean | # # convert tabs to spaces, transform multiple consecutive spaces to one, # remove leading and trailing spaces column_clean() { sed 's,\t, ,g; s, *, ,g; s,^[ ]*,,; s,[ ]*$,,' } # This function sets the 'confopt' and some other variables. # Re-run it in the package .conf file if you modify $prefix # set_confopt() { local x= z= prefix=${prefix#/} if atstage toolchain; then z="$root" fi confopt="--prefix=$z/$prefix" mesonopt="setup objdir/ --prefix=$z/$prefix" for x in bindir sbindir libdir libexecdir datadir includedir \ docdir infodir mandir sysconfdir localstatedir do # bindir=/usr/bin eval "$x=`pkggetdir $x`" # --bindir=$root\$bindir if [ "$x" != libexecdir -a "$x" != docdir ]; then confopt="$confopt --$x=$z\$$x" mesonopt="$mesonopt --$x=$z\$$x" fi done export LIBSUFF=${libdir##*/lib} if [ "$SDECFG_CONFIGURE_OPTS" ]; then var_append confopt " " "$SDECFG_CONFIGURE_OPTS" fi if [ "$SDECFG_DEBUG" = 0 ]; then var_append confopt " " "--disable-debug" fi if [ "$SDECFG_DISABLE_NLS" = 1 ]; then var_remove confopt ' ' '--enable-nls' var_append confopt ' ' '--disable-nls' fi confopt="$confopt \$extraconfopt" atstage cross && var_append confopt ' ' '--with-sysroot=$root' if atstage toolchain; then confopt="$confopt --target=\$arch_target --build=\$arch_build --host=\$arch_build" else confopt="$confopt --build=\$arch_build --host=\$arch_target" fi } # # eval_config_command $(eval echo $confopt) # function eval_config_command() { local config_command for x in /usr/share/automake/*; do [ -x "$x" -a -f "$x" ] || continue x="$(basename "$x")" if [ -L $x -a ! -e $x ]; then echo "Fixing dead symlink $x." ln -sf /usr/share/automake/$x . fi done if atstage cross; then create_config_cache >> config.cache grep -q '.--cache-file=' $configscript && set -- "$@" "--cache-file=./config.cache" export cache_file=config.cache fi config_command="$configprefix $configscript" sub_scripts="$(find $(dirname $configscript) -name configure)" if [ "$cleanconfopt" == "0" ]; then config_command="$config_command $@" else # remove unsupported config script options for x; do if grep -q "[[ ]${x%%=*}[]= ):]" $configscript $sub_scripts; then config_command="$config_command $x" elif [[ $x = --*able-* ]] && egrep -q "\--(en|dis)able-\*" $configscript || [[ $x = --with* ]] && egrep -q "\--with(|out)-\*" $configscript; then echo "Autodetection for option impossible: " \ "$x passed thru." config_command="$config_command $x" else echo "Removing unsupported '$x' from configure option string." fi done fi echo Running "$config_command" eval "$config_command" # the missing script is generally not very helpful, ... if [ -f build/missing ]; then echo '#!/bin/true' > build/missing; fi if [ -f missing ]; then echo '#!/bin/true' > missing; fi } # run 'make check' if Makefile supports it. # function run_check() { if grep -q -e "^check:" Makefile; then echo "Running make check" $MAKE check fi if grep -q -e "^test:" Makefile; then echo "Running make test" $MAKE test fi } # move the static libs from lib to usr/lib and correct the libdir used # inside the .la file # postflist_static_lib() { echo "Processing static lib corrections ..." egrep '^(lib|lib64)/.*\.(a|la)$' $builddir/flist.txt | while read fn; do [ -e $root/$fn -o -L $root/$fn ] || continue if [[ $fn = *.a ]]; then mv -fv $root/$fn $root/usr/$fn else sed "s,\([ =']\)/lib\(.*\),\1/usr/lib\2,g" \ $root/$fn > $root/usr/$fn so=${fn%.la}.so ln -svf ../../$so $root/usr/$so add_flist $root/usr/$so rm $root/$fn fi add_flist $root/usr/$fn done # this check might be removed in the future when we decide this is not # an issue anymore ... echo "Verifing the .la files ..." defect_la="`egrep '(lib|lib64)/.*\.la$' $builddir/flist.txt | xargs egrep 'dependency_libs=.*-pthread.*' | cut -d : -f1 | sort -u | tr '\n' ' '`" if [ "$defect_la" ]; then abort "-pthread in: $defect_la!" fi defect_la="`egrep '(lib|lib64)/.*\.la$' $builddir/flist.txt | xargs egrep "dependency_libs=.*(TOOLCHAIN|BACKUP|$SDECFG_ID).*" | cut -d : -f1 | sort -u | tr '\n' ' '`" if [ "$defect_la" ]; then local la echo_warning "Detected problems in following libtool files:" for la in $defect_la; do echo_warning " $la" done echo_warning "In absence of a proper fix (or replacement) for libtool and friends," echo_warning "for now the .la files are automatically corrected." # Cleanup dependency_libs, remove build system path local dependency_libs local dlibsnew="" local dlibtmp deplib local libsub=${libdir##*/} for la in $defect_la; do eval `grep ^dependency_libs= $root/$la` for deplib in $dependency_libs; do if [ $libsub != lib ]; then case "$deplib" in */lib|*/lib/*) deplib="`echo $deplib | sed "s,/lib$,/$libsub,g; s,/lib/,/$libsub/,g"`" ;; esac fi case "$deplib" in *TOOLCHAIN*|*BACKUP*|*$SDECFG_ID*) ;; *) dlibtmp=$dlibsnew; var_remove dlibtmp ' ' "$deplib" [ "$dlibtmp" = "$dlibsnew" ] && var_append dlibsnew ' ' "$deplib" ;; esac done sed -i "s,^dependency_libs=.*,dependency_libs='$dlibsnew'," $root/$la dlibsnew= done fi } postflist_fix_cross_scripts() { grep 'bin/' $builddir/flist.txt | while read f; do if [ -f "$root/$f" ] && grep -qa '#!.*TOOLCHAIN/cross.*bin/' $root/$f; then echo_warning "Sed'ing TOOLCHAIN.*bin in $f" sed -i '1s,^#!.*TOOLCHAIN/cross.*bin/,#!/usr/bin/env -S ,' "$root/$f" fi done } # Parse the *.desc file. Use the description from PKG-DESC-FORMAT and # save the tag data in $desc_*. # parse_desc() { unset ${!desc_*} tags="`sed -n '/^\[/ { s/][^]]*$//; s/. ./|/g; s/^\[//; p }' \ $base/misc/share/PKG-DESC-FORMAT`" descs=$base/package/*/$1/$1.desc [ -e $base/architecture/$arch/package/$1/$1.desc ] && var_append descs ' ' $base/architecture/$arch/package/$1/$1.desc [ -e $base/target/$target/package/$pkg/$pkg.desc ] && var_append descs ' ' $base/target/$target/package/$1/$1.desc for desc in $descs; do #echo_status "Reading $desc ..." for tag in $tags; do tagdata="`egrep -a "^\[($tag)\]" $desc | cut -f2- -d']' | sed 's,^ ,,'`" tag="`echo $tag | cut -f1 -d'|' | tr - _`" # only overwrite defined tags [ "$tagdata" ] && eval "desc_$tag=\"\$tagdata\"" done done ver="`echo "$desc_V" | tail -n 1 | cut -f1 -d' '`" extraver="`echo "$desc_V" | tail -n 1 | cut -s -f2- -d' '`" [ -z "$extraver" ] && extraver="${sdever//DEV-*/DEV}" } # This function is used for forcing a file to be in the flist # add_flist() { for addfile; do echo "$addfile" | fl_wrparse -D -r "$xroot/" \ >> $builddir/flist.txt done } # This function is used for forcing a package to be in the dependency list # add_dependency() { for addpackage; do echo "$addpackage: add_dependency()" \ >> $builddir/dependencies.debug done } # This function is used to subsitute some important variables # using a D_ prefix thru m4 ... sde_substitute() { sed -e s,D_prefix,$prefix,g -e s,D_sysconfdir,$sysconfdir,g \ -e s,D_docdir,$docdir,g -e s,D_localstatedir,$localstatedir,g \ -e s,D_datadir,$datadir,g -e s,D_infodir,$infodir,g \ -e s,D_bindir,$bindir,g -e s,D_sbindir,$sbindir,g \ -e s,D_libdir,$libdir,g -e s,D_libexecdir,$libexecdir,g \ -e s,D_mandir,$mandir,g -e s,D_includedir,$includedir,g \ -e s,D_ver,$ver,g $1 } # This outputs a predefined config.cache file as it needed by some # packages to cross-build correctly in stages 0 and 1. # create_config_cache() { cat $base/scripts/config.cache if [ $createarchcache -eq 1 ]; then cat <<-EOT # Architecture specific stuff\n" arch_sizeof_char=1 ac_cv_sizeof_char=1 ac_cv_sizeof_short=$arch_sizeof_short ac_cv_sizeof_int=$arch_sizeof_int ac_cv_sizeof_long=$arch_sizeof_long ac_cv_sizeof_long_long=$arch_sizeof_long_long ac_cv_sizeof_char_p=$arch_sizeof_char_p ac_cv_sizeof_void_p=$arch_sizeof_char_p ac_cv_c_bigendian=$arch_bigendian EOT fi } create_meson_cross() { cat <<-EOT [binaries] c = '$CC' cpp = '$CXX' ar = '$AR' strip = '$STRIP' pkgconfig = 'pkg-config' llvm-config = 'llvm-config' cmake = 'cmake' rust = [ 'rustc' ] [properties] sizeof_int = $arch_sizeof_int sizeof_wchar_t = $arch_sizeof_int sizeof_void* = $arch_sizeof_char_p alignment_char = 1 alignment_void* = $arch_sizeof_int alignment_double = 4 has_function_printf = true needs_exe_wrapper = true [host_machine] system = '$SDECFG_KERNEL' cpu_family = '$(uname -m)' cpu = '$arch' # or uname -m? EOT [ $arch_bigendian == "yes" ] && echo "endian = 'big'" || echo "endian = 'little'" } # Generate a CMake toolchain file for cross builds # create_cmake_toolchain_file() { cat <<-EOT SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_VERSION 1) SET(CMAKE_C_COMPILER $CC) SET(CMAKE_CXX_COMPILER $CXX) SET(CMAKE_FIND_ROOT_PATH $root) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) SET(PACKAGE_VENDOR "T2 SDE") EOT } # Abort build before actual build starts # (is overwritten in Build-Pkg) # abort() { echo -e "The package build aborted with the following config" \ "error:\n$*" > $root/var/adm/logs/$stagelevel-$xpkg.err echo_errorquote "$(< $root/var/adm/logs/$stagelevel-$xpkg.err)" echo_pkg_abort $stagelevel $repository $xpkg exit 1 } # Dump Environment # dump_env() { # Dump $base - only set if there is not already an older value. # echo "base=\"\${base:-$base}\"" # Dump all variables including their flags, but skip read-only # variables and $base. # # Substitute base directory with ${base}. # for name in ${!a*} ${!b*} ${!c*} ${!d*} ${!e*} ${!f*} ${!g*} ${!h*} \ ${!i*} ${!j*} ${!k*} ${!l*} ${!m*} ${!n*} ${!o*} ${!p*} \ ${!q*} ${!r*} ${!s*} ${!t*} ${!u*} ${!v*} ${!w*} ${!x*} \ ${!y*} ${!z*} \ ${!A*} ${!B*} ${!C*} ${!D*} ${!E*} ${!F*} ${!G*} ${!H*} \ ${!I*} ${!J*} ${!K*} ${!L*} ${!M*} ${!N*} ${!O*} ${!P*} \ ${!Q*} ${!R*} ${!S*} ${!T*} ${!U*} ${!V*} ${!W*} ${!X*} \ ${!Y*} ${!Z*} ${!_*} do [ $name = base -o $name = PWD ] && continue if declare -p $name | head -n 1 | grep -qv '^declare -[a-z]*r' then declare -p $name | sed "s,\\(^\\|[\"=:]\\)$base\\([\"=:/]\\|\$\\),\\1\${base}\\2,g" fi done # Dump functions # declare -f | sed 's/^declare -f //; s/<<(/< <(/;' # Dump aliases # alias } # Estimate package build time based on binutils reference time and cached build time. # pkgbuildtime() { local pkg="$1" buildtime [ -e $base/build/$SDECFG_ID/TOOLCHAIN/reftime ] && local reftime=$(< $base/build/$SDECFG_ID/TOOLCHAIN/reftime) [ -e $base/package/*/$pkg/$pkg.cache ] && buildtime=$(sed -n "s/\[BUILDTIME\] \([^ ]*\).*/\1/p" $base/package/*/$pkg//$pkg.cache) [ "$buildtime" = 0 ] && buildtime=1 # old quantizised to 0, or just fast: at least something [ "$reftime" -a "$buildtime" ] && gawk "BEGIN { parallel=.95; buildtime=$reftime * $buildtime / 100 / 100; \ time = int(buildtime * (1-parallel) + buildtime * parallel / $SDECFG_PARALLEL_MAX); \ printf(\"%d\n\", time > 0 ? time : 1); }" } # Check if a package is already installed # # It does check the build-list if not in the rebuild stage - and # the really installed package data for rebuilds (and so manual builds). # pkginstalled() { # add optional dep, if not supressed with "-n" [ "$1" == "-n" ] && shift || var_append desc_E $'\n' "opt $1" if ! atstage rebuild; then local pattern="${1//+/\\+}" egrep -q "^X.* ($pattern) " $base/config/$config/packages && return else [ -f $root/var/adm/packages/$1 ] && return fi [ -e $base/package/*/$1 ] || echo_warning "Installed package checked: $1 does not exist" false } # pkgprefix [-t] [ ] # Returns the prefix or the location of a 'type' of an already built package, # or aborts the build if not yet installed. # When run in the test mode [-t] it returns an error code accordingly. # pkgprefix() { local type= pkg= local dotest= abortmsg= local prefix= value= # -t : only see if it's possible to get the values if [ "$1" = "-t" ]; then dotest=1; shift fi if [ $# -eq 2 ]; then type="$1"; shift fi pkg="$1" # test usual error causes if [ -z "$pkg" ]; then abort "pkgprefix: you must specify a package" elif [ ! -f "$root/var/adm/packages/$pkg" ]; then abortmsg="package $pkg is not present" elif grep -q "^Prefix:" "$root/var/adm/packages/$pkg"; then prefix=$(grep "^Prefix: " "$root/var/adm/packages/$pkg" | cut -d' ' -f2-) else abort "pkgprefix: $pkg record is to old (no Prefix: entry), please rebuild it." fi if [ "$dotest" ]; then # test mode: abort or continue if [ "$abortmsg" ]; then echo "pkgprefix: $abortmsg" 1>&2 return 1 else return 0 fi elif [ "$abortmsg" ]; then echo "pkgprefix: $abortmsg" 1>&2 elif [ -z "$type" -o "$type" = "prefix" ]; then echo "$prefix" return 0 elif [ "$type" = "ver" ]; then value=$(grep "^Package Name and Version:" "$root/var/adm/packages/$pkg" | cut -d' ' -f6) else value=$(grep "^Location $type: " "$root/var/adm/packages/$pkg" | cut -d' ' -f3-) if [ -z "$value" ]; then # try default location for that $prefix value=$(xpkg="$pkg"; pkggetdir "$type") fi fi echo "${value:-PKGPREFIX_ERROR}" } # pkggetdir (needs $prefix and $xpkg) # returns the location for the file of a 'type' considering it's prefix # pkggetdir() { local xprefix=${prefix:+/$prefix} case "$1" in bindir) echo "$xprefix/bin" ;; sbindir) echo "$xprefix/sbin" ;; libdir) if atstage toolchain; then echo "$xprefix/lib" elif [ "$SDECFG_MULTILIB" = 1 ]; then case $arch_machine in powerpc64*|sparc64|loongarch64|mips64|riscv*|x86_64) if [ "$SDECFG_X8664_X32" = 1 ]; then echo "$xprefix/libx32" elif [ "$SDECFG_MIPS64_N32" = 1 ]; then echo "$xprefix/lib32" else echo "$xprefix/lib64" fi ;; *) echo "$xprefix/lib" ;; esac else echo "$xprefix/lib" fi ;; libexecdir) echo "${xprefix:-/usr}/libexec" ;; datadir) echo "${xprefix:-/usr}/share" ;; infodir) echo "${xprefix:-/usr}/info" ;; mandir) echo "${xprefix:-/usr}/man" ;; docdir) echo "${xprefix:-/usr}/doc/$xpkg" ;; includedir) echo "${xprefix:-/usr}/include" ;; sysconfdir) echo "/etc${xprefix##/usr*}" ;; localstatedir) echo "/var${xprefix##/usr*}" ;; esac } # This function generates the T2 package checksum of $confdir. # The checksum includes the filenames and content (except of the .cache), # including subdirs but without whitespaces and comments and some tag lines # that are not vital for rebuilds during update checks. # # pkgchksum package-name | full-patch # pkgchksum() { ( local md5sum="md5sum" if ! type -p $md5sum > /dev/null; then md5sum="md5 -r" fi # expand to full path if only a package name was specified [[ $1 == */* ]] || set $base/package/*/$1/ cd $1 || return 1 # find all files (without hidden (e.g. .svn) files) find . ! -path '*/.*' ! -name '*.cache' -print -exec cat \{\} \; \ 2>/dev/null | # strip some unimportant stuff (e.g. comments, whitespaces, ...) sed \ -e '/^[ ]*#.*/d' \ -e '/^\[COPY\]/d' \ -e '/^\[CV-*\]/d' \ -e '/^\[[T,I,U,A,M,L,S,C]\]/d' \ -e 's/[\t ]*//g' \ -e '/^ *$/d' | $md5sum | cut -d ' ' -f 1 ) } # Create Package Database for gasgui install tool # create_package_db() { rm -f $3.tmp for file in $(echo $1/descs/*); do [ -f "$file" ] || continue pkg="${file##*/}" # only include the package if a binary file is available if [ "$SDECFG_PKGFILE_VER" = 1 ]; then v=-$(grep '^Package Name and Version' \ $1/packages/$pkg | cut -f6 -d' ') else v="" fi bfile=${pkg}${v}.$SDECFG_PKGFILE_TYPE if [ -e $2/$bfile ]; then [ "$pkg" = TRANS.TBL ] && continue ( echo -e "$pkg" echo -e "\027" cat $1/descs/$pkg | grep -v '\[COPY\]' echo -e "\027" cat $1/dependencies/$pkg echo -e "\027" cat $1/md5sums/$pkg echo -e "\027" echo -e "\004" ) >> $3.tmp else echo_error "Binary file for $bfile not present." \ "Skipped in package database." fi done gzip -c $3.tmp > $3; rm -f $3.tmp } # Add files to the 'badfiles' list # register_badfiles() { local x desc="$1" shift for x in "$@"; do var_append badfiles $'\n' " $x\$" badfiles_desc[$badfiles_nr]=" $x\$"$'\n'"$desc" ((badfiles_nr++)) done } # Detect the available patchfiles # detect_patchfiles() { local x= y= patchfiles="`ls $confdir/*.patch{,.$arch,.$SDECFG_KERNEL} \ $confdir/*.patch_$xpkg{.$arch,.$SDECFG_KERNEL} \ 2> /dev/null | tr '\n' ' '`" atstage toolchain && var_append patchfiles ' ' "`ls $confdir/*.patch.cross0{,.$arch,.$SDECFG_KERNEL} \ 2>/dev/null | tr '\n' ' '`" atstage cross && var_append patchfiles ' ' "`ls $confdir/*.patch.cross{,.$arch,.$SDECFG_KERNEL} \ 2>/dev/null | tr '\n' ' '`" for x in $(get_reverted $targetchain); do for y in pkg_$pkg.patch{,.$arch,.$SDECFG_KERNEL} xpkg_$xpkg.patch{,.$arch,.$SDECFG_KERNEL}; do if [ -f $base/target/$x/$y ]; then patchfiles="$patchfiles $base/target/$x/$y" fi done done # get additional patches from $targetdir/package/$pkg and architecture/package/$pkg - # if it's not the confdir ie. contains the .desc file which overrides the default for x in $targetdir/package/$pkg $base/architecture/$arch/package/$pkg; do if [ $confdir != $x ]; then var_append patchfiles ' ' "`ls $x/*.patch{,.$arch} 2> /dev/null | tr '\n' ' '`" fi done } get_compressor() { local x case "$1" in *.bz2|*.tbz2) x="bzip2 -d" ;; *.gz|*.tgz) x="gzip -d" ;; *.lz) x="lzip -d" ;; *.lzma) x="lzma -d" ;; *.xz) x="xz -d" ;; *.Z) x="compress -d" ;; *.zst) x="zstd -d" ;; *.br) x="brotli -d" ;; esac [ "$x" ] && echo "$x" } # Apply the given $patchfiles # [ hook called for each patch ] [ filter script ] # apply_patchfiles() { local hook="$1" local filter="$2" [ "$filter" ] || filter=cat for x in $patchfiles; do # correct the absolute path, e.g. for patchfiles supplied in # the .desc file, we assume relative path patches are mirrorable if [ ! -e "$x" -a -n "${x##*/*}" ]; then x="$base/download/mirror/${x:0:1}/$x" fi echo "Applying $x" local compressor="$(get_compressor "$x")" if [ "$compressor" ]; then patch_file=`mktemp` $compressor < $x > $patch_file else patch_file=$x fi $filter $patch_file | patch $patchopt [ "$compressor" ] && rm $patch_file eval "$hook" done } # ------------------------------------------------------------------- # The automatic extraction of archive (prior to building) supports # multiple archive types. For every archive type we have a separate # func that knows how to extract the archive. However, every func # should deliver two file: untar.txt and xsrcdir.txt. # # untar.txt needs to contain all extracted files. # xsrcdir.txt need to contain the top level extraction directories. # ------------------------------------------------------------------- autoextract_tar() { echo "Extracting $xsrctar ($taropt) ... " tar -v $taropt $1 > untar.txt } autoextract_zip() { echo "Extracting $xsrctar ($zipopt) ... " unzip $zipopt $1 | sed 's,^.*/$,,' | cut -f4 -d" " | grep -v "^$" > untar.txt } autoextract_7z() { echo "Extracting $xsrctar ($sevenzipopt) ... " 7za $sevenzipopt $1 | sed 's,/,,' | cut -f3 -d" " | grep -v "^$" > untar.txt } # Main program for building a package # build_this_package() { if [ ".$desc_SRC" == "." ]; then # Autodetect source tar and extract it # if [ "$srctar" = auto ]; then xsourceballs=$(echo "$desc_D" | head -n 1 | sed 's, ,\t,g; s,\t\t*,\t,g' | cut -f2) if [ -z "$xsourceballs" ]; then echo "Can't auto-detect srctar for package '$xpkg'!" false fi else xsourceballs="$srctar" fi elif [ "$srctar" = auto ]; then sourceballs=$(echo "$desc_D" | sed 's, ,\t,g; s,\t\t*,\t,g' | cut -f2) xsrcpattern=$(echo "$desc_SRC" | sed 's, ,\t,g; s,\t\t*,\n,g') xsourceballs=$(echo "$sourceballs" | grep -F "$xsrcpattern") else xsourceballs="$srctar" fi for xsrctar in $xsourceballs; do saved_patchfiles="$patchfiles" var_append patchfiles " " \ "`ls $confdir/*.patch.${xsrctar/-[v0-9]*/} 2> /dev/null`" if [ "$xsrctar" != none -a "$autoextract" = 1 ]; then cd $builddir if [ -z "$custextract" ]; then # No custom extraction, so determine what # autoextraction to use. case "$xsrctar" in *.zip) custextract="autoextract_zip" ;; *.7z) custextract="autoextract_7z" ;; *) custextract="autoextract_tar" ;; # *.tar.bz2|*.tbz2|*.tbz esac fi if [ -n "$custextract" ]; then # Do the actual extraction of the archive. eval "$custextract $archdir/$xsrctar" sed 's,^\./,,; /^$/d' untar.txt | cut -f1 -d/ | sort -u > xsrcdir.txt fi # if [ "$srcdir" = auto ]; then xsrcdir=${xsrctar%.tar.*} xsrcdir=${xsrcdir%.t?z*} if [ ! -d $xsrcdir ]; then for x in $pkg-$ver ${pkg}_$ver $pkg \ $xpkg-$ver ${xpkg}_$ver $xpkg \ "$(cat xsrcdir.txt)" do [ -d "$x" ] && xsrcdir="$x" done fi else xsrcdir="$srcdir" fi # if [ "$chownsrcdir" = 1 ]; then echo "Fixing ownership and permissions ..." chown -R 0:0 $builddir/$xsrcdir fi # if [ "$nocvsinsrcdir" = 1 ]; then echo "Removing CVS, .svn, {arch} and .arch-ids directories ..." egrep '(^|/)(CVS|\.svn|\{arch\}|\.arch-ids)(/|$)' untar.txt | while read x; do echo "Removing $x ..." rm -rf "$x" done fi # echo "Changeing into $builddir/$xsrcdir ..." cd $builddir/$xsrcdir # Apply patches # hook_eval prepatch [ $autopatch = 1 ] && apply_patchfiles hook_eval postpatch else cd $builddir fi if [ "$createprefix" = 1 ]; then echo "Creating $root/$prefix/<..> if required ..." for x in $foodirlist; do eval "x=\"$root\$$x\"" if [ ! -e $x ]; then mkdir -p $x rmemptydir="$rmemptydir $x" fi done fi if [ ".$custmain" = "." ] then hook_eval preconf # Maybe generate a configure first # if [ "$autogen" = 1 -o \ \( -f configure.in -a ! -f configure -a "$autogen" != 0 \) ]; then if [ -f autogen.sh ]; then echo "Running package autogen script" sed -i 's,.*/configure ,: # &,' autogen.sh sh autogen.sh $(eval echo $confopt) else echo "Running builtin autogen script" libtoolize --force --automake aclocal $ACLOCAL_FLAGS if grep AM_INIT_AUTOMAKE \ configure.[ia][nc] then automake --add-missing; fi autoconf fi fi # Run configure scripts etc. # if [ "$runconf" = 1 ]; then if [ -n "$(type -p $configscript)" -o "$autogen" = 1 ]; then eval_config_command $(eval echo $confopt) fi fi # CMake style # if [ "$runcmake" = 1 -a ! -f Makefile ] && [ -e $cmakelists -o -e ../$cmakelists ]; then if atstage cross; then create_cmake_toolchain_file >> t2.cmake var_insert cmakeopt " " "-DCMAKE_TOOLCHAIN_FILE=t2.cmake" fi # top-level CMakeLists? [ ! -e $cmakelists ] && cmakelists="../$cmakelists" # already ending with a directory? [[ "$cmakeopt" = *. ]] || var_append cmakeopt ' ' "${cmakelists%%/*}" eval echo "Running cmake $cmakeopt" cmake $(eval echo $cmakeopt) fi # automated package build # styles without make run first: if [ -f setup.py -a "$runpysetup" = 1 ]; then pyconfopt="${pyconfopt:=--prefix $root/$prefix}" hook_eval premake eval echo "Running ${pyscript:-python} setup.py build install $pyconfopt" eval ${pyscript:-python} setup.py build install $pyconfopt hook_eval postmake elif [ -f pyproject.toml -a "$runpipinstall" = 1 ]; then hook_eval premake eval echo "Running ${pyscript:-python} -m pip install ." eval ${pyscript:-python} -m pip install . hook_eval postmake elif [ -f meson.build -a "$runmeson" = 1 ]; then if atstage cross; then create_meson_cross >> cross.ini CC=cc CXX=c++ # make meson happy :-/ var_append mesonopt " " "--cross-file cross.ini" fi hook_eval premake eval echo "Running meson $mesonopt" eval "meson $mesonopt" hook_eval inmake eval echo "Running ninja -C objdir/ -j$SDECFG_PARALLEL_MAX install" atstage cross && export DESTDIR=$root ninja -C objdir/ -j$SDECFG_PARALLEL_MAX install # TODO: $ninjainstopt hook_eval postmake elif [ -f Cargo.toml -a "$runcargo" = 1 ]; then hook_eval premake if [ "$cargoopt" -a ! "$cargoinstopt" ]; then eval echo "Running cargo $cargoopt" eval "cargo $cargoopt -j$SDECFG_PARALLEL_MAX" fi hook_eval inmake if [ "$cargoinstopt" ]; then eval echo "Running cargo $cargoinstopt" eval "cargo $cargoinstopt -j$SDECFG_PARALLEL_MAX" fi hook_eval postmake elif [ -f SConstruct -a "$runscons" = 1 ]; then hook_eval premake if [ "$sconsopt" ]; then eval echo "Running scons $sconsopt" eval "scons $sconsopt" fi hook_eval inmake if [ "$sconsinstopt" ]; then eval echo "Running scons $sconsinstopt" eval "scons $sconsinstopt" fi hook_eval postmake elif [ -f build.zig -a "$runzig" = 1 ]; then # some projects still use makefile hook_eval premake zigconfopt="${zigconfopt:=--prefix $root/$prefix}" eval echo "Running zig build $zigconfopt" eval "zig build $zigconfopt" hook_eval inmake eval echo "Running zig build install" eval "zig build install" hook_eval postmake elif [ -f go.mod -a "$rungo" = 1 ]; then # some projects still use makefile hook_eval premake eval echo "Running go build $goconfopt" eval "go build $goconfopt" hook_eval inmake #eval "go install" # No universal way to install? hook_eval postmake elif [ -f META6.json -a "$runzef" = 1 ]; then hook_eval premake var_append zefopt " " "--force-install --/depends --/test-depends --/build-depends" var_append zefopt " " "--install-to=inst#$root/$prefix/share/perl6/site" hook_eval inmake eval echo "Running zef install . $zefopt" eval "zef install . $zefopt" hook_eval postmake else # styles that include a make run if [ ! -f Makefile -a ! -f makefile -a \ -f Makefile.PL -a "$runmkpl" = 1 ]; then echo "Running perl Makefile.PL ${plconfopt:-INSTALLDIRS=perl}" perl Makefile.PL ${plconfopt:-INSTALLDIRS=perl} if atstage cross; then sed -i "s,/TOOLCHAIN/cross/usr/lib,$libdir,g" Makefile sed -i "s,/TOOLCHAIN/cross,,g" Makefile var_append makeopt ' ' 'PERL=perl FULLPERL=perl' var_append makeinstopt ' ' 'PERL=perl FULLPERL=perl DESTDIR=' fi fi # if [ ! -f Makefile -a ! -f makefile -a \ -f Imakefile -a "$runxmkmf" = 1 ]; then echo "Running xmkmf -a" xmkmf -a fi # # Build it # hook_eval premake if [ "$runmake" = 1 -a "$makeopt" ]; then eval echo "Running $MAKE $makeopt" eval "$MAKE $makeopt" fi hook_eval inmake if [ "$runmake" = 1 -a "$makeinstopt" ]; then eval echo "Running $MAKE $makeinstopt" eval "$MAKE $makeinstopt" fi hook_eval postmake fi else echo_warning "The use of custmain is deprecated, please use hooks instead." eval "$custmain" for x in preconf premake inmake postmake; do if eval "[ -n \"\$hookdirty_$x\" ]"; then echo "Hook $x is still marked as dirty running it, now ..." hook_eval $x fi done fi if [ "$createdocs" != 0 ]; then if [ ! -e $root$docdir ]; then mkdir -p $docdir rmemptydir="$rmemptydir $root$docdir" fi [ -z "$createdocs" ] && createdocs="$SDECFG_CREATE_DOCS" fi if [ "$createdocs" = 1 ]; then echo "Trying to copy the default documentation ..." for x in [A-Z][A-Z]* *.lsm ChangeLog*; do [ "${x#*.[cho0-9]}" ] || continue [ "${x#*.info*}" ] || continue [ "${x#*.TAR*}" ] || continue [ "${x#*akefile*}" ] || continue [ -f $x ] && cp -v $x $root$docdir/$x done echo "Trying to copy even more documentation ..." [ -d $builddir/$xsrcdir ] && cd $builddir/$xsrcdir for x in `find -type d \( -name 'doc' -o -name 'docs' \ -o -name '[Dd]ocumentation' \) ! -empty` do if [ -d "$x" -a "`echo $x/*`" != "$x/*" ] then cp -rLv $x/* $root$docdir || true; fi done for x in $confdir/*.doc; do if [ -f $x ] then cp -v $x $root$docdir/${x%.doc}; fi done find $root$docdir/ -name '*.[0-9]' -o -name '*.info*' \ -o -name '[Mm]akefile*' | xargs -r rm -f 2> /dev/null || true find $root$docdir/* -type d -empty 2> /dev/null | xargs -r rmdir 2> /dev/null || true fi hook_eval postdoc if atstage native && [ -f /sbin/ldconfig ]; then echo "Running ldconfig" ldconfig fi patchfiles="$saved_patchfiles" done if [ "$rmemptydir" ]; then rmdir $rmemptydir 2> /dev/null || true fi return 0 } # source_file cksum file url # # Create the file path from 'file' and 'url'. # cksum and url are ignored # ([D] tag compatible format) # source_file() { local pre="" file="$2" url="$3" mirror="mirror" # '-' as $url prefix means, nomirrorable [ "${url:0:1}" == "-" ] && mirror="local" # inside Build-Pkg $archdir is set if [ -n "$archdir" ]; then pre=$base/ fi echo ${pre}download/${mirror}/${file:0:1}/$file } # match_source_file [-p] pattern [[package] ...] # # Returns path and name of a downloaded file from a list of packages, matching # a grep pattern. Without -p it only returns it's name, not the path. # match_source_file() { local pattern= package= showpath=0 local x= file= url= mirror= local found=1 while [ "$1" ]; do case "$1" in -p) showpath=1; shift ;; *) break ;; # no abort as the pattern might start with a '-' esac done pattern="$1"; shift for package in ${*:-$pkg}; do while read x x file url x; do found=0 if [ $showpath -eq 0 ]; then echo $file else [ "${url:0:1}" == "-" ] && mirror="local" || mirror="mirror" echo $base/download/${mirror}/${file:0:1}/$file fi done < <(for f in $base/target/$target/package/$package/$package.desc \ $base/architecture/$arch/package/$package/$package.desc \ $base/package/*/$package/$package.desc; do grep -a -e "^\[D\] [^ ]* .*$pattern" $f 2> /dev/null grep -q -a -e "^\[D\]" $f 2> /dev/null && break done) done return $found } # create the virtual $archdir symlinks # populate_archdir() { local x= missing=0 for x in `match_source_file -p .`; do if [ ! -f $x ]; then echo_warning "File not found: ${x#$base/}" missing=1 elif [ ! -e "$builddir/archdir/${x##*/}" ]; then ln -vs $x $builddir/archdir/ fi done if [ $missing -eq 1 ]; then echo_warning "Did you run scripts/Download for this package?" false fi } # search for the package confdir # detect_confdir() { confdir= for x in package/*/$pkg/$pkg.desc; do [ -f "$x" ] || continue if [ "$confdir" ]; then echo_pkg_deny $stagelevel $pkg "in multiple trees" echo "Package $pkg in multiple trees!" \ > $root/var/adm/logs/$stagelevel-$xpkg.err exit 1 fi x=${x#package/} x=${x%%/*} confdir="$base/package/$x/$pkg" repository=$x done if [ -e architecture/$arch/package/$pkg/$pkg.desc ] then confdir="$base/architecture/$arch/package/$pkg"; fi if [ -e $base/target/$target/package/$pkg/$pkg.desc ] then confdir="$base/target/$target/package/$pkg"; fi } # initialize standard vars and hooks # init_vars_and_hooks() { makeopt='CC="$CC" CPP="$CPP" CXX="$CXX"' sconsopt='CC=$CC PREFIX=/$prefix LIBDIR=$libdir' cargoopt='build' cargoinstopt='install --path . --root $root/$prefix --no-track --force' # -Z no-index-update goconfopt='-buildmode=pie -trimpath -mod=readonly -ldflags=-linkmode=external' # support both lowercase GNU and uppercase BSD conventions if atstage toolchain; then makeopt="$makeopt"' prefix="$root/$prefix" PREFIX="$root/$prefix" docdir="$root$docdir"' cmakeopt='-DCMAKE_INSTALL_PREFIX="$root/$prefix"' else makeopt="$makeopt"' prefix="/$prefix" PREFIX="/$prefix" docdir="$docdir"' cmakeopt='-DCMAKE_INSTALL_PREFIX="/$prefix" -DCMAKE_INSTALL_LIBDIR="$libdir" -DCMAKE_LIBRARY_PATH="$libdir"' fi if [ "$SDECFG_DEBUG" = 1 ]; then var_append cargoinstopt ' ' '--debug' var_append cmakeopt ' ' '-DCMAKE_BUILD_TYPE=Debug' else var_append cargoopt ' ' '--release' var_append cmakeopt ' ' '-DCMAKE_BUILD_TYPE=Release' fi if ! atstage native; then makeopt="$makeopt"' CC_FOR_BUILD="$BUILDCC"' makeopt="$makeopt"' BUILDCC="$BUILDCC" BUILD_CC="$BUILD_CC"' makeopt="$makeopt"' HOSTCC="$HOSTCC" HOST_CC="$HOST_CC"' makeopt="$makeopt"' STRIP="$STRIP" AR="$AR" LD="$LD" AS="$AS"' makeopt="$makeopt"' RANLIB="$RANLIB" NM="$NM"' fi if atstage native; then flistdel="$flistdel|`echo $base | sed s,^/,,`/.*" fi if atstage cross; then cmakeopt="$cmakeopt -DCMAKE_SYSTEM_PROCESSOR=$(echo $arch | arch2uname)" # everyting non-DESTDIR is passed in the specific packages makeinstopt="$makeopt"' DESTDIR="$root" install' sconsinstopt='PREFIX=$root/$prefix LIBDIR=$root$libdir install' cargoopt="$cargoopt"' --target ${arch_target}' # /-t2-/-unknown-} cargoinstopt="$cargoinstopt"' --target ${arch_target}' # /-t2-/-unknown-} else makeinstopt="$makeopt"' install' sconsinstopt="$sconsopt"' install' fi atstage cross && hook_add postflist 2 'postflist_fix_cross_scripts' [ "$SDECFG_DO_CHECK" = 1 ] && hook_add inmake 6 'run_check' [ "$SDECFG_STATIC_IN_USR" = 1 ] && hook_add postflist 3 'postflist_static_lib' createarchcache=0 custmain="" configprefix="" autogen= configscript="./configure" extraconfopt="" cmakelists="CMakeLists.txt" srcdir=auto srctar=auto taropt="-xf" # --use-compress-program=zstd sevenzipopt="x" mainfunction="build_this_package" runconf=1 runmake=1 runxmkmf=1 runmkpl=1 runpysetup=1 runpipinstall=1 runcmake=1 runmeson=1 runcargo=1 rungo=1 runscons=1 runzig=1 runzef=1 autopatch=1 autoextract=1 chownsrcdir=1 nocvsinsrcdir=1 cleanconfopt=1 patchopt="-bfp1 -z .orig" createprefix=1 createdocs="" rmemptydir="" check_shared=1 check_usrlocal=1 check_badfiles=1 badfiles="" badfiles_nr=0 declare -a badfiles_desc } # this is a 2nd lightweight and modular "build this package" implementation # currently only used for the postlinux stuff - later maybe for more -ReneR # build_package() { logstamp=$PWD/log ( set -e pushd $base super=$pkg pkg="$1" xpkg="$pkg" [ "$2" ] && conffile="$2" || conffile="$pkg.conf" unset ${!hook*} declare -a hook_functions='()' hook_fcounter=0 init_vars_and_hooks detect_confdir detect_patchfiles parse_desc $pkg # Erase positional parameters to prevent unintended current # arguments pssing to the loaded script. set -- eval "$desc_O" echo_status "Building $xpkg within $super (using $conffile)" for x in $(get_expanded $base/target/%/pkg_$pkg.conf $targetchain) \ $targetdir/package/$pkg/$pkg.conf \ architecture/$arch/package/$pkg/$pkg.conf \ $confdir/$conffile; do if [ -f $x ]; then if [[ $x == */$conffile ]]; then echo "Reading package configuration ($conffile) from package directory." else echo "Reading package configuration from $x." fi . $x break fi done # short path - to not abort on missing downloads of postlinux.conf # packages that are not built anyway -ReneR if [ "$custmain" = "true" ]; then echo "Nothing is going to be done ayway - returning quickly." return fi populate_archdir popd # dump for debugging hook_dump > $builddir/debug.hooks.$pkg dump_env > $builddir/debug.buildenv.$pkg echo "Running main build function '$mainfunction'" cd $builddir eval "$mainfunction" touch $logstamp ) [ -f $logstamp ] || return 1 rm $logstamp return 0 }