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
11usage() {
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>
30package_exists() {
31  apt-cache pkgnames | grep -x "$1" > /dev/null 2>&1
32}
33
34while test "$1" != ""
35do
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
53done
54
55ubuntu_versions="12\.04|12\.10|13\.04"
56ubuntu_codenames="precise|quantal|raring"
57ubuntu_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.
61gcel_issue="^GCEL"
62
63if [ 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
74fi
75
76if [ "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
80fi
81
82# Packages needed for chromeos only
83chromeos_dev_list="libbluetooth-dev"
84
85# Packages needed for development
86dev_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).
103if file /sbin/init | grep -q 'ELF 64-bit'; then
104  dev_list="${dev_list} libc6-i386 lib32gcc1 lib32stdc++6"
105fi
106
107# Run-time libraries required by chromeos only
108chromeos_lib_list="libpulse0 libbz2-1.0"
109
110# Full list of required run-time libraries
111lib_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
120dbg_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
129arm_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
137armel_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
145arm_list="$arm_list $armel_list"
146
147# Some package names have changed over time
148if package_exists ttf-mscorefonts-installer; then
149  dev_list="${dev_list} ttf-mscorefonts-installer"
150else
151  dev_list="${dev_list} msttcorefonts"
152fi
153if package_exists libnspr4-dbg; then
154  dbg_list="${dbg_list} libnspr4-dbg libnss3-dbg"
155  lib_list="${lib_list} libnspr4 libnss3"
156else
157  dbg_list="${dbg_list} libnspr4-0d-dbg libnss3-1d-dbg"
158  lib_list="${lib_list} libnspr4-0d libnss3-1d"
159fi
160if package_exists libjpeg-dev; then
161  dev_list="${dev_list} libjpeg-dev"
162else
163  dev_list="${dev_list} libjpeg62-dev"
164fi
165if package_exists libudev1; then
166  dev_list="${dev_list} libudev1"
167else
168  dev_list="${dev_list} libudev0"
169fi
170if package_exists libbrlapi0.6; then
171  dev_list="${dev_list} libbrlapi0.6"
172else
173  dev_list="${dev_list} libbrlapi0.5"
174fi
175
176
177# Some packages are only needed if the distribution actually supports
178# installing them.
179if package_exists appmenu-gtk; then
180  lib_list="$lib_list appmenu-gtk"
181fi
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".
189yes_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
222if test "$do_inst_syms" = "" && test 0 -eq ${do_quick_check-0}
223then
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
233fi
234if test "$do_inst_syms" = "1"; then
235  echo "Including debugging symbols."
236else
237  echo "Skipping debugging symbols."
238  dbg_list=
239fi
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.
244if file /sbin/init | grep -q 'ELF 64-bit'; then
245  arm_list="$arm_list g++-multilib"
246fi
247
248if 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."
257else
258  echo "Skipping ARM cross toolchain."
259  arm_list=
260fi
261
262packages="$(echo "${dev_list} ${lib_list} ${dbg_list} ${arm_list}" | \
263  tr " " "\n" | sort -u | tr "\n" " ")"
264
265if [ 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
299fi
300
301sudo 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.
307echo "Finding missing packages..."
308# Intentionally leaving $packages unquoted so it's more readable.
309echo "Packages required: " $packages
310echo
311new_list_cmd="sudo apt-get install --reinstall $(echo $packages)"
312if 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."
315elif [ $? -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
328else
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
341fi
342
343# Install the Chrome OS default fonts. This must go after running
344# apt-get, since install-chromeos-fonts depends on curl.
345if 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
361else
362  echo "Skipping installation of Chrome OS fonts."
363fi
364
365# Install 32bit backwards compatibility support for 64bit systems
366if 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";
438EOF
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
576fi
577