# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: lib/functions.in # Copyright (C) 2006 - 2020 The OpenSDE Project # Copyright (C) 2004 - 2006 The T2 SDE Project # Copyright (C) 1998 - 2003 Clifford Wolf # # 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 as published by # the Free Software Foundation; version 2 of the License. A copy of the # GNU General Public License can be found in the file COPYING. # --- SDE-COPYRIGHT-NOTE-END --- . ${SDEROOT:-.}/lib/core-functions.in # This function returns a "uniqe id" as output # get_unique() { local hostsum=`hostname 2>/dev/null | tr '()' _` if [ -z "$hostsum" -a -x /sbin/ip ]; then hostsum=`/sbin/ip link show eth0 | sed -e '/link\//!d' -e 's,.*link[^ ]* \([^ ]*\) .*,\1,'` 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" } # 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 } ;; 3.*|4.*|5.*) 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|crossbuild|crosscompile) [ $stagelevel -ne 1 ] || return 0 ;; rebuild) [ $stagelevel -ne 9 ] || return 0 ;; native) [ $stagelevel -lt 2 ] || return 0 ;; *) echo "atstage: '$x' stagename is not supported." >&2 break ;; esac done return 1 } # hasflag FLAG # hasflag() { local flag= for flag; do if ! echo "$desc_F" | grep -q -e "^\(.* \)\?$flag\( .*\)\?\$"; then return 1 fi done return 0 } # bz2filename [] # outputs filename converted to .bz2. stdin and $1 inputs are accepted # bz2filename() { local pattern='-e s,\.\(t\?\)\(gz\|xz\|Z\)$,.\1bz2,' pattern="-e s,\.gpg$,, $pattern" pattern="-e s,\.tar$,\.tar.bz2, $pattern" if [ -n "$1" ]; then echo "$1" | sed $pattern else sed $pattern fi } # pseudo_realpath # returns a clean absolute path without caring about symlinks or actual existance # pseudo_realpath() { local origpath="$1" local newpath= x= local path="$(echo "$1" | sed -e "s,^\([^/]\),$PWD/\1," )" while [ -n "$path" ]; do x="${path%%/*}" if [ "$x" = "$path" ]; then path= else path="${path#*/}" fi case "$x" in ""|.) ;; # skip ..) if [ -n "$newpath" ]; then newpath="${newpath%/*}" else echo "$origpath: invalid" >&2 return fi ;; *) newpath="$newpath/$x" esac done echo "$newpath" } # relative_path # returns a relative patch from source to target (for symlinking) # relative_path() { local orig_to="$1" orig_from="$2" local to=$(pseudo_realpath "$orig_to") local from=$(pseudo_realpath "$orig_from") local rel= x= y= [ -n "$to" -a -n "$from" ] || return # remove common part while [ -n "$from" ]; do x="${to%%/*}" y="${from%%/*}" [ "$x" = "$y" ] || break if [ "$x" = "$to" ]; then to= else to="${to#*/}" fi if [ "$y" = "$from" ]; then from= else from="${from#*/}" fi done if [ -z "$from" ]; then echo "$orig_to: invalid target for $orig_from" >&2 return fi case "$from" in */*) rel=$(echo "${from%/*}/" | sed -e 's,[^/]*/,../,g' -e 's,/$,,') ;; *) rel=. ;; esac echo "$rel${to:+/$to}" | sed -e 's,^\./,,' } # 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() { tr '\t' ' ' | tr -s ' ' | sed -e 's,^[ ]*,,; s,[ ]*$,,;' } # | column_clean_tab | # # see column_clean, but with tabs column_clean_tab() { tr ' ' '\t' | tr -s '\t' | sed -e 's,^[\t]*,,; s,[\t]*$,,;' } # 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:+/$prefix}" for x in bindir sbindir libdir datadir includedir \ docdir infodir mandir sysconfdir localstatedir do # bindir=/usr/bin eval "$x=`pkggetdir $x`" # --bindir=$root\$bindir confopt="$confopt --$x=$z\$$x" done export LIBSUFF=${libdir##*/lib} if [ "$SDECFG_CONFIGURE_OPTS" ] ; then confopt="$confopt $SDECFG_CONFIGURE_OPTS" fi if [ "$SDECFG_DEBUG" = 0 ] ; then confopt="$confopt --disable-debug" fi if ! atstage native || [ "$SDECFG_DISABLE_NLS" = 1 ] ; then confopt="${confopt//--enable-nls/} --disable-nls" fi confopt="$confopt \$extraconfopt" 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= local config_cache=$builddir/config.cache.$buildloop 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 [ -n "$configcache" ] || atstage cross; then if atstage cross; then create_config_cache >> $config_cache fi if [ -n "$configcache" ]; then cat <<-EOT # Some custom values EOT for x in $configcache; do echo "$x" done fi >> $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" } # 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 } # make symlinks relative # postflist_dirty_symlinks() { echo "Processing symlink corrections ..." while read fn; do local ffn="$root/$fn" if [ -L "$ffn" ]; then local dfn=$(readlink "$ffn") if [ "${dfn:0:1}" = '/' ]; then local dfn2="${dfn#$root}" if [ "$dfn2" != "$dfn" ]; then echo_warning "dirty symlink: $fn (fixing)" echo "$fn: dirty!" dfn="$dfn2" else echo_warning "absolute symlink: $fn (fixing)" echo "$fn: absolute, fixing." fi dfn2=$(relative_path "$dfn" "/$fn") if [ -z "$dfn2" ]; then echo_error "invalid symlink: $fn (can't fix)" echo "$fn: invalid!" continue fi ln -svnf "$dfn2" "$ffn" if [ ! -e "$ffn" ]; then echo_error "broken absolute symlink: $fn" echo "$fn: broken" fi elif [ ! -e "$ffn" ]; then echo_error "broken symlink: $fn" echo "$fn: broken" fi fi done < "$builddir/flist.txt" } # 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\..*|a|la|o|so|pc)$' $builddir/flist.txt | while read fn ; do local ffn="$root/$fn" ffn2="$root/usr/$fn" [ -e "$ffn" -o -L "$ffn" ] || continue case "$fn" in *.la) # move libtool archives to usr/lib and fixup the # dependency_libs and libdir entries accordingly local dependency_libs local deplibsnew eval `grep ^dependency_libs= $ffn` for deplib in $dependency_libs; do case "$deplib" in $libdir/*.la) deplib="`echo $deplib | sed "s,$libdir,/usr$libdir,g"`" ;; esac var_append deplibsnew ' ' "$deplib" done sed -e "s,^dependency_libs=.*,dependency_libs=' $deplibsnew'," \ -e "s,^libdir=.*,libdir='/usr$libdir'," \ "$ffn" > "$ffn2" rm "$ffn" unset dependency_libs unset deplibsnew ;; *.a|*.o|*.pc) mv -fv "$ffn" "$ffn2" ;; *.so) if [ -L "$ffn" ]; then local dfn="${ffn%/*}/$(readlink "$ffn")" dfn=$(relative_path "$dfn" "$ffn2") ln -svnf "$dfn" "$ffn2" rm -f "$ffn" fi ;; esac add_flist "$ffn2" if [ -L "$ffn2" -a ! -e "$ffn2" ]; then echo_error "broken symlink: usr/$fn (after static lib correction)" fi 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 } # Parse the *.desc file. Use the description from etc/desc_format and # save the tag data in $desc_*. # parse_desc() { tag="`grep '^\[' $base/etc/desc_format | sed 's, (\*),,; s,\] \[,|,g; s,\[,,; s,\],,;'`" for tag in $tag ; do tagdata="`egrep "^\[($tag)\]" $confdir/$1.desc | cut -f2- -d']' | sed 's,^ ,,'`" tag="`echo $tag | cut -f1 -d'|' | tr - _`" eval "desc_$tag=\"\$tagdata\"" 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 ... rock_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_mandir,$mandir,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() { if [ -e $base/architecture/share/config.cache ]; then cat $base/architecture/share/config.cache fi if [ $createarchcache -eq 1 ]; then cat <<-EOT # Architecture specific stuff # arch_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 if [ -n "$configcachefile" ]; then for x in $configcachefile; do if [ -e $x ]; then cat <<-EOT # cache file: $x EOT cat "$x" fi done fi } # Abort build before actual build starts # (is overwritten in Build-Pkg) # abort() { ${ECHO_E:-echo -e} "The package build aborted with the following config" \ "error:\n$*" > $root/var/adm/logs/$stagelevel-$xpkg.err echo_errorquote "`cat $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 } # Returns the value of a field of the .desc file of a package # pkgdesc() { local pattern= local descfile=$( ls -1d $base/package/*/$2/$2.desc 2> /dev/null ) case "$1" in ver) pattern="V" ;; *) pattern="$1" ;; esac if [ -s "$descfile" ]; then case "$1" in confdir) echo "${descfile%/*}" ;; *) sed -n "s,^\[$pattern\][ \t]\+\(.\+\)[ \t]*$,\1,p" "$descfile" ;; esac else echo_error "pkgdesc: Package $2 not found." fi } # 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). # # space delimited list, -f as first arguent for effective check # pkginstalled() { local effective=0 if [ $# -eq 0 ]; then return 1 # nothing elif [ "$1" = "-f" ]; then effective=1; shift elif atstage rebuild; then effective=1 fi if [ $effective -eq 0 ]; then local pattern= [ $# -gt 0 ] || return 1 # we expect at least one package if [ $# -eq 1 ]; then pattern="$1" else pattern="($*)" fi pattern="${pattern//+/\\+}" egrep -q "^X.* ${pattern// /|} " $base/config/$config/packages # we return what egrep returns else local pkg= # be happy if any package from the list is installed for pkg; do [ ! -f "$root/var/adm/packages/$pkg" ] || return 0 done return 1 fi } # pkgprefix [-rt] [] # returns the prefix or the location of a 'type' of an already build package # pkgprefix() { local type= pkg= local dotest= addroot= wantsroot= abortmsg= local prefix= value= while [ $# -gt 1 ]; do case "$1" in -t) dotest=1 ;; -r) addroot="$root" wantsroot="yes" ;; -*) abortmsg="invalid option $1" ;; *) break ;; esac shift done if [ $# -eq 2 ]; then type="$1"; shift fi pkg="$1" # test usual error causes if [ -n "$abortmsg" ]; then : elif [ -z "$pkg" ]; then abortmsg="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 abortmsg=`echo "$pkg record is old, please rebuild the package $pkg. As an alternative, you can insert a line into the file $root/var/adm/packages/$pkg containing the text below:\n\nPrefix: " | fmt -w 55 | sed 's,$,\\n,g'` fi if [ "$dotest" ]; then # test mode: abort or continue if [ "$abortmsg" ]; then abort "pkgprefix: $abortmsg" else return 0 fi elif [ "$abortmsg" ]; then echo "pkgprefix: $abortmsg" 1>&2 elif [ -z "$type" -o "$type" = "prefix" ]; then type="prefix" if [ "$wantsroot" = "yes" ]; then value="${prefix:+/$prefix}" else value="$prefix" fi 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 if [ -n "$value" -o "$type" = "prefix" ]; then echo "$addroot$value" else echo "PKGPREFIX_ERROR" fi } # 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) case $arch_machine in powerpc64|sparc64|x86_64|mips64) echo "$xprefix/lib64" ;; *) echo "$xprefix/lib" ;; esac ;; 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 } # # pkgchksum package-name # pkgchksum() { ( # expand to full patch if only a package name was specified [[ $1 == */* ]] || set $base/package/*/$1/ sh "$base/lib/sde-package/pkgchksum.sh" "$1" ) } # 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} \ $confdir/*.patch_$xpkg{.$arch} \ 2> /dev/null | tr '\n' ' '`" for x in $( get_reverted $targetchain ); do for y in pkg_$pkg.patch{,.$arch} xpkg_$xpkg.patch{,.$arch}; do if [ -f $base/target/$x/$y ]; then patchfiles="$patchfiles $base/target/$x/$y" fi done done } # 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 abolute path - e.g for patchfiles supplied # in the .desc file # we assume relative path patches are mirrorables //mnemoc if [ ! -e "$x" -a -n "${x##*/*}" ] ; then x="$base/download/mirror/${x:0:1}/$x" fi # Apply the patch if the file does exist or issue a warning if [ -f "$x" ] ; then echo "Apply patch $x ..." if [[ $x = *.bz2 ]] ; then patch_file=`mktemp` ; patch_del=1 bzcat $x > $patch_file else patch_file=$x ; patch_del=0 fi $filter $patch_file | patch $patchopt [ $patch_del = 1 ] && rm $patch_file eval "$hook" else echo_warning "Unable to apply patch: $x (File not found!)" fi 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_bz2() { echo "Extracting $xsrctar ($taropt) ... " tar -v $taropt $1 > untar.txt } autoextract_subdir_tar_bz2() { local taropt_orig="$taropt" mkdir -p "$pkg-$ver" taropt="-C $pkg-$ver $taropt" autoextract_tar_bz2 "$@" taropt="$taropt_orig" } autoextract_zip() { echo "Extracting $xsrctar ($zipopt) ... " unzip $zipopt $1 | sed 's,^.*/$,,' | cut -f4 -d" " | grep -v "^$" > untar.txt } autoextract_subdir_zip() { local zipopt_orig="$zipopt" mkdir -p "$pkg-$ver" zipopt="-d $pkg-$ver $zipopt" autoextract_zip "$@" zipopt="$zipopt_orig" } createprefix_function() { echo "Creating $root/$prefix/<..> if required ..." local dir= local foodir= for foodir in $foodirlist; do eval "dir=\"$root\$$foodir\"" if [ ! -e $dir ]; then mkdir -p $dir rmemptydir="$rmemptydir $dir" fi case $foodir in libdir) # create lib -> lib64 compat symlinks # TODO: MULTILIB if [[ "$dir" = *lib64 ]] && [ ! -e "$root/$prefix/lib" ]; then echo "Creating 'lib -> lib64' compatibility symlink" ln -sf lib64 "$root/$prefix/lib" fi ;; esac done } # splitting debug symbols of ELF binaries into separate files # split_debug_files() { echo "split debug symbols into separate files" if ! atstage native; then # we need to use the objdump and objcopy from our toolchain # when cross-compiling objdumpcmd=${arch_target}-objdump objcopycmd=${arch_target}-objcopy else # use the installed objdump and a temporary copy of objcopy # when building natively in a chroot sandbox local objdumpcmd=objdump local objcopy=$( type -ap objcopy ) local objcopytmp=${objcopy}.tmp local objcopycmd=$( basename $objcopytmp ) cp -a $objcopy $objcopytmp fi # iterate through a list files generated from the fl_wrapper.wlog for x in $( fl_wrparse -D -s -r "$xroot/" < $builddir/fl_wrapper.wlog | sort -u ); do local is_dynelf=false # files we do not process case $( basename $root/$x ) in $objcopycmd|*.a) continue ;; esac # process regular files only [ "$( stat --printf="%F" $root/$x )" = "regular file" ] || continue; # only process dynamically linked ELF binaries $objdumpcmd -s -j .dynsym $root/$x &>/dev/null && is_dynelf=true if $is_dynelf; then # skip if the file has a '.gnu_debuglink' section yet such as a # hardlink which had been processed before local has_gnu_debuglink=false $objdumpcmd -s -j .gnu_debuglink $root/$x &>/dev/null && has_gnu_debuglink=true if $has_gnu_debuglink; then continue; fi # create destination directory for the debug info file if needed local debugdir=$( dirname $root/$libdir/debug/$x ) [ -d $debugdir ] || mkdir -p $debugdir # split debug symbols into a separate file $objcopycmd --only-keep-debug $root/$x $root/$libdir/debug/$x chmod 644 $root/$libdir/debug/$x # preserve hardlinks if [ $( stat --printf="%h" $root/$x ) -gt 1 ]; then cp -fla $root/$x $root/$x.stripped else cp -a $root/$x $root/$x.stripped fi # create a stripped binary with gnu_debuglink section $objcopycmd --strip-debug $root/$x.stripped $objcopycmd --add-gnu-debuglink=$root/$libdir/debug/$x $root/$x.stripped # 'objcopy --strip-debug' will only remove debug symbols, whereas # 'strip -s' will remove debug symbols and the symbol table (.symtab) # 'objcopy --strip-unneeded' removes .symtab resulting in similarly # stripped binaries compared to 'strip -s' $objcopycmd --strip-unneeded $root/$x.stripped # preserve hardlinks cp -fla $root/$x.stripped $root/$x rm -f $root/$x.stripped fi done if atstage native; then # remove the temporary objcopy we used rm -f $objcopytmp fi } # 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 | tr ' ' '\t' | tr -s '\t' | cut -f2 | bz2filename ) 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" | tr ' ' '\t' | tr -s '\t' | cut -f2 | bz2filename ) xsrcpattern=$( echo "$desc_SRC" | tr ' ' '\t' | tr -s '\t' | tr '\t' '\n' ) xsourceballs=$( echo "$sourceballs" | grep -F "$xsrcpattern" ) else xsourceballs="$srctar" fi for xsrctar in $xsourceballs; do saved_patchfiles="$patchfiles" buildloop=1 var_append patchfiles " " \ "`ls $confdir/*.patch.${xsrctar/-[v0-9]*/} 2> /dev/null`" if [ -d "$confdir/$xsrctar" ]; then xsrcdir="$pkg-$ver-$xsrctar" cp -a "$confdir/$xsrctar" "$builddir/$xsrcdir" cd "$builddir/$xsrcdir" elif [ "$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" ;; *) custextract="autoextract_tar_bz2" ;; # *.tar.bz2|*.tbz2|*.tbz esac fi if [ -n "$custextract" ]; then # Do the actual extraction of the archive. eval "$custextract $archdir/$xsrctar" cat untar.txt | sed 's,^\./,,' | cut -f1 -d/ | sort -u > xsrcdir.txt fi # if [ "$srcdir" = auto ]; then xsrcdir=${xsrctar%.tar.bz2} xsrcdir=${xsrcdir%.tbz2} xsrcdir=${xsrcdir%.tbz} 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, .git, {arch} and .arch-ids directories ..." egrep '(^|/)(CVS|\.svn|\.git|\{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 # if [ $autopatch = 1 ]; then hook_eval prepatch apply_patchfiles hook_eval postpatch fi else cd $builddir fi if [ "$createprefix" = 1 ]; then createprefix_function fi if [ -z "$custmain" ]; then while [ ${buildloop:-1} -le ${buildloops:-1} ]; do [ "${buildloops:-1}" = "1" ] || echo "loop ${buildloop:-1} of ${buildloops:-1} for $xsrctar." hook_eval preconf # Maybe generate a configure first # if [ $autogen -eq 1 -o \ \( -f autogen.sh -a ! -f configure \) ] ; then if [ -f autogen.sh ] ; then echo "Running package autogen script." sed -i '/^\.\/configure /d' autogen.sh sh autogen.sh 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 based Makefile generation # if [ -f CMakeLists.txt -a $runcmake = 1 -a ! -f Makefile ]; then local cmakesrcdir='..' # check if we use a dedicated build directory if [ $cmakebuilddir = 1 ]; then mkdir -p build cd build else cmakesrcdir='.' fi eval echo "Running cmake $cmakeopt" cmake $( eval echo $cmakeopt $cmakesrcdir ) fi # automated package build # styles without make run first: if [ -f setup.py -a $runpysetup = 1 ] ; then hook_eval premake eval ${pyscript:-python} setup.py $pyconfopt \ build $pybuildopt \ install $pyinstopt hook_eval postmake elif [ -f waf -a $runwaf = 1 ] ; then wafconfopt="${wafconfopt:=configure --prefix=/$prefix}" wafbuildopt="${wafbuildopt:=build}" wafinstopt="${wafinstopt:=install --destdir=$root --force}" hook_eval premake eval ${wafscript:-./waf} $wafconfopt eval ${wafscript:-./waf} $wafbuildopt hook_eval inmake eval ${wafscript:-./waf} $wafinstopt hook_eval postmake elif [ -f Sconstruct -o -f SConstruct -a $runscons = 1 -a ! -f configure ] ; then hook_eval premake eval ${sconsscript:-scons} $sconsopt hook_eval inmake hook_eval postmake else # styles that include a make run if [ ! -f Makefile -a ! -f makefile -a \ -f Makefile.PL -a $runmkpl = 1 ]; then # always install into 'vendor' directory var_append plconfopt ' ' "INSTALLDIRS=vendor" perl Makefile.PL $plconfopt fi # if [ ! -f Makefile -a ! -f makefile -a \ -f Imakefile -a $runxmkmf = 1 ]; then xmkmf -a fi # # Build it # hook_eval premake if [ "$makeopt" ]; then eval echo "Running $MAKE $makeopt" eval "$MAKE $makeopt" fi hook_eval inmake if [ "$makeinstopt" ]; then eval echo "Running $MAKE $makeinstopt" eval "$MAKE $makeinstopt" fi hook_eval postmake fi buildloop=$( expr ${buildloop:-1} + 1 ) done else eval "$custmain" for x in preconf premake inmake postmake; do if eval "[ -n \"\$hookdirty_$x\" ]"; then echo "Hook $x is still marked as dirty ..." 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* README LICENSE COPYING; 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/; file="$( bz2filename $file )" 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 if [ "$1" = "-p" ]; then showpath=1; shift fi pattern="$1"; shift for package in ${*:-$pkg}; do while read x x file url x; do file="$( bz2filename $file )" 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 < <( grep -e "^\[D\].*$pattern" $base/package/*/$package/$package.desc ) 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 download for this package?" false fi } # search for the package confdir # detect_confdir() { confdir= if [ -z "$pkgdir" ] ; then for x in package/*/$pkg/$pkg.desc ; do if [ -f "$x" ] ; then if [ "$confdir" ] ; then echo_pkg_deny $stagelevel $pkg "in multiple trees" echo "Package in multiple trees: $pkg !" \ > $root/var/adm/logs/$stagelevel-$xpkg.err exit 1 fi x=${x#package/}; x=${x%%/*} confdir="$base/package/$x/$pkg" repository=$x fi done else if [ -f "$pkgdir/$pkg.desc" ] ; then confdir="$pkgdir" repository=extern fi fi } # initialize standard vars and hooks # init_vars_and_hooks() { makeopt='CC="$CC" CPP="$CPP" CXX="$CXX"' cmakeopt='-DCMAKE_INSTALL_PREFIX="/$prefix"' cmakeopt="$cmakeopt"' -DCMAKE_LIBRARY_PATH="$libdir"' cmakebuilddir=1 # some scons based builds are using 'prefix' others 'PREFIX' sconsopt='PREFIX=/$prefix prefix=/$prefix install' # python builds pybuildopt= pyinstopt='--prefix=/$prefix' if atstage toolchain; then makeopt="$makeopt"' prefix="$root${prefix:+/$prefix}"' else makeopt="$makeopt"' prefix="${prefix:+/$prefix}"' 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"' makeopt="$makeopt"' RANLIB="$RANLIB" NM="$NM"' fi if atstage native; then flistdel="$flistdel|`echo $base | sed s,^/,,`/.*" fi if atstage cross; then makeopt="$makeopt"' INSTALL_PREFIX="$root"' makeopt="$makeopt"' DESTDIR="$root" DEST_DIR="$root"' makeopt="$makeopt"' INSTROOT="$root" INSTALLROOT="$root"' # scons based build sconsopt='DESTDIR="$root" '"$sconsopt" fi makeinstopt="$makeopt"' install' custmain= buildloop=1 buildloops=1 [ "$SDECFG_DO_CHECK" = 1 ] && hook_add inmake 6 'run_check' hook_add postflist 3 'postflist_dirty_symlinks' # no static lib corrections at toolchain stage atstage toolchain || hook_add postflist 3 'postflist_static_lib' createarchcache=0 configprefix=; configcache= ; autogen=0 configscript="./configure" ; extraconfopt= srcdir=auto ; srctar=auto taropt="--use-compress-program=bzip2 -xf" mainfunction="build_this_package" runconf=1 ; runcmake=1 ; runxmkmf=1 ; runmkpl=1 ; runpysetup=1 ; runwaf=1 ; runscons=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" conffile="$2" ; [ "$conffile" ] || 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 parameter # passing. We do not want to pass the current positional parameters # to the loaded script. set -- eval "$desc_O" echo_status "Building $xpkg ($ver) within $super (using $conffile)." for x in $( get_expanded $base/target/%/pkg_$pkg.conf $targetchain ) \ $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 target directory." 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 }