X-Git-Url: https://git.distorted.org.uk/~mdw/distorted-chroot/blobdiff_plain/fd0f20e15d713daf7f0cb2cfe429edbcc50574fb..3e5b03e2c0f0a3ddf3a56136f475e99d44432f18:/bin/update-cross-tools?ds=sidebyside diff --git a/bin/update-cross-tools b/bin/update-cross-tools new file mode 100755 index 0000000..a738af0 --- /dev/null +++ b/bin/update-cross-tools @@ -0,0 +1,277 @@ +#! /bin/sh -e +### +### Fetch native versions of tools for insertion into foreign chroots +### +### (c) 2018 Mark Wooding +### + +###----- Licensing notice --------------------------------------------------- +### +### This file is part of the distorted.org.uk chroot maintenance tools. +### +### distorted-chroot 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; either version 2 of the +### License, or (at your option) any later version. +### +### distorted-chroot is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +### General Public License for more details. +### +### You should have received a copy of the GNU General Public License +### along with distorted-chroot. If not, write to the Free Software +### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +### USA. + +. state/config.sh # @@@config@@@ + +###-------------------------------------------------------------------------- +### Utilities. + +chase_link () { + p=$1 d= + ## Copy an absolute path P from the donor tree `$root/' into the + ## cross-tools tree `$crossnew/'. If resolving P involves traversing a + ## symbolic link, then ensure that the pieces of filesystem it directs us + ## to are also copied. + + ## Work through the remaining components of the path. + while :; do + + ## Analyse the first remaining component of the path P. + case $p in + + ## It's empty. We're done. + "") break ;; + + ## A redundant `/' or `./'. Skip it. + "/"*) p=${p#/} ;; + "./"*) p=${p#./} ;; + + ## A `../'. Strip off the trailing component of D. + "../"*) + p=${p#../} + case $d in */*) d=${d%/*} ;; *) d= ;; esac + ;; + + ## Something else. Transfer the component name to D. + *) + case $p in */*) f=${p%%/*} p=${p#*/} ;; *) f=$p p="" ;; esac + d=${d:+$d/}$f + ;; + esac + + ## If D doesn't refer to a file in the cross-tools tree, then maybe it + ## refers to something in the donor tree. Find out what, and copy it + ## into the cross-tools tree. + if ! [ -e "$crossnew$d" ] && ! [ -L "$crossnew$d" ]; then + if [ -d "$root/$d" ] && ! [ -L "$root/$d" ]; then + mkdir "$crossnew$d" + else + echo >&2 "$0: copy /$d to satisfy symlinks" + rsync -aHR $root/./$d $crossnew + fi + fi + + ## If D refers to a symbolic link, then append the link target to P, so + ## that we can make sure we copy the target. + if [ -L "$crossnew$d" ]; then + t=$(readlink "$crossnew$d") + case $t in /*) t=${t#/} d= ;; esac + case $d in */*) d=${d%/*} ;; *) d= ;; esac + p=$t${p:+/$p} + fi + done +} + +###-------------------------------------------------------------------------- +### Main program. + +## Parse the command line. +badp=nil +case $# in 2) ;; *) badp=t ;; esac +case $badp in t) echo >&2 "usage: $0 DIST MYARCH"; exit 2 ;; esac +d=$1 myarch=$2 + +## Keep track of our original stdout. +exec 3>&1 + +## Figure out derived architecture names. +mymulti=$(dpkg-architecture -a$myarch -qDEB_HOST_MULTIARCH) + +## First, set `cross_archs' as a list of GNUish names for our supported +## foreign architectures. +cross_archs="arm-linux-gnueabi arm-linux-gnueabihf aarch64-linux-gnu" + +## Make a list of extra packages we'll need to install to obtain our tools. +cross_pkgs=" + apt bash ccache coreutils dash eatmydata fakeroot findutils + gnupg gpgv gzip m4 make mawk qemu-user-static sed tar xz-utils" +for a in $cross_archs; do + for i in gcc g++ binutils; do + cross_pkgs="$cross_pkgs $i-$a" + done +done +cross_pkgs=$(echo $cross_pkgs) + +## Make an enormous shopping list of paths. +## +## The `wanted' list consists of two kinds of items: an absolute path names a +## prefix (not necessarily a directory name) to be attached to the following +## relative names, up to the end of the list or the next absolute path. +wanted=" + /usr/bin/ apt apt-cache apt-config apt-get apt-key apt-mark + /usr/lib/apt/ methods/ solvers/ + + /bin/ cat chgrp chown cp date dd df dir echo false ln ls mkdir + mknod mktemp mv pwd readlink rm rmdir sleep stty sync touch + true uname vdir + /usr/bin/ [ arch b2sum base32 base64 basename chcon cksum comm + csplit cut dircolors dirname du env expand expr factor fmt + fold groups head hostid id install join link logname md5sum + mkfifo nice nl nohup nproc numfmt od paste pathchk pinky pr + printenv printf ptx realpath runcon seq sha1sum sha224sum + sha256sum sha384sum sha512sum shred shuf sort split stat + stdbuf sum tac tail tee test timeout tr truncate tsort tty + unexpand uniq unlink users wc who whoami yes + /usr/lib/$mymulti/ coreutils/ + + /lib/$mymulti/ libnss_*.so.* + + /usr/bin/ gpg gpgv gpgconf kbxutil watchgnupg + + /usr/bin/ qemu-*-static + + /bin/ bash dash gzip sed tar + /usr/bin/ ccache find m4 make mawk xargs xz + /usr/lib/$mymulti/ libeatmydata.so* libfakeroot/ + + /etc/ld.so.conf.d/ $mymulti.conf fakeroot*.conf" + +for a in $cross_archs; do + wanted="$wanted + + /usr/bin/$a- addr2line ar as c++filt dwp elfedit gprof ld ld.* + nm objcopy objdump ranlib readelf size strings strip + + /usr/bin/$a- cpp gcc g++ gcov gcov-dump gcov-tool gprof + gcc-ar gcc-nm gcc-ranlib + /usr/lib/gcc-cross/$a/ ..." +done +wanted=$(echo $wanted) + +## Figure out how to recognize dynamic executables. +case $myarch in + i386) elfsig=7f454c46010101??0000000000000000????0300 ;; + amd64) elfsig=7f454c46020101??0000000000000000????3e00 ;; + *) echo >&2 "$0: unsupported local arch \`$myarch'"; exit 2 ;; +esac + +## Open a session to the donor chroot. +echo >&2 "$0: create $d snapshot" +sess=$(schroot -bc$LVPREFIX$d-$myarch 3>&-) + +## Make sure the donor tree is up-to-date, and install the extra packages we +## need. +schroot -uroot -rc$sess -- eatmydata sh -ec " + apt-get update + apt-get -y upgrade + apt-get -y install $cross_pkgs" + +## Establish some pathnames. Prepare a place for our cross-tools tree. +crossdir=$LOCAL/cross/$d-$myarch/ +crossold=${crossdir%/}.old/ crossnew=${crossdir%/}.new/ +root=/schroot/$sess/fs +rm -rf $crossnew; mkdir -p $crossnew + +## Work through the shopping list, copying the things it names into the +## cross-tools tree. +dir=/ +for i in $wanted; do + case $i in + /*) + dir=$i + ;; + *) + case $i in ...) f=$dir ;; *) f=$dir$i ;; esac + echo >&2 "$0: copy $f" + rsync -aHR $root/.$f $crossnew + ;; + esac +done + +## Chase links in the new tree, copying extra stuff that we'll need. +find $crossnew -xtype l -print | while read i; do + chase_link ${i#$crossnew} +done + +## Search the new tree for ELF binaries, and build a list of them in +## `QUEUE.in'. +find $crossnew -type f -print | while read i; do + sig=$(head -c20 "$i" | bincode -e -m0 -flowerc hex) + case $sig in $elfsig) echo "$i" ;; esac +done >$root/private/QUEUE.in + +while [ -s $root/private/QUEUE.in ]; do + ## Work through the ELF binaries in `QUEUE.in', determining which shared + ## libraries they'll need. Write the list of dependencies to `QUEUE.out' + schroot -uroot -rc$sess -- eatmydata sh -ec ' + prog=$1 + while read i; do + echo >&2 "$prog: scanning binary $i" + ldd "$i" | while read a b c d; do + case $a:$b:$c:$d in + not:a:dynamic:executable) ;; + statically:linked::) ;; + /*) echo "$a" ;; + *:=\>:/*) echo "$c" ;; + linux-*) ;; + *) echo >&2 "$i: unable to find $a"; exit 2 ;; + esac + done + done /private/QUEUE.out' - "$0" + + ## Work through the shared libraries in `QUEUE.out', copying them to the + ## cross-tools tree if they're not there already. Add the new ones to a + ## new `QUEUE.in' file to scan them in turn. + while read i; do + if [ -e "$crossnew$i" ] || [ -L "$crossnew$i" ] + then continue; fi + if [ -d "$root$i" ]; then continue; fi + echo >&2 "$0: copy $i" + rsync -aHR $root/.$i $crossnew >&3 + chase_link $i >&3 + sig=$(head -c20 $crossnew$i | bincode -e -m0 -flowerc hex) + case $sig in $elfsig) echo "$i" ;; esac + done <$root/private/QUEUE.out >$root/private/QUEUE.in +done + +## Set up the cross-compiler. This is rather hairy. +echo >&2 "$0: establish TOOLCHAIN" +for a in $cross_archs; do + tooldir=$crossnew/TOOLCHAIN/$a + mkdir -p $tooldir + for i in $crossnew/usr/bin/$a-*; do + t=${i#$crossnew/usr/bin/} + mv $i $tooldir/$t + ln -s $t $tooldir/${t#$a-} + done +done +mkdir $crossnew/TOOLCHAIN/lib +ln -s ../../usr/lib/gcc-cross $crossnew/TOOLCHAIN/lib/ + +## Set up the emulator. +echo >&2 "$0: establish QEMU" +mkdir $crossnew/QEMU +mv $crossnew/usr/bin/qemu-*-static $crossnew/QEMU/ + +## We're done. Remove the snapshot, and replace the old cross-tools tree +## with our new one. +echo >&2 "$0: remove snapshot" +schroot -ec$sess 3>&- +if [ -d $crossdir ]; then mv $crossdir $crossold; fi +mv $crossnew $crossdir; rm -rf $crossold +echo >&2 "$0: committed $crossdir" + +###----- That's all, folkd --------------------------------------------------