#!/bin/bash ##################################################################### # Program: /usr/share/slackdev/buildkit.sh # Purpose: Provide a sourceable environment for build scripts # via ScratchBox or natively # Author : Stuart Winter # Date...: 17-Jan-2004 ##################################################################### # Caveats: # [1] This script is full of cruft. It needs trimming. If you have # any comments or optimisations then please email me. # I'm very keen to improve speed where I can because you # really *can* feel the difference on my StrongARM RiscPCs! ##################################################################### # Source in the config file source /usr/share/slackdev/slackdev.config # Test if we're using distcc. This enables setting parallel jobs to # the number of local cores when a package is incompatible with distcc. function using_distcc() { [ -z "${DISTCC_HOSTS}" ] && return 1 || return 0 } # Determine whether a function exists: function fnexists() { local estat=1 type -t $1 >/dev/null && { [ $( type -t $1 ) = "function" ] && estat=0 ;} return $estat } # Call a function with any supplied arguments, if it exists: function fnexists_call() { local estat=0 if type -t $1 >/dev/null ; then if [ $( type -t $1 ) = "function" ]; then # Launch the supplied function name with any arguments, returning the # exit value from it: echo "Calling build plugin function: $@" $@ return $? else # Return 0 (non-error) if the function requested doesn't exist. return 0 fi fi } # Call a shell function if it exists. # This enables a build system to supply a bunch of plugin names, and have the build system # execute a custom function specific to that plugin. # e.g. within a shell script file plugin named "rk3399", we could have a function called "_prepatch" # i.e. "rk3399_prepatch" # # This would be called by the following function in this way: # BUILD_PLUGINS="rk3399 bcm2711 others" # fnexists_multicall "$BUILD_PLUGINS" prepatch function fnexists_multicall() { local plugin_list="$1" # the full list of plugins local call_function="$2" # e.g. "prepatch" local plugin # Iterate through the plugin list, calling the specified function. e.g. "rk3399_prepatch" for plugin in ${plugin_list}; do fnexists_call "${plugin}_${call_function}" # We won't return any error status here, as such functions can terminate the build process as they see fit. done } # Load a plugin's shell script configuration into the build system: # BUILD_PLUGINS="rk3399 rpi foo" # Usage: fnexists_loadplugins "${BUILD_PLUGINS}" $PORTCWD/buildplugins # The loaded plugin file would be named: $PORTCWD/buildplugins/rk3399/rk3399.conf function fnexists_loadplugins() { local plugin local plugin_conffile for plugin in $1 ; do plugin_conffile="${2}/${plugin}/${plugin}.conf" if [ -s "${plugin_conffile}" ]; then echo "Loading plugin script: ${plugin_conffile}" . ${plugin_conffile} fi done } # Kill off daemons and any other processes which tend to modify the contents # of the file system (creating files, modifying dirs etc). # The purpose of this is so that when building a package through altertrack, altertrack # it less likely to detect a file that was not created during the installation routine # of the software it's building. function altertrackprep() { /etc/rc.d/rc.cups stop > /dev/null 2>&1 /etc/rc.d/rc.sendmail stop > /dev/null 2>&1 killall crond > /dev/null 2>&1 } # From the current directory (presumed to be a linux source tree) # install the headers into /usr/local/arm where our cross compile # tool chain lives. # # 12-Jul-04: *** This is old rubbish now. Needs to be removed *** function kernheads() { rm -rf /usr/local/arm/include mkdir -p /usr/local/arm/include # make ARCH=$ARCH menuconfig # make ARCH=$ARCH symlinks include/linux/version.h # need to edit ARCH=arm and CROSSCOMPILE=arm-linux- cp -a include/linux /usr/local/arm/include cp -a include/asm-arm /usr/local/arm/include/asm } # Determine ARM architecture # "arm" = ARMv7 hard float # aarch64 = ARM 64 bit function slack_archtype() { if [ ! -z "$( readelf -h /usr/bin/readelf | grep -E 'Machine:.*AArch64' )" ]; then export ARCH=aarch64 export LIBDIRSUFFIX="64" # Autoconf settings for --host, --build, --target export SLK_ARCH_HOST="$ARCH-slackware-linux-gnu" export SLK_ARCH_BUILD="$ARCH-slackware-linux-gnu" # Used by gcc, binutils and llvm. export SLK_ARCH_TARGET="$ARCH-slackware-linux-gnu" else export ARCH=arm export LIBDIRSUFFIX="" # Autoconf settings for --host, --build, --target export SLK_ARCH_HOST="$ARCH-slackware-linux-gnueabihf" export SLK_ARCH_BUILD="$ARCH-slackware-linux-gnueabihf" # Used by gcc, binutils and llvm. export SLK_ARCH_TARGET="$ARCH-slackware-linux-gnueabihf" fi } # Utilize /dev/shm if more than 8GB of RAM is available. # This assumes /dev/shm is mounted without the 'noexec' option, which # is not the default configuration for Slackware, but it's adjusted for # Slackware ARM build hosts. # Utilizing /dev/shm speeds up builds significantly and reduces wear on storage. # This feature is supported on machines with ample RAM, such as the HoneyComb LX2. # Caution: Running this command will clear the root of /dev/shm/buildtmp, # preventing simultaneous builds of packages that utilise this function # to set the temporary build location. # This limitation arises due to the absence of cleanup routines in most, # if not all, Slackware ARM build scripts, necessitating pre-emptive # clearing of the entire area. # While storage capacity is typically ample, with tens or hundreds of GBs # available, RAM storage is more constrained. function shm_tmp() { local shmtmpbuilddir=/dev/shm/buildtmp if ! findmnt -o options /dev/shm | grep -q noexec; then rm -rf ${shmtmpbuilddir} # needs removing first due to no cleanup in build scripts [ $( df --output=avail /dev/shm | tail -n1 ) -gt $((8 * 1024 * 1024)) ] && { echo "Sufficient RAM available: using /dev/shm for temporary storage" export TMP=${shmtmpbuilddir} # this overrides the setting in /usr/share/slackdev/slackdev.config mkdir -vpm755 $TMP ;} fi } # Delete and re-create package temporary directories function mkpkgdirs() { echo -n "Preparing build area: cleansing; " rm -rf $TMPBUILD $PKG echo -n "creating; " mkdir -pm755 $TMPBUILD $PKG echo -n "cd $TMPBUILD " cd $TMPBUILD echo "... done" } # Apply Debian patch set. # Normally we wouldn't want to do this entirely but it can be # helpful when testing builds: function apply_full_debian_patches() { # grep -Ev "^#|^$" debian/patches/series | awk '{print $1}' | while read patchfile ; do find debian/patches -type f -printf "%f\n" | while read patchfile ; do if [ -s "debian/patches/$patchfile" ]; then # Most patches should not require more levels than this: success=0 for (( pl=0 ; pl<=5 ; pl++ )) ; do echo "Patch : $patchfile , trying patch level $pl" patch -N --fuzz=20 -t --dry-run -p$pl < debian/patches/$patchfile > /dev/null 2>&1 && success=1 && break done if [ $success = 1 ]; then echo "Patch: $patchfile will apply at level $pl" patch -N --fuzz=20 --verbose -p$pl < debian/patches/$patchfile else echo "Patch: $patchfile failed to apply" fi fi done } # GNU autotools stuff # If there's no ./configure but there's an autogen, build the confgiure; # otherwise force a reconfiguration and script rebuild. # This is the original code: #if [ ! -r configure ]; then # if [ -x ./autogen.sh ]; then # NOCONFIGURE=1 ./autogen.sh # else # autoreconf -vif # fi #fi function slack_autotoolsprep() { # [ ! -r configure ] && { [ -x ./autogen.sh ] && ./autogen.sh || autoreconf -vif ;} if [ ! -r configure ]; then if [ -x ./autogen.sh ]; then ./autogen.sh else autoreconf -vif fi fi } # Automatically unpack patches and determine patch level, and apply: function auto_apply_patch () { local patchfile=$1 # Original patch file name: local origpatchfile="${1##*/}" echo echo "***********************************************************" echo "** Working on Patch: $patchfile" echo "***********************************************************" echo # Decompress the patch if it's compressed with a known method: FTYPE=$( file $patchfile ) case "$FTYPE" in *xz*compressed*) xz -dc $patchfile > $TMPBUILD/$(basename $patchfile).unpacked patchfile=$TMPBUILD/$(basename $patchfile).unpacked ;; *bzip2*compressed*) bzcat -f $patchfile > $TMPBUILD/$(basename $patchfile).unpacked patchfile=$TMPBUILD/$(basename $patchfile).unpacked ;; *gzip*compressed*) zcat -f $patchfile > $TMPBUILD/$(basename $patchfile).unpacked patchfile=$TMPBUILD/$(basename $patchfile).unpacked ;; esac # By now the patch is decompressed or wasn't compressed originally. # # Most patches should not require more levels than this: success=0 for (( pl=0 ; pl<=5 ; pl++ )) ; do # Some patches don't work with --dry-run, so we can suffix the patch # level to the file name: e.g. 'foo-fix.patch.xz_p1' [[ ${origpatchfile: -2} =~ p[0-9] ]] && { pl="${origpatchfile: -1}" echo "Hard coded patch level found: ${pl}" success=1 break ;} echo "Patch : $patchfile , trying patch level $pl" patch -N --fuzz=20 -t --dry-run -lp$pl < $patchfile > /dev/null 2>&1 && success=1 && break done if [ $success = 1 ]; then echo "Patch: $patchfile will apply at level $pl" patch -N --fuzz=20 --verbose -lp$pl < $patchfile return 0 else echo "Patch: $patchfile failed to apply at levels 0-5" return 1 fi } # Reduce changelog size: # Syntax: changelogliposuction # This allows change log reduction when there are more than one app # bundled into a package. function changelogliposuction() { # If there's a ChangeLog, installing at least part of the recent history # is useful, but don't let it get totally out of control: if [ -r $1 ]; then echo "Liposuction on $PKG/usr/doc/$2-$3/$1" DOCSDIR=$(echo $PKG/usr/doc/$2-$3) cat << EOF > $DOCSDIR/$1 $( head -n1000 $1) [--snip--] EOF touch -r $1 $DOCSDIR/$1 fi } # Record toolchain & some other info (useful to see in build logs) function slackbuildinfo() { echo "------------------------------------------------------------" echo "Build starting on.....: $( date )" echo "Build host............: $( uname -a )" echo "Building for arch.....: $ARCH" echo "Building as UNIX user : $( whoami ) on $( tty )" echo "------------------------------------------------------------" echo "Toolchain & development tools information" echo "------------------------------------------------------------" echo "glibc .....: $( /lib${LIBDIRSUFFIX}/libc.so.6 | head -n1 | grep -o 'version [0-9.]*' )" echo "binutils ..: $( ld --version | head -n1 | rev | cut -d' ' -f1 | rev )" echo "libtool ...: $( libtool --version | head -n1 )" echo "GCC .......: $( gcc --version | head -n1 )" echo "GCC-C++ ...: $( g++ --version | head -n1 )" [ -x /usr/bin/clang ] && \ echo "llvm/clang : $( clang --version | head -n2 | xargs )" echo "GNU make ..: $( make --version | head -n1 )" echo "cmake .....: $( cmake --version | head -n1 )" echo "automake ..: $( automake --version | head -n1 )" echo "Perl ......: $( perl --version | grep -i "this is" )" [ -x /usr/bin/python2 ] && \ echo "Python2 ...: $( python2 --version 2>&1 | head -n1 )" [ -x /usr/bin/python3 ] && \ echo "Python3 ...: $( python3 --version 2>&1 | head -n1 )" [ -x /usr/bin/ruby ] && \ echo "ruby ......: $( ruby --version | head -n1 )" || { echo "not installed" ; } [ -x /usr/bin/meson ] && \ echo "meson .....: $( meson --version | head -n1 )" || { echo "not installed" ; } [ -x /usr/bin/rustc ] && \ echo "rust.......: $( rustc -vV | grep -E '^release|^host|^LLVM' | xargs )" || { echo "not installed" ; } echo "------------------------------------------------------------" } # ARM: Reinstall the default /targets/ARM -- clean our file system # This function is only meant to be run from within scratchbox - ie not # on a machine with an ARM processor. function sboxsysrestore() { # Regardless of whether we're inside sbox or native, /install has to go # otherwise if we rebuild the same package twice, slack-desc runs the risk of # being ignored. You don't build packages that use .build scripts anyway. rm -rf /install if [ -d /targets/ARM -a -s $HOME/armedslack-current/source/slackdev/cleanfs/cleanfs*bz2 ]; then ( echo "Reinstalling the default /targets/ARM" cd /targets/ chmod -R u+rwx ARM rm -rf ARM tar jxf $HOME/armedslack-current/source/slackdev/cleanfs/clean*bz2 # re-install the Slackware passwd & group. # I need to remember to keep this up todate with the 'etc' package. ( cd $HOME/armedslack-current/source/slackdev/installdata cp -fa passwd shadow group /etc ) # This is now in a Separate slackware devkit ('slackkit') but it's just # as easy to do this inside scratchbox: mkdir -p /usr/share ln -fs $HOME/armedslack-current/source/slackdev /usr/share/slackdev # Delete the Linux 2.6 headers because these cause things to break # This won't be necessary in future. Probably. Hopefully. #echo "deleting SB's 2.6 headers;" #rm -rf /usr/include/{linux,asm,asm-generic} # Having the Linux Kernel headers installed is also a must (and they replace those we just rm -rf'd) #echo ${PKGSTORE}/d/kernel-headers*.t?z #if [ -s ${PKGSTORE}/d/kernel-headers*.t?z ]; then # installpkg ${PKGSTORE}/d/kernel-headers*.t?z # else # read -p "Cannot find ${PKGSTORE}/d/kernel-headers*.t?z. There may be problems." #fi # Ensure target arch is ARMv3 # perl -pi -e 's?^-D__ARM_ARCH_4T__?-D__ARM_ARCH_3__?;' /lib/gcc-lib/arm-linux/3.3.2/specs ) else echo "Scratchbox not detected; not cleansing the OS" fi } # ARM: Find ldrh & strh instructions in all files # These instructions cause problems with the StrongARM RiscPC # and as such, we don't want our package to contain any binaries. # The fix is to compile for the armv3. # However, we occasionally find false positives: -- Jim Hawkins # Well, if you pipe the objdump -d into less and search for them using the same rexep as # grep -E you'll notice that they often come write at the very end of a section. # It just takes each 32-bit instruction and decodes it; it doesn't know if it's actually an # instruction or not. # Although this data is different from actual data. The executable is split into several # different bits. The most important are the ".text" and the ".data" sections. The .text is the # code and the .data is data. But because of the way the ARM works it can't encode certain # numeric values, so it stores them alongside the actuall instructions and uses a load # instruction to use the value. BBC BASIC assembler reports "Bad immediate constant" # when it can't encode them into an instruction, which you might have seen. # So that's why you end up with data in the code section of the executable. # # Question: Why don't I optimise using -march=armv3m as suggested here: # http://groups.google.com/groups?selm=199905201007.LAA01988%40sun52.NIS.cambridge&output=gplain # It's because when I tried it, gcc choked. If you find that stuff does compile # with it then please let me know, but I don't have time to wait for things to fail. # -- function shortwords() { echo "No longer checking shortwords - it's not neceessary" # local FOO # echo "Searching for half word instructions" # find . -type f \( -perm -100 -o -perm -010 -o -perm -001 \) | while read file ; do # if [ ! -z "$( file $file | grep -E '(ELF.*)' | cut -d: -f1 | xargs objdump -d | awk '{print $3}' | grep -E '(str|ldr)(\w\w)?h$' )" ]; then # echo "Shortwords in $file" # fi #done } # This thing doesn't work with shopt turned on so we call it as a separate script. function slackmp () { /usr/share/slackdev/slackmakepkg $@ } # Refresh to support latest architectures: function slackupdatelibtool() { find . -name config.guess -print0 | xargs -0i cp -favv /usr/share/libtool/build-aux/config.guess '{}' find . -name config.sub -print0 | xargs -0i cp -favv /usr/share/libtool/build-aux/config.sub '{}' } # gzip info and man pages and fix any resulting broken symlinks. # This code is taken from slacktrack # Syntax: gzpages [-i] # where -i deletes usr/info/dir if it exists. For everything other than # the texinfo package you'll want to do this. function slackgzpages() { local MPLIST ILIST if [ "${1}" = "-i" ]; then rm -vf usr/info/dir fi MPLIST="/usr/man /usr/local/man /usr/X11R?/man /opt/kde/man" echo -n "gzipping (and removing zero size) man pages in $PWD" for man_dir in ${MPLIST}; do if [ -d "./${man_dir}" ]; then # Remove any zero length man pages: ( find ./${man_dir} -type f -size 0 -exec rm "{}" \; ) >/dev/null 2>&1 # Decompress to maintain consistency: ( find ./${man_dir} -type f -name '*.bz2' -print0 | xargs -0 bzip2 -df ) >/dev/null 2>&1 ( find ./${man_dir} -type f -name '*.gz' -print0 | xargs -0 gunzip -f ) >/dev/null 2>&1 ( find ./${man_dir} -type f -name '*.xz' -print0 | xargs -0 xz -df ) >/dev/null 2>&1 # Compress: ( find ./${man_dir} -type f -print0 | xargs -0 gzip -9f ) >/dev/null 2>&1 ( find ./${man_dir} -type f -print0 | xargs -0 chmod 644 ) >/dev/null 2>&1 fi done echo " ... done" echo -n "Fixing any broken symlinks in man page directories in $PWD" for man_dir in ${MPLIST}; do if [ -d "./${man_dir}" ]; then ( cd ./${man_dir} # Enter each man page directory (man1,man2..) and whittle them down one by one for i in $( find . -type d -maxdepth 1 -printf "%P\n" | grep -v "^$" ); do cd ${i} && ( find . -type l -not -name '*.gz' -printf "rm -f %P ; ln -s %l.gz %p.gz\n" ) | /bin/bash && cd .. done ) fi done echo " ... done" ILIST="/usr/info /usr/local/info" echo -n "gzipping info pages in $PWD" for info_dir in ${ILIST}; do if [ -d "./${info_dir}" ]; then ( find ./${man_dir} -type f -name '*.gz' -print0 | xargs -0 gunzip -f ) >/dev/null 2>&1 ( find ./${info_dir} -type f -name '*.bz2' -print0 | xargs -0 bzip2 -df ) >/dev/null 2>&1 ( find ./${info_dir} -type f -print0 | xargs -0 gzip -9f ) >/dev/null 2>&1 ( find ./${info_dir} -type f -print0 | xargs -0 chmod 644 ) >/dev/null 2>&1 fi done echo " ... done" echo -n "Fixing any broken symlinks in info page directories" for info_dir in ${ILIST}; do if [ -d "./${info_dir}" ]; then ( cd ./${info_dir} && ( find . -type l -printf "rm -f %P ; ln -s %l.gz %p.gz\n" ) | /bin/bash ) fi done echo " ... done" } # Determine whether we're building for /patches within a Stable Release, or # whether we're in -current. # The script's calling pwd needs to contain /patches/source, otherwise it's # considered to be slackware-current: function slack_findpkgstore_is_stablerelease() { # Determine if we're building within /patches: #if pwd | grep -Fq "/patches/source" -a ; then # Check what the Slackware upstream src dir is set to. If it's not -current, it's a stable release. if [[ ! "$SLACKSOURCE" =~ (-current) ]] ; then export SLACKPATCHING=yes return 0 else export SLACKPATCHING=no return 1 fi } # Strip shared object with the longest line ever ;-) function slackstripso() { echo -n "Stripping unstripped ELF shared objects in $PWD" for i in /usr/lib /lib /usr/local/lib; do ( cd ./${i} && find . -name '*.so*' -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | grep -E '(ELF.*shared.*not stripped)' | awk -F: '{print $1}' | xargs strip -p --strip-unneeded ) > /dev/null 2>&1 done echo " ... done" } # Strip .a (archive) files: function slackstripar() { echo -n "Stripping .a (archive) files in $PWD" ( find . -name '*.a' -type f -print0 | xargs -0 strip -p -g ) > /dev/null 2>&1 echo " ... done" } # Strip binaries: function slackstripbin() { echo -n "Stripping unstripped ELF binaries in $PWD" for i in /bin /sbin /usr/sbin /usr/bin /usr/local/bin /usr/local/sbin /usr/X11R?/bin; do ( cd ./${i} && find . -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | grep -E '(ELF.*not stripped)' | awk -F: '{print $1}' | xargs strip -p --strip-unneeded ) >/dev/null 2>&1 done echo " ... done" } # Strip everything? This does the same as the above but instead it does it across # the entire package directory -- therefore it finds stuff in /opt and anywhere else # that files have been created. You may prefer to use this option if you already use -jkA # but it's worth noting that it will take longer (especially on a package with many files # in a deep directory structure) function slackstripall() { echo -n "Stripping all unstripped executable ELF files in $PWD" ( find . -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | grep -E '(ELF.*not stripped)' | awk -F: '{print $1}' | xargs strip -p --strip-unneeded ) >/dev/null 2>&1 # Strip the .a archives ( find . -name '*.a' -type f -print0 | xargs -0 strip -p -g ) > /dev/null 2>&1 echo " ... done" } # Remove rpaths: function slackstriprpaths() { local rpfile for rpfile in $(find . | xargs file | grep -e "executable" -e "shared object" | grep ELF | cut -f 1 -d : 2> /dev/null) ; do if [ ! "$(patchelf --print-rpath $rpfile 2> /dev/null)" = "" ]; then patchelf --remove-rpath $rpfile fi done } # chown root.bin stuff # As of Slackware 11, we don't do root:bin anymore. # This function is no longer required, but remains for the operability # with older source trees. function slackchown() { local dr echo -n "Setting root:root ownerships in $PWD" chmod 755 . # set pkg's root dir to the correct permission just incase # Handle coreutils 5.2.1's chown not perserving setuid bits: ( for dr in sbin bin usr/sbin usr/bin usr/local/sbin usr/local/bin usr/X11R?/bin ; do # ( cd ${dr} && chown root:root . && find . -type f -printf "chown root:bin '%p' && chmod %m '%p'\n" | bash ) ( cd ${dr} && chown root:root . && find . -type f -printf "chown root:root '%p' && chmod %m '%p'\n" | bash ) done ) > /dev/null 2>&1 echo " ... done" } # Fix up duff ownerships & permissions in source balls # This list has been compiled from various Slackware build scripts. function slackhousekeeping() { echo -n "Setting sane ownerships & permissions in $PWD" ( chown -R root:root . chmod -Rf a-s,a+rX,u+w,g-w,o-w . ) > /dev/null 2>&1 echo " ... done" } # chmod 644 doc files and doc dirs function slack644docs() { echo -n "Running chmod 644 over documents in usr/doc/ inside $PWD" ( find usr/doc/ -type f -print0 | xargs -0 chmod 644 ) >/dev/null 2>&1 ( chown -R root:root usr/doc/ ) >/dev/null 2>&1 ( find usr/doc -type d -print0 | xargs -0 chmod 755 ) >/dev/null 2>&1 echo " ... done" } # Find hard links and also embedded temporary build paths function slackhlinks() { echo "Scanning for hard links in $PWD" find . -type f -links +1 -printf "Hard link: %P\n" echo "Scanning for temporary embedded build paths in $PWD" grep -FHlr $TMPBUILD . | xargs strings -f | grep -F $TMPBUILD } # Check if we have any package dependencies. This is a lame way of doing it and # possibly proves nothing, but it saves me writing it in a few build scripts that # would otherwise fail when they haven't got package X installed. function slackcheckpkgdeps () { local error pack # Change comma separated input into spaces and consider them one by one for pack in $( echo ${1} | sed s/,/\ /g ); do slack_is_package_installed "${pack}" if [ $? -eq 0 ]; then echo "Dependency Slackware package '${pack}' not installed" error=y else echo "Dependency Slackware package '${pack}' is installed. OK!" fi done if [ ! -z "${error}" ]; then echo "Error: Package dependencies failed" # In some cases where we're bootstrapping, or merging in a huge number of 'Added' packages, # we hit package circular dependencies, and many packages fail to initially even attempt to be built. # Therefore, r2b offers the option --ignore-prebuild-deps to permit the first 10 or so build passes. if [ "$R2BIGNOREPREBUILDDEPS" = "Yes" ]; then echo "Ignoring dependency failure due to runtime configuration" else echo "Enforcing dependency failure" return 1 fi fi } # Function to retrieve the package name. # glibc-solibs-2.2-i386-1.t?z = glibc-solibs function slack_tgz2package_name () { echo $1 | rev | cut -d- -f4- | rev } # Exit if a package is installed. The purpose of this function is # to prevent packages from being compiled against others that they should # not be compiled against (to avoid an unwanted dependency). function slackfailpkgdeps () { local error pack for pack in $( echo ${1} | sed s/,/\ /g ); do slack_is_package_installed "${pack}" if [ $? -eq 0 ]; then echo "Slackware package '${pack}' not installed. OK!" else error=y fi done if [ ! -z "${error}" ]; then echo "Error: Found unwanted package(s) installed" # In some cases where we're bootstrapping, or merging in a huge number of 'Added' packages, # we hit package circular dependencies, and many packages fail to initially even attempt to be built. # Therefore, r2b offers the option --ignore-prebuild-deps to permit the first 10 or so build passes. if [ "$R2BIGNOREPREBUILDDEPS" = "Yes" ]; then echo "Not removing installed package due to runtime configuration" else echo "Unwanted Slackware package '${pack}' is installed" return 1 fi fi } # Function to determine whether a supplied package name is already installed # Returns 0 if not installed, 1 if installed. # This function allows us to specify 'autoconf' for example, without having # to worry about the version number installed (unless you specifically want to, # in which case specify the version number as well - e.g. autoconf-2.54) function slack_is_package_installed () { local PACKAGENAME="$1" local installed_package # We have to go through each package like this (rather than just do if -f foobar-* # because otherwise packges such as glibc, glibc-solibs and so on get wildcarded # and things get confused. for installed_package in $( find /var/log/packages/${PACKAGENAME}-* -type f -printf "%f\n" 2>/dev/null ) ; do installed_package="$( slack_tgz2package_name ${installed_package} )" if [ "${installed_package}" = "${PACKAGENAME}" ]; then return 1 # the package 'short' name is installed break fi done return 0 } # Defaults for everything. You WON'T always want to do this # but in the main it's probably ok. function slackslack() { local scansetuid=0 echo -n "Running chmod -R og-w & chown -R root:root . in $PWD " chmod 755 . # set pkg's root dir to the correct permission just incase # For certain packages such as the Kernels, we have no setuid binaries. # As such, we can use chown directly. scansetuid=$( find . -type f -perm /4000 -print -quit | wc -l 2>/dev/null ) if [ $scansetuid -eq 0 ]; then # No setuid binaries were found within the package, so we can # use fast mode: echo "[fast mode]" chown -R root:root . else # setuid binaries found, so we need to preserve the mode. # non-root ownerships are set within the SlackBuild explicitly. echo "[setuid preservation mode]" # Handle coreutils 5.2.1's chown not perserving setuid bits: ( find . -type f -printf "chown root:root '%p' && chmod %m '%p'\n" | bash ) fi ( chmod -R og-w . ) > /dev/null 2>&1 # Since we're chown root:root across the entire package, there's no need # to call 'slackchown'. Originally this was to set the cosmetic 'root:bin' # ownerships in Slackware v11 and earlier. # slackchown slack644docs if [ -d usr/lib${LIBDIRSUFFIX} ]; then echo 'Running chmod 755 for usr/lib${LIBDIRSUFFIX}/lib*.so*' chmod 755 usr/lib${LIBDIRSUFFIX}/lib*.so* fi if [ -d lib${LIBDIRSUFFIX} ]; then echo 'Running chmod 755 over lib${LIBDIRSUFFIX}/lib*.so*' chmod 755 lib${LIBDIRSUFFIX}/lib*.so* fi } # Remove the set uid bit on everything # You won't generally want to do this function slacknosuid() { echo -n "Running chmod -R -s" ( chmod -R -s . ) > /dev/null 2>&1 echo " ... done" } # Function to find Intel binaries. You never know when # cross compiling, even within scratchbox. function slackx86() { #if [ -d /scratchbox ]; then echo "Scanning for any x86 binaries in $PWD" exec 3<&0 find . -type f -print | while read file ; do ( file grep | grep "Intel.*86" ) > /dev/null 2>&1 if [ $? -eq 0 ]; then read -p "ERROR: Found Intel x86 file '${file}' ; press " <&3 fi done exec 3<&- # else # echo "Scratchbox not detected - not scanning for x86 binaries" #fi } # Function to install the new package. Note that this uses # removepkg first. This is DANGEROUS. Don't use this in anything # other than a simulated environment. # If you're really keen to install the new package, I suggest that you # replace the installpkg command with upgradepkg. function slackipkg() { if [ -z "${PKGSERIES}" ]; then echo "Syntax: slackipkg " elif [ -s $PKGSTORE/$PKGSERIES/$PKGNAM-${VERSION}-${PKGARCH}-${BUILD}.t?z ]; then removepkg $PKGNAM > /dev/null 2>&1 installpkg $PKGSTORE/$PKGSERIES/$PKGNAM-${VERSION}-${PKGARCH}-${BUILD}.t?z fi } # Install the slack-desc & doinst file from the slack source tree into # the $PKG's /install function slackdesc() { echo "Installing install/slack-desc" mkdir -pm755 install > /dev/null 2>&1 if [ -f $PORTCWD/slack-desc ]; then echo "Installing slack-desc from $PORTCWD" install -vpm644 $PORTCWD/slack-desc install/ else # Install the version from the official Slackware source tree: # We need to do it in this order to handle symlinked package sources: if [ -f $CWD/slack-desc.$PKGNAM ]; then echo "Installing slack-desc.$PKGNAM from $CWD" install -vpm644 $CWD/slack-desc.$PKGNAM install/slack-desc elif [ -f $CWD/slack-desc ]; then echo "Installing slack-desc from $CWD" install -vpm644 $CWD/slack-desc install fi fi if [ -s ${CWD}/doinst.sh.gz ]; then echo "Installing gzipped doinst.sh from $CWD" ( set -x ; zcat ${CWD}/doinst.sh.gz >> install/doinst.sh ) > /dev/null 2>&1 elif [ -s ${CWD}/doinst.sh ]; then echo "Installing doinst.sh from $CWD" ( set -x ; cat ${CWD}/doinst.sh >> install/doinst.sh ) # > /dev/null 2>&1 # install -vpm644 ${CWD}/doinst.sh install > /dev/null 2>&1 elif [ -s ${PORTCWD}/doinst.sh ]; then echo "Installing doinst.sh from $PORTCWD" # install -vpm644 ${PORTCWD}/doinst.sh install/ ( set -x ; cat ${PORTCWD}/doinst.sh >> install/doinst.sh ) # > /dev/null 2>&1 elif [ -s ${PORTCWD}/doinst.sh.gz ]; then echo "Installing gzipped doinst.sh from $PORTCWD" ( set -x ; zcat ${PORTCWD}/doinst.sh.gz >> install/doinst.sh ) # > /dev/null 2>&1 fi } # Function to ensure base system packages are installed. # This is intended for use when compiling inside Scratchbox. Otherwise # things build against Scratchbox's stuff, which isn't compiled for ARMv3. # # Obviously there are other glaringly obvious packages that should be # installed but I'm assuming that you have these installed already; # but I'm always open to suggestions, but don't suggest things like # procps, coreutils -- without those the system wouldn't be running ;-) # (but you may see that in some build scripts (tin's spring to mind), # I do ensure procps is installed but this is only required when # building inside Scratchbox) # # I strongly suggest installing all of the d/ package series. # function slackbasedeps() { # aaa_base contains the main directory structure. Without it things like openssh # need to be force fed /var/run because the configure script can't find it: slackcheckpkgdeps aaa_base || installpkg ${PKGSTORE}/a/aaa_base-*.t?z # having an ARM bash tends to upset scratchbox 0.9.8/qemu. #slackcheckpkgdeps bash || installpkg ${PKGSTORE}/a/bash-*.t?z # if [ ! -d /scratchbox ]; then # Bash is linked against libtermcap: # termcap removed in post Slackware 14.2 # slackcheckpkgdeps libtermcap || installpkg ${PKGSTORE}/l/libtermcap-*.t?z # slackcheckpkgdeps sed || installpkg ${PKGSTORE}/a/sed-*.t?z slackcheckpkgdeps gawk || installpkg ${PKGSTORE}/a/gawk-*.t?z # Needed to build documentation: slackcheckpkgdeps groff || installpkg ${PKGSTORE}/ap/groff-*.t?z slackcheckpkgdeps texinfo || installpkg ${PKGSTORE}/ap/texinfo-*.t?z # No system should be without Perl: slackcheckpkgdeps perl || installpkg ${PKGSTORE}/d/perl-*.t?z # Needed to build anything: slackcheckpkgdeps binutils || installpkg ${PKGSTORE}/d/binutils-*.t?z # Needed for creating makefiles & configure scripts: slackcheckpkgdeps autoconf || installpkg ${PKGSTORE}/d/autoconf-*.t?z slackcheckpkgdeps automake || installpkg ${PKGSTORE}/d/automake-*.t?z # Lots of things need pkg-config these days: slackcheckpkgdeps pkg-config || installpkg ${PKGSTORE}/d/pkg-config-*.t?z fi # Needed to build message files: slackcheckpkgdeps gettext-tools || installpkg ${PKGSTORE}/d/gettext-tools-*.t?z # And last but certainly not least, what would we do without glibc? :-) # This check is for Scratchbox, mainly. Obvously you're going to have glibc # installed on a native ARMedSlack box! # (note that it's the 'glibc' package rather than 'glibc-solibs') slackcheckpkgdeps glibc || installpkg ${PKGSTORE}/l/glibc-[0-9]*-*.t?z slackcheckpkgdeps glibc || exit 99 # We don't bail out of if we can't install the others because they're # not always necessary, plus if we haven't already built bash, libtermcap & friends # then we find ourselves in a catch 22 situation. # I did think about separating these out into different functions but I prefer it # this way. } # Some default error messages. Eventually the exit values will be used by an auto builder. # Maybe anyway - that's the idea. function failconfig() { echo "${PACKAGE}: failed configure $1" ; exit 100 ; } function failmake() { echo "${PACKAGE}: failed make $1" ; exit 101 ; } function failtest() { echo "${PACKAGE}: failed test $1" ; exit 102 ; } function failinstall() { echo "${PACKAGE}: failed install $1" ; exit 103 ; } function failextract() { echo "${PACKAGE}: failed to extract source $1" ; exit 105 ; } function failpatch() { echo "${PACKAGE}: failed to patch source $1" ; exit 106 ; } function faildocs() { echo "${PACKAGE}: failed to install docs $1" ; exit 107 ; } function failmisc() { echo "${PACKAGE}: failed for some non descript reason $1" ; exit 108 ; } ########################################################################################## # This is our architecture & our CFLAGS # Exports variable "ARCH" slack_archtype # Set the variables - $CWD and $PORTCWD # Handle building in /patches function slackset_var_cwds() { # The ARM source repository - normally source// # This function assumes that you're building within that directory. export PORTCWD=$PWD # Paths to skeleton port's source & real Slackware source tree: # Build directory for -current: export CWD=$SLACKSOURCE/$PKGSERIES/$PKGNAM # for /extra: pwd | grep -Fq "/extra/source/" && { # Overwrite the SLACKSOURCE that's defined in /usr/share/slackdev/slackdev.config # because for /extra on stable releases, patch packages aren't in /patches/packages: export SLACKSOURCE="$SLACKUPSTREAMROOTDIR/extra/source" export CWD=$SLACKSOURCE/$PKGNAM* export PKGSTORE="$PORTROOTDIR/extra/$PKGNAM/" ;} # for /patches - note that slackdev.config has SLACKSOURCE set (usually) to $HOME/slackware64-14.2/patches/source # which is why this works. #pwd | grep -Fq "/patches/source/" && export CWD=$SLACKSOURCE/$PKGNAM* # Unsure why I suffixed the * there, but it breaks with 'apr' and 'apr-util' # packages and I cannot think at this time why it'd be necessary. pwd | grep -Fq "/patches/source/" && export CWD=$SLACKSOURCE/$PKGNAM # for /pasture: #pwd | grep -Fq "/pasture/source/" && export CWD=$SLACKSOURCE/../pasture/source/$PKGNAM* pwd | grep -Fq "/pasture/source/" && export CWD=$SLACKSOURCE/../pasture/source/$PKGNAM # Only display the info if not running through r2b, otherwise this # triggers the pre-build checks list display: [ -z "$R2BRUNNING" ] && { echo "Source tree information" echo "-----------------------" echo "Master Slackware CWD: $CWD" echo "Port Overlay PORTCWD: $PORTCWD" ;} } # Delete *.la files: function slack_delete_lafiles() { echo "Deleting any *.la files" rm -fv $PKG/{,usr/}lib${LIBDIRSUFFIX}/*.la } # Automatically determine the package series based on the pwd function slack_var_pkgseries() { # If PKGSERIES is already set, do nothing. [ ! -z "$PKGSERIES" ] && return 0 # Working in -current tree, where the pwd would be ~/ac/source/a/bash export PKGSERIES="$( pwd | grep -Eo '/a/|/ap/|/d/|/e/|/f/|/k/|/kde/|/kdei$|/l/|/n/|/t/|/tcl/|/x/|/xap/|/xfce/|/y/' | sed 's?\/??g' )" # for /extra: pwd | grep -Fq "/extra/source/" && export PKGSERIES=extra # for /patches: pwd | grep -Fq "/patches/source/" && export PKGSERIES=patches if [ -z "$PKGSERIES" ]; then echo "ERROR: Could not determine PKGSERIES variable." exit 1 else # Output the package series, unless r2b is running: [ -z "$R2BRUNNING" ] && echo "Package series directory: $PKGSERIES" fi } # We need to give the minimum cpu as ARM3 otherwise our binaries have # ldrh instructions compiled into them, which fail in funky ways # on the RiscPC StrongARM110. You can read about this in various places on the net. # Chocky says that specifying StrongARM110 will most likely make the code # execute slower on the XScale systems. I only have RiscPCs at the moment so # I'm not too fussed. #export ARMCFLAGS="-march=armv4 -mtune=strongarm110" #export PORTCFLAGS="${ARMCFLAGS}" #export PORTCXXFLAGS="${ARMCFLAGS}" #export SLKCFLAGS="${ARMCFLAGS}" #export SLKCXXFLAGS="${ARMCFLAGS}" # Ensure target arch is ARMv3 # This doesn't work as SB's gcc seems not to honour gcc specs files. # Instead, you need an armv3 toolchain. Having an armv3 toolchain also means # you get a version of sbrshd that works on the SA110 RiscPC. # perl -pi -e 's?^-D__ARM_ARCH_4T__?-D__ARM_ARCH_3__?;' /lib/gcc-lib/arm-linux/3.3.2/specs # This is where our armedslack source tree lives # and where we'll be doing our /tmp stuff. # We cannot compile in /tmp because it's NFS exported to the ARM # box, and whilst it may *appear* to build, it will fail in # weird ways. # However, if you're stuck between a rock and a hard place, you could # always NFS export /tmp on the Scratchbox (x86 Slackware) host and NFS mount # it as /tmp on the ARMedslack machine. I've done this before and it was fine, # and infact, since gcc has /tmp hard coded a gazillion times in its files, # I guess you may want to use it when building gcc inside scratchbox. #export BBASE=/home/build export BBASE=/root # The stash of ARM binary .t?z packages. # I replace the versions in the repository manually incase # the new build breaks. export PKGSTORE=${BBASE}/tgzstash # The package building logs: export PBLOGS=${BBASE}/buildlogs mkdir -p ${PBLOGS} >/dev/null 2>&1 # Within the scratchbox, our ARM root is /targets/ARM # This setting is for altertrack. if [ -f /targets/links/scratchbox.config ]; then export PORTSYSROOT="--rootdir=/targets/ARM/" else export PORTSYSROOT="--rootdir=/" # we're working natively fi # Build up the Slackware binary repository structure. # This is where our .t?z packages will reside once built. # This can eventually be scrapped when I've setup my scripts to track all dir # additions/removals in slackware-current. #for i in ../extra/source ../pasture ../testing ../extra/glibc-extra-packages \ # This is useless - the dirs will have already existed, and if not - create them manually! #for i in a ap d e f k kde kdei l n t tcl x xap xfce y ; do # mkdir -pm755 ${PKGSTORE}/${i} >/dev/null 2>&1 #done # Export all functions: FUNCTIONS="auto_apply_patch kernheads altertrackprep apply_full_debian_patches changelogliposuction sboxsysrestore slackbuildinfo shortwords slackgzpages slackstripso slackstripar slackstripbin slackstripall slackstriprpaths slackchown slack644docs slackhlinks slackhousekeeping slackfailpkgdeps slackcheckpkgdeps slack_tgz2package_name slack_is_package_installed slack_autotoolsprep slackslack slacknosuid slackx86 slackipkg slackmp slackdesc slack_findpkgstore_is_stablerelease slackbasedeps slackset_var_cwds slack_var_pkgseries slack_delete_lafiles slackupdatelibtool shm_tmp using_distcc mkpkgdirs failconfig failmake failinstall failpatch failextract fnexists_call fnexists fnexists_multicall fnexists_loadplugins" for i in $FUNCTIONS; do export -f $i done