#! /bin/sh -e badp=nil myarch=$(dpkg-architecture -qDEB_HOST_ARCH) while getopts "a:" opt; do case $opt in a) myarch=$OPTARG ;; *) badp=t ;; esac done shift $(( $OPTIND - 1 )) case $# in 0) badp=t ;; esac case $badp in t) cat >&2 <&2 "$0: bad arch name \`$arg'"; exit 1 ;; esac done mymulti=$(dpkg-architecture -a$myarch -qDEB_HOST_MULTIARCH) cross_archs="arm-linux-gnueabi arm-linux-gnueabihf aarch64-linux-gnu" 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) 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) case $myarch in i386) elfsig=7f454c46010101??0000000000000000????0300 ;; amd64) elfsig=7f454c46020101??0000000000000000????3e00 ;; *) echo >&2 "$0: unsupported local arch \`$myarch'"; exit 1 ;; esac chase_link () { p=$1 d= while :; do case $p in "") break ;; "/"*) p=${p#/} ;; "./"*) p=${p#./} ;; "../"*) p=${p#../} case $d in */*) d=${d%/*} ;; *) d= ;; esac ;; *) case $p in */*) f=${p%%/*} p=${p#*/} ;; *) f=$p p="" ;; esac d=${d:+$d/}$f ;; esac 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 [ -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 } exec 3>&1 for d in "$@"; do echo >&2 "$0: create $d snapshot" sess=$(schroot -bc$d-$myarch 3>&-) schroot -uroot -rc$sess -- eatmydata sh -ec " apt-get update apt-get -y upgrade apt-get -y install $cross_pkgs" crossdir=/usr/local.schroot/cross/$d-$myarch/ crossold=${crossdir%/}.old/ crossnew=${crossdir%/}.new/ rm -rf $crossnew; mkdir -p $crossnew root=/schroot/$sess/fs; 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 find $crossnew -xtype l -print | while read i; do chase_link ${i#$crossnew} done 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 counter=0 cp $root/private/QUEUE.in /tmp/mdw/queue.in.$counter while [ -s $root/private/QUEUE.in ]; do 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" cp $root/private/QUEUE.out /tmp/mdw/queue.out.$counter counter=$(( $counter + 1 )) 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 cp $root/private/QUEUE.in /tmp/mdw/queue.in.$counter done 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/ echo >&2 "$0: establish QEMU" mkdir $crossnew/QEMU mv $crossnew/usr/bin/qemu-*-static $crossnew/QEMU/ 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" done