Home | History | Annotate | Download | only in build
      1 #!/bin/bash -e
      2 
      3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 # Script to install everything needed to build chromium (well, ideally, anyway)
      8 # See http://code.google.com/p/chromium/wiki/LinuxBuildInstructions
      9 # and http://code.google.com/p/chromium/wiki/LinuxBuild64Bit
     10 
     11 usage() {
     12   echo "Usage: $0 [--options]"
     13   echo "Options:"
     14   echo "--[no-]syms: enable or disable installation of debugging symbols"
     15   echo "--[no-]lib32: enable or disable installation of 32 bit libraries"
     16   echo "--[no-]arm: enable or disable installation of arm cross toolchain"
     17   echo "--[no-]chromeos-fonts: enable or disable installation of Chrome OS"\
     18        "fonts"
     19   echo "--no-prompt: silently select standard options/defaults"
     20   echo "--quick-check: quickly try to determine if dependencies are installed"
     21   echo "               (this avoids interactive prompts and sudo commands,"
     22   echo "               so might not be 100% accurate)"
     23   echo "--unsupported: attempt installation even on unsupported systems"
     24   echo "Script will prompt interactively if options not given."
     25   exit 1
     26 }
     27 
     28 # Checks whether a particular package is available in the repos.
     29 # USAGE: $ package_exists <package name>
     30 package_exists() {
     31   apt-cache pkgnames | grep -x "$1" > /dev/null 2>&1
     32 }
     33 
     34 while test "$1" != ""
     35 do
     36   case "$1" in
     37   --syms)                   do_inst_syms=1;;
     38   --no-syms)                do_inst_syms=0;;
     39   --lib32)                  do_inst_lib32=1;;
     40   --no-lib32)               do_inst_lib32=0;;
     41   --arm)                    do_inst_arm=1;;
     42   --no-arm)                 do_inst_arm=0;;
     43   --chromeos-fonts)         do_inst_chromeos_fonts=1;;
     44   --no-chromeos-fonts)      do_inst_chromeos_fonts=0;;
     45   --no-prompt)              do_default=1
     46                             do_quietly="-qq --assume-yes"
     47     ;;
     48   --quick-check)            do_quick_check=1;;
     49   --unsupported)            do_unsupported=1;;
     50   *) usage;;
     51   esac
     52   shift
     53 done
     54 
     55 ubuntu_versions="12\.04|12\.10|13\.04"
     56 ubuntu_codenames="precise|quantal|raring"
     57 ubuntu_issue="Ubuntu ($ubuntu_versions|$ubuntu_codenames)"
     58 # GCEL is an Ubuntu-derived VM image used on Google Compute Engine; /etc/issue
     59 # doesn't contain a version number so just trust that the user knows what
     60 # they're doing.
     61 gcel_issue="^GCEL"
     62 
     63 if [ 0 -eq "${do_unsupported-0}" ] && [ 0 -eq "${do_quick_check-0}" ] ; then
     64   if ! egrep -q "($ubuntu_issue|$gcel_issue)" /etc/issue; then
     65     echo "ERROR: Only Ubuntu 12.04 (precise) through 13.04 (raring) are"\
     66         "currently supported" >&2
     67     exit 1
     68   fi
     69 
     70   if ! uname -m | egrep -q "i686|x86_64"; then
     71     echo "Only x86 architectures are currently supported" >&2
     72     exit
     73   fi
     74 fi
     75 
     76 if [ "x$(id -u)" != x0 ] && [ 0 -eq "${do_quick_check-0}" ]; then
     77   echo "Running as non-root user."
     78   echo "You might have to enter your password one or more times for 'sudo'."
     79   echo
     80 fi
     81 
     82 # Packages needed for chromeos only
     83 chromeos_dev_list="libbluetooth-dev"
     84 
     85 # Packages needed for development
     86 dev_list="apache2.2-bin bison curl elfutils fakeroot flex g++ git-core gperf
     87           language-pack-da language-pack-fr language-pack-he
     88           language-pack-zh-hant libapache2-mod-php5 libasound2-dev libbrlapi-dev
     89           libbz2-dev libcairo2-dev libcap-dev libcups2-dev libcurl4-gnutls-dev
     90           libdrm-dev libelf-dev libgconf2-dev libgl1-mesa-dev libglib2.0-dev
     91           libglu1-mesa-dev libgnome-keyring-dev libgtk2.0-dev libkrb5-dev
     92           libnspr4-dev libnss3-dev libpam0g-dev libpci-dev libpulse-dev
     93           libsctp-dev libspeechd-dev libsqlite3-dev libssl-dev libudev-dev
     94           libwww-perl libxslt1-dev libxss-dev libxt-dev libxtst-dev
     95           mesa-common-dev openbox patch perl php5-cgi pkg-config python
     96           python-cherrypy3 python-dev python-psutil rpm ruby subversion
     97           ttf-dejavu-core ttf-indic-fonts ttf-kochi-gothic ttf-kochi-mincho
     98           ttf-thai-tlwg wdiff xfonts-mathml $chromeos_dev_list"
     99 
    100 # 64-bit systems need a minimum set of 32-bit compat packages for the pre-built
    101 # NaCl binaries. These are always needed, regardless of whether or not we want
    102 # the full 32-bit "cross-compile" support (--lib32).
    103 if file /sbin/init | grep -q 'ELF 64-bit'; then
    104   dev_list="${dev_list} libc6-i386 lib32gcc1 lib32stdc++6"
    105 fi
    106 
    107 # Run-time libraries required by chromeos only
    108 chromeos_lib_list="libpulse0 libbz2-1.0"
    109 
    110 # Full list of required run-time libraries
    111 lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcap2 libcups2 libexpat1
    112           libfontconfig1 libfreetype6 libglib2.0-0 libgnome-keyring0
    113           libgtk2.0-0 libpam0g libpango1.0-0 libpci3 libpcre3 libpixman-1-0
    114           libpng12-0 libspeechd2 libstdc++6 libsqlite3-0 libx11-6
    115           libxau6 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxdmcp6
    116           libxext6 libxfixes3 libxi6 libxinerama1 libxrandr2 libxrender1
    117           libxtst6 zlib1g $chromeos_lib_list"
    118 
    119 # Debugging symbols for all of the run-time libraries
    120 dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg libfontconfig1-dbg
    121           libglib2.0-0-dbg libgtk2.0-0-dbg libpango1.0-0-dbg libpcre3-dbg
    122           libpixman-1-0-dbg libsqlite3-0-dbg libx11-6-dbg libxau6-dbg
    123           libxcb1-dbg libxcomposite1-dbg libxcursor1-dbg libxdamage1-dbg
    124           libxdmcp6-dbg libxext6-dbg libxfixes3-dbg libxi6-dbg libxinerama1-dbg
    125           libxrandr2-dbg libxrender1-dbg libxtst6-dbg zlib1g-dbg
    126           libstdc++6-4.6-dbg"
    127 
    128 # arm cross toolchain packages needed to build chrome on armhf
    129 arm_list="libc6-armhf-cross libc6-dev-armhf-cross libgcc1-armhf-cross
    130           libgomp1-armhf-cross linux-libc-dev-armhf-cross
    131           libgcc1-dbg-armhf-cross libgomp1-dbg-armhf-cross
    132           binutils-arm-linux-gnueabihf cpp-arm-linux-gnueabihf
    133           gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
    134           libmudflap0-dbg-armhf-cross"
    135 
    136 # Old armel cross toolchain packages
    137 armel_list="libc6-armel-cross libc6-dev-armel-cross libgcc1-armel-cross
    138             libgomp1-armel-cross linux-libc-dev-armel-cross
    139             libgcc1-dbg-armel-cross libgomp1-dbg-armel-cross
    140             binutils-arm-linux-gnueabi cpp-arm-linux-gnueabi
    141             gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
    142             libmudflap0-dbg-armel-cross"
    143 
    144 # TODO(sbc): remove armel once the armhf transition is complete
    145 arm_list="$arm_list $armel_list"
    146 
    147 # Some package names have changed over time
    148 if package_exists ttf-mscorefonts-installer; then
    149   dev_list="${dev_list} ttf-mscorefonts-installer"
    150 else
    151   dev_list="${dev_list} msttcorefonts"
    152 fi
    153 if package_exists libnspr4-dbg; then
    154   dbg_list="${dbg_list} libnspr4-dbg libnss3-dbg"
    155   lib_list="${lib_list} libnspr4 libnss3"
    156 else
    157   dbg_list="${dbg_list} libnspr4-0d-dbg libnss3-1d-dbg"
    158   lib_list="${lib_list} libnspr4-0d libnss3-1d"
    159 fi
    160 if package_exists libjpeg-dev; then
    161   dev_list="${dev_list} libjpeg-dev"
    162 else
    163   dev_list="${dev_list} libjpeg62-dev"
    164 fi
    165 if package_exists libudev1; then
    166   dev_list="${dev_list} libudev1"
    167 else
    168   dev_list="${dev_list} libudev0"
    169 fi
    170 if package_exists libbrlapi0.6; then
    171   dev_list="${dev_list} libbrlapi0.6"
    172 else
    173   dev_list="${dev_list} libbrlapi0.5"
    174 fi
    175 
    176 
    177 # Some packages are only needed if the distribution actually supports
    178 # installing them.
    179 if package_exists appmenu-gtk; then
    180   lib_list="$lib_list appmenu-gtk"
    181 fi
    182 
    183 # Waits for the user to press 'Y' or 'N'. Either uppercase of lowercase is
    184 # accepted. Returns 0 for 'Y' and 1 for 'N'. If an optional parameter has
    185 # been provided to yes_no(), the function also accepts RETURN as a user input.
    186 # The parameter specifies the exit code that should be returned in that case.
    187 # The function will echo the user's selection followed by a newline character.
    188 # Users can abort the function by pressing CTRL-C. This will call "exit 1".
    189 yes_no() {
    190   if [ 0 -ne "${do_default-0}" ] ; then
    191     [ $1 -eq 0 ] && echo "Y" || echo "N"
    192     return $1
    193   fi
    194   local c
    195   while :; do
    196     c="$(trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT
    197          stty -echo iuclc -icanon 2>/dev/null
    198          dd count=1 bs=1 2>/dev/null | od -An -tx1)"
    199     case "$c" in
    200       " 0a") if [ -n "$1" ]; then
    201                [ $1 -eq 0 ] && echo "Y" || echo "N"
    202                return $1
    203              fi
    204              ;;
    205       " 79") echo "Y"
    206              return 0
    207              ;;
    208       " 6e") echo "N"
    209              return 1
    210              ;;
    211       "")    echo "Aborted" >&2
    212              exit 1
    213              ;;
    214       *)     # The user pressed an unrecognized key. As we are not echoing
    215              # any incorrect user input, alert the user by ringing the bell.
    216              (tput bel) 2>/dev/null
    217              ;;
    218     esac
    219   done
    220 }
    221 
    222 if test "$do_inst_syms" = "" && test 0 -eq ${do_quick_check-0}
    223 then
    224   echo "This script installs all tools and libraries needed to build Chromium."
    225   echo ""
    226   echo "For most of the libraries, it can also install debugging symbols, which"
    227   echo "will allow you to debug code in the system libraries. Most developers"
    228   echo "won't need these symbols."
    229   echo -n "Do you want me to install them for you (y/N) "
    230   if yes_no 1; then
    231     do_inst_syms=1
    232   fi
    233 fi
    234 if test "$do_inst_syms" = "1"; then
    235   echo "Including debugging symbols."
    236 else
    237   echo "Skipping debugging symbols."
    238   dbg_list=
    239 fi
    240 
    241 # When cross building for arm on 64-bit systems the host binaries
    242 # that are part of v8 need to be compiled with -m32 which means
    243 # that basic multilib support is needed.
    244 if file /sbin/init | grep -q 'ELF 64-bit'; then
    245   arm_list="$arm_list g++-multilib"
    246 fi
    247 
    248 if test "$do_inst_arm" = "1" ; then
    249   . /etc/lsb-release
    250   if ! [ "${DISTRIB_CODENAME}" = "precise" -o \
    251       1 -eq "${do_unsupported-0}" ]; then
    252     echo "ERROR: Installing the ARM cross toolchain is only available on" \
    253          "Ubuntu precise." >&2
    254     exit 1
    255   fi
    256   echo "Including ARM cross toolchain."
    257 else
    258   echo "Skipping ARM cross toolchain."
    259   arm_list=
    260 fi
    261 
    262 packages="$(echo "${dev_list} ${lib_list} ${dbg_list} ${arm_list}" | \
    263   tr " " "\n" | sort -u | tr "\n" " ")"
    264 
    265 if [ 1 -eq "${do_quick_check-0}" ] ; then
    266   failed_check="$(dpkg-query -W -f '${PackageSpec}:${Status}\n' \
    267     ${packages} 2>&1 | grep -v "ok installed" || :)"
    268   if [ -n "${failed_check}" ]; then
    269     echo
    270     nomatch="$(echo "${failed_check}" | \
    271       sed -e "s/^No packages found matching \(.*\).$/\1/;t;d")"
    272     missing="$(echo "${failed_check}" | \
    273       sed -e "/^No packages found matching/d;s/^\(.*\):.*$/\1/")"
    274     if [ "$nomatch" ]; then
    275       # Distinguish between packages that actually aren't available to the
    276       # system (i.e. not in any repo) and packages that just aren't known to
    277       # dpkg (i.e. managed by apt).
    278       unknown=""
    279       for p in ${nomatch}; do
    280         if apt-cache show ${p} > /dev/null 2>&1; then
    281           missing="${p}\n${missing}"
    282         else
    283           unknown="${p}\n${unknown}"
    284         fi
    285       done
    286       if [ -n "${unknown}" ]; then
    287         echo "WARNING: The following packages are unknown to your system"
    288         echo "(maybe missing a repo or need to 'sudo apt-get update'):"
    289         echo -e "${unknown}" | sed -e "s/^/  /"
    290       fi
    291     fi
    292     if [ -n "${missing}" ]; then
    293       echo "WARNING: The following packages are not installed:"
    294       echo -e "${missing}" | sed -e "s/^/  /"
    295     fi
    296     exit 1
    297   fi
    298   exit 0
    299 fi
    300 
    301 sudo apt-get update
    302 
    303 # We initially run "apt-get" with the --reinstall option and parse its output.
    304 # This way, we can find all the packages that need to be newly installed
    305 # without accidentally promoting any packages from "auto" to "manual".
    306 # We then re-run "apt-get" with just the list of missing packages.
    307 echo "Finding missing packages..."
    308 # Intentionally leaving $packages unquoted so it's more readable.
    309 echo "Packages required: " $packages
    310 echo
    311 new_list_cmd="sudo apt-get install --reinstall $(echo $packages)"
    312 if new_list="$(yes n | LANGUAGE=en LANG=C $new_list_cmd)"; then
    313   # We probably never hit this following line.
    314   echo "No missing packages, and the packages are up-to-date."
    315 elif [ $? -eq 1 ]; then
    316   # We expect apt-get to have exit status of 1.
    317   # This indicates that we cancelled the install with "yes n|".
    318   new_list=$(echo "$new_list" |
    319     sed -e '1,/The following NEW packages will be installed:/d;s/^  //;t;d')
    320   new_list=$(echo "$new_list" | sed 's/ *$//')
    321   if [ -z "$new_list" ] ; then
    322     echo "No missing packages, and the packages are up-to-date."
    323   else
    324     echo "Installing missing packages: $new_list."
    325     sudo apt-get install ${do_quietly-} ${new_list}
    326   fi
    327   echo
    328 else
    329   # An apt-get exit status of 100 indicates that a real error has occurred.
    330 
    331   # I am intentionally leaving out the '"'s around new_list_cmd,
    332   # as this makes it easier to cut and paste the output
    333   echo "The following command failed: " ${new_list_cmd}
    334   echo
    335   echo "It produces the following output:"
    336   yes n | $new_list_cmd || true
    337   echo
    338   echo "You will have to install the above packages yourself."
    339   echo
    340   exit 100
    341 fi
    342 
    343 # Install the Chrome OS default fonts. This must go after running
    344 # apt-get, since install-chromeos-fonts depends on curl.
    345 if test "$do_inst_chromeos_fonts" != "0"; then
    346   echo
    347   echo "Installing Chrome OS fonts."
    348   dir=`echo $0 | sed -r -e 's/\/[^/]+$//'`
    349   if ! sudo $dir/linux/install-chromeos-fonts.py; then
    350     echo "ERROR: The installation of the Chrome OS default fonts failed."
    351     if [ `stat -f -c %T $dir` == "nfs" ]; then
    352       echo "The reason is that your repo is installed on a remote file system."
    353     else
    354       echo "This is expected if your repo is installed on a remote file system."
    355     fi
    356     echo "It is recommended to install your repo on a local file system."
    357     echo "You can skip the installation of the Chrome OS default founts with"
    358     echo "the command line option: --no-chromeos-fonts."
    359     exit 1
    360   fi
    361 else
    362   echo "Skipping installation of Chrome OS fonts."
    363 fi
    364 
    365 # Install 32bit backwards compatibility support for 64bit systems
    366 if file /sbin/init | grep -q 'ELF 64-bit'; then
    367   if test "$do_inst_lib32" != "1"
    368   then
    369     echo "NOTE: If you were expecting the option to install 32bit libs,"
    370     echo "please run with the --lib32 flag."
    371     echo
    372     echo "Installation complete."
    373     exit 0
    374   else
    375     # This conditional statement has been added to deprecate and eventually
    376     # remove support for 32bit libraries on 64bit systems. But for the time
    377     # being, we still have to support a few legacy systems (e.g. bots), where
    378     # this feature is needed.
    379     # We only even give the user the option to install these libraries, if
    380     # they explicitly requested doing so by setting the --lib32 command line
    381     # flag.
    382     # And even then, we interactively ask them one more time whether they are
    383     # absolutely sure.
    384     # In order for that to work, we must reset the ${do_inst_lib32} variable.
    385     # There are other ways to achieve the same goal. But resetting the
    386     # variable is the best way to document the intended behavior -- and to
    387     # allow us to gradually deprecate and then remove the obsolete code.
    388     if test "${do_default-0}" -ne 1; then
    389       do_inst_lib32=
    390     fi
    391   fi
    392 
    393   echo "WARNING"
    394   echo
    395   echo "We no longer recommend that you use this script to install"
    396   echo "32bit libraries on a 64bit system. Instead, consider using the"
    397   echo "install-chroot.sh script to help you set up a 32bit environment"
    398   echo "for building and testing 32bit versions of Chrome."
    399   echo
    400   echo "The code for installing 32bit libraries on a 64bit system is"
    401   echo "unmaintained and might not work with modern versions of Ubuntu"
    402   echo "or Debian."
    403   if test "$do_inst_lib32" != "" ; then
    404     echo
    405     echo -n "Are you sure you want to proceed (y/N) "
    406     if yes_no 1; then
    407       do_inst_lib32=1
    408     fi
    409   fi
    410   if test "$do_inst_lib32" != "1"
    411   then
    412     exit 0
    413   fi
    414 
    415   # Standard 32bit compatibility libraries
    416   echo "First, installing the limited existing 32-bit support..."
    417   cmp_list="ia32-libs lib32asound2-dev lib32stdc++6 lib32z1
    418             lib32z1-dev libc6-dev-i386 libc6-i386 g++-multilib"
    419   if [ -n "`apt-cache search lib32readline-gplv2-dev 2>/dev/null`" ]; then
    420     cmp_list="${cmp_list} lib32readline-gplv2-dev"
    421   else
    422     cmp_list="${cmp_list} lib32readline5-dev"
    423   fi
    424   sudo apt-get install ${do_quietly-} $cmp_list
    425 
    426   tmp=/tmp/install-32bit.$$
    427   trap 'rm -rf "${tmp}"' EXIT INT TERM QUIT
    428   mkdir -p "${tmp}/apt/lists/partial" "${tmp}/cache" "${tmp}/partial"
    429   touch "${tmp}/status"
    430 
    431   [ -r /etc/apt/apt.conf ] && cp /etc/apt/apt.conf "${tmp}/apt/"
    432   cat >>"${tmp}/apt/apt.conf" <<EOF
    433         Apt::Architecture "i386";
    434         Dir::Cache "${tmp}/cache";
    435         Dir::Cache::Archives "${tmp}/";
    436         Dir::State::Lists "${tmp}/apt/lists/";
    437         Dir::State::status "${tmp}/status";
    438 EOF
    439 
    440   # Download 32bit packages
    441   echo "Computing list of available 32bit packages..."
    442   sudo apt-get -c="${tmp}/apt/apt.conf" update
    443 
    444   echo "Downloading available 32bit packages..."
    445   sudo apt-get -c="${tmp}/apt/apt.conf" \
    446           --yes --download-only --force-yes --reinstall install \
    447           ${lib_list} ${dbg_list}
    448 
    449   # Open packages, remove everything that is not a library, move the
    450   # library to a lib32 directory and package everything as a *.deb file.
    451   echo "Repackaging and installing 32bit packages for use on 64bit systems..."
    452   for i in ${lib_list} ${dbg_list}; do
    453     orig="$(echo "${tmp}/${i}"_*_i386.deb)"
    454     compat="$(echo "${orig}" |
    455               sed -e 's,\(_[^_/]*_\)i386\(.deb\),-ia32\1amd64\2,')"
    456     rm -rf "${tmp}/staging"
    457     msg="$(fakeroot -u sh -exc '
    458       # Unpack 32bit Debian archive
    459       umask 022
    460       mkdir -p "'"${tmp}"'/staging/dpkg/DEBIAN"
    461       cd "'"${tmp}"'/staging"
    462       ar x "'${orig}'"
    463       tar Cfx dpkg data.tar*
    464       tar zCfx dpkg/DEBIAN control.tar.gz
    465 
    466       # Create a posix extended regular expression fragment that will
    467       # recognize the includes which have changed. Should be rare,
    468       # will almost always be empty.
    469       includes=`sed -n -e "s/^[0-9a-z]*  //g" \
    470                        -e "\,usr/include/,p" dpkg/DEBIAN/md5sums |
    471                   xargs -n 1 -I FILE /bin/sh -c \
    472                     "cmp -s dpkg/FILE /FILE || echo FILE" |
    473                   tr "\n" "|" |
    474                   sed -e "s,|$,,"`
    475 
    476       # If empty, set it to not match anything.
    477       test -z "$includes" && includes="^//"
    478 
    479       # Turn the conflicts into an extended RE for removal from the
    480       # Provides line.
    481       conflicts=`sed -n -e "/Conflicts/s/Conflicts: *//;T;s/, */|/g;p" \
    482                    dpkg/DEBIAN/control`
    483 
    484       # Rename package, change architecture, remove conflicts and dependencies
    485       sed -r -i                              \
    486           -e "/Package/s/$/-ia32/"           \
    487           -e "/Architecture/s/:.*$/: amd64/" \
    488           -e "/Depends/s/:.*/: ia32-libs/"   \
    489           -e "/Provides/s/($conflicts)(, *)?//g;T1;s/, *$//;:1"   \
    490           -e "/Recommends/d"                 \
    491           -e "/Conflicts/d"                  \
    492         dpkg/DEBIAN/control
    493 
    494       # Only keep files that live in "lib" directories or the includes
    495       # that have changed.
    496       sed -r -i                                                               \
    497           -e "/\/lib64\//d" -e "/\/.?bin\//d"                                 \
    498           -e "\,$includes,s,[ /]include/,&32/,g;s,include/32/,include32/,g"   \
    499           -e "s, lib/, lib32/,g"                                              \
    500           -e "s,/lib/,/lib32/,g"                                              \
    501           -e "t;d"                                                            \
    502           -e "\,^/usr/lib32/debug\(.*/lib32\),s,^/usr/lib32/debug,/usr/lib/debug," \
    503         dpkg/DEBIAN/md5sums
    504 
    505       # Re-run ldconfig after installation/removal
    506       { echo "#!/bin/sh"; echo "[ \"x\$1\" = xconfigure ]&&ldconfig||:"; } \
    507         >dpkg/DEBIAN/postinst
    508       { echo "#!/bin/sh"; echo "[ \"x\$1\" = xremove ]&&ldconfig||:"; } \
    509         >dpkg/DEBIAN/postrm
    510       chmod 755 dpkg/DEBIAN/postinst dpkg/DEBIAN/postrm
    511 
    512       # Remove any other control files
    513       find dpkg/DEBIAN -mindepth 1 "(" -name control -o -name md5sums -o \
    514                        -name postinst -o -name postrm ")" -o -print |
    515         xargs -r rm -rf
    516 
    517       # Remove any files/dirs that live outside of "lib" directories,
    518       # or are not in our list of changed includes.
    519       find dpkg -mindepth 1 -regextype posix-extended \
    520           "(" -name DEBIAN -o -name lib -o -regex "dpkg/($includes)" ")" \
    521           -prune -o -print | tac |
    522         xargs -r -n 1 sh -c "rm \$0 2>/dev/null || rmdir \$0 2>/dev/null || : "
    523       find dpkg -name lib64 -o -name bin -o -name "?bin" |
    524         tac | xargs -r rm -rf
    525 
    526       # Remove any symbolic links that were broken by the above steps.
    527       find -L dpkg -type l -print | tac | xargs -r rm -rf
    528 
    529       # Rename lib to lib32, but keep debug symbols in /usr/lib/debug/usr/lib32
    530       # That is where gdb looks for them.
    531       find dpkg -type d -o -path "*/lib/*" -print |
    532         xargs -r -n 1 sh -c "
    533           i=\$(echo \"\${0}\" |
    534                sed -e s,/lib/,/lib32/,g \
    535                -e s,/usr/lib32/debug\\\\\(.*/lib32\\\\\),/usr/lib/debug\\\\1,);
    536           mkdir -p \"\${i%/*}\";
    537           mv \"\${0}\" \"\${i}\""
    538 
    539       # Rename include to include32.
    540       [ -d "dpkg/usr/include" ] && mv "dpkg/usr/include" "dpkg/usr/include32"
    541 
    542       # Prune any empty directories
    543       find dpkg -type d | tac | xargs -r -n 1 rmdir 2>/dev/null || :
    544 
    545       # Create our own Debian package
    546       cd ..
    547       dpkg --build staging/dpkg .' 2>&1)"
    548     compat="$(eval echo $(echo "${compat}" |
    549                           sed -e 's,_[^_/]*_amd64.deb,_*_amd64.deb,'))"
    550     [ -r "${compat}" ] || {
    551       echo "${msg}" >&2
    552       echo "Failed to build new Debian archive!" >&2
    553       exit 1
    554     }
    555 
    556     msg="$(sudo dpkg -i "${compat}" 2>&1)" && {
    557         echo "Installed ${compat##*/}"
    558       } || {
    559         # echo "${msg}" >&2
    560         echo "Skipped ${compat##*/}"
    561       }
    562   done
    563 
    564   # Add symbolic links for developing 32bit code
    565   echo "Adding missing symbolic links, enabling 32bit code development..."
    566   for i in $(find /lib32 /usr/lib32 -maxdepth 1 -name \*.so.\* |
    567              sed -e 's/[.]so[.][0-9].*/.so/' |
    568              sort -u); do
    569     [ "x${i##*/}" = "xld-linux.so" ] && continue
    570     [ -r "$i" ] && continue
    571     j="$(ls "$i."* | sed -e 's/.*[.]so[.]\([^.]*\)$/\1/;t;d' |
    572          sort -n | tail -n 1)"
    573     [ -r "$i.$j" ] || continue
    574     sudo ln -s "${i##*/}.$j" "$i"
    575   done
    576 fi
    577