Home | History | Annotate | Download | only in build
      1 #!/bin/bash -e
      2 
      3 # Copyright (c) 2011 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-]gold: enable or disable installation of gold linker"
     16   echo "--[no-]lib32: enable or disable installation of 32 bit libraries"
     17   echo "Script will prompt interactively if options not given."
     18   exit 1
     19 }
     20 
     21 while test "$1" != ""
     22 do
     23   case "$1" in
     24   --syms)     do_inst_syms=1;;
     25   --no-syms)  do_inst_syms=0;;
     26   --gold)     do_inst_gold=1;;
     27   --no-gold)  do_inst_gold=0;;
     28   --lib32)    do_inst_lib32=1;;
     29   --no-lib32) do_inst_lib32=0;;
     30   *) usage;;
     31   esac
     32   shift
     33 done
     34 
     35 install_gold() {
     36   # Gold is optional; it's a faster replacement for ld,
     37   # and makes life on 2GB machines much more pleasant.
     38 
     39   # First make sure root can access this directory, as that's tripped
     40   # up some folks.
     41   if sudo touch xyz.$$
     42   then
     43     sudo rm xyz.$$
     44   else
     45     echo root cannot write to the current directory, not installing gold
     46     return
     47   fi
     48 
     49   BINUTILS=binutils-2.21
     50   BINUTILS_URL=http://ftp.gnu.org/gnu/binutils/$BINUTILS.tar.bz2
     51   BINUTILS_SHA1=ef93235588eb443e4c4a77f229a8d131bccaecc6
     52 
     53   test -f $BINUTILS.tar.bz2 || wget $BINUTILS_URL
     54   if test "`sha1sum $BINUTILS.tar.bz2|cut -d' ' -f1`" != "$BINUTILS_SHA1"
     55   then
     56     echo Bad sha1sum for $BINUTILS.tar.bz2
     57     exit 1
     58   fi
     59 
     60   tar -xjvf $BINUTILS.tar.bz2
     61   cd $BINUTILS
     62   patch -p1 <<EOF
     63 diff -u -r1.103 -r1.103.2.1
     64 --- src/gold/object.h	2010/09/08 23:54:51	1.103
     65 +++ src/gold/object.h	2011/02/10 01:15:28	1.103.2.1
     66 @@ -1,6 +1,6 @@
     67  // object.h -- support for an object file for linking in gold  -*- C++ -*-
     68  
     69 -// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     70 +// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
     71  // Written by Ian Lance Taylor <iant@google.com>.
     72  
     73  // This file is part of gold.
     74 @@ -2165,15 +2165,6 @@
     75  		      Output_symtab_xindex*,
     76  		      Output_symtab_xindex*);
     77  
     78 -  // Clear the local symbol information.
     79 -  void
     80 -  clear_local_symbols()
     81 -  {
     82 -    this->local_values_.clear();
     83 -    this->local_got_offsets_.clear();
     84 -    this->local_plt_offsets_.clear();
     85 -  }
     86 -
     87    // Record a mapping from discarded section SHNDX to the corresponding
     88    // kept section.
     89    void
     90 diff -u -r1.60 -r1.60.2.1
     91 --- src/gold/reloc.cc	2010/10/14 22:10:22	1.60
     92 +++ src/gold/reloc.cc	2011/02/10 01:15:28	1.60.2.1
     93 @@ -1,6 +1,6 @@
     94  // reloc.cc -- relocate input files for gold.
     95  
     96 -// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     97 +// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
     98  // Written by Ian Lance Taylor <iant@google.com>.
     99  
    100  // This file is part of gold.
    101 @@ -685,9 +685,6 @@
    102    // Write out the local symbols.
    103    this->write_local_symbols(of, layout->sympool(), layout->dynpool(),
    104  			    layout->symtab_xindex(), layout->dynsym_xindex());
    105 -
    106 -  // We should no longer need the local symbol values.
    107 -  this->clear_local_symbols();
    108  }
    109  
    110  // Sort a Read_multiple vector by file offset.
    111 EOF
    112   ./configure --prefix=/usr/local/gold --enable-gold --enable-threads
    113   make maybe-all-binutils maybe-all-gold -j4
    114   if sudo make maybe-install-binutils maybe-install-gold
    115   then
    116     # Still need to figure out graceful way of pointing gyp to use
    117     # /usr/local/gold/bin/ld without requiring him to set environment
    118     # variables.  That will go into bootstrap-linux.sh when it's ready.
    119     echo "Installing gold as /usr/bin/ld."
    120     echo "To uninstall, do 'cd /usr/bin; sudo rm ld; sudo mv ld.orig ld'"
    121     test -f /usr/bin/ld && test ! -f /usr/bin/ld.orig && \
    122         sudo mv /usr/bin/ld /usr/bin/ld.orig
    123     sudo strip /usr/local/gold/bin/ld
    124     sudo ln -fs /usr/local/gold/bin/ld /usr/bin/ld.gold
    125     sudo ln -fs /usr/bin/ld.gold /usr/bin/ld
    126   else
    127     echo "make install failed, not installing gold"
    128   fi
    129 }
    130 
    131 if ! egrep -q \
    132     'Ubuntu (8\.04|8\.10|9\.04|9\.10|10\.04|10\.10|karmic|lucid|maverick)' \
    133     /etc/issue; then
    134   echo "Only Ubuntu 8.04 (hardy) through 10.10 (maverick) are currently" \
    135       "supported" >&2
    136   exit 1
    137 fi
    138 
    139 if ! uname -m | egrep -q "i686|x86_64"; then
    140   echo "Only x86 architectures are currently supported" >&2
    141   exit
    142 fi
    143 
    144 if [ "x$(id -u)" != x0 ]; then
    145   echo "Running as non-root user."
    146   echo "You might have to enter your password one or more times for 'sudo'."
    147   echo
    148 fi
    149 
    150 # Packages needed for chromeos only
    151 chromeos_dev_list="libpulse-dev"
    152 
    153 # Packages need for development
    154 dev_list="bison fakeroot flex g++ gperf libapache2-mod-php5 libasound2-dev
    155           libbz2-dev libcairo2-dev libdbus-glib-1-dev libgconf2-dev
    156           libgl1-mesa-dev libglu1-mesa-dev libglib2.0-dev libgnome-keyring-dev
    157           libgtk2.0-dev libjpeg62-dev libnspr4-dev libnss3-dev libpam0g-dev
    158           libsctp-dev libsqlite3-dev libxslt1-dev libxss-dev libxtst-dev
    159           mesa-common-dev msttcorefonts patch perl php5-cgi pkg-config python
    160           python-dev rpm subversion ttf-dejavu-core ttf-kochi-gothic
    161           ttf-kochi-mincho wdiff libcurl4-gnutls-dev
    162           $chromeos_dev_list"
    163 
    164 # Run-time libraries required by chromeos only
    165 chromeos_lib_list="libpulse0 libbz2-1.0 libcurl4-gnutls-dev"
    166 
    167 # Full list of required run-time libraries
    168 lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libdbus-glib-1-2 libexpat1
    169           libfontconfig1 libfreetype6 libglib2.0-0 libgnome-keyring0 libgtk2.0-0
    170           libnspr4-0d libnss3-1d libpam0g libpango1.0-0 libpcre3 libpixman-1-0
    171           libpng12-0 libstdc++6 libsqlite3-0 libx11-6 libxau6 libxcb1
    172           libxcomposite1 libxcursor1 libxdamage1 libxdmcp6 libxext6 libxfixes3
    173           libxi6 libxinerama1 libxrandr2 libxrender1 libxtst6 zlib1g
    174           $chromeos_lib_list"
    175 
    176 # Debugging symbols for all of the run-time libraries
    177 dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg
    178           libfontconfig1-dbg libglib2.0-0-dbg libgtk2.0-0-dbg libnspr4-0d-dbg
    179           libnss3-1d-dbg libpango1.0-0-dbg libpcre3-dbg libpixman-1-0-dbg
    180           libx11-6-dbg libxau6-dbg libxcb1-dbg libxcomposite1-dbg
    181           libxcursor1-dbg libxdamage1-dbg libxdmcp6-dbg libxext6-dbg
    182           libxfixes3-dbg libxi6-dbg libxinerama1-dbg libxrandr2-dbg
    183           libxrender1-dbg libxtst6-dbg zlib1g-dbg"
    184 
    185 # CUPS package changed its name from hardy to the next version. Include
    186 # proper package here depending on the system.
    187 if egrep -q 'Ubuntu (8\.04|8\.10)' /etc/issue; then
    188   dev_list="${dev_list} libcupsys2-dev"
    189 else
    190   dev_list="${dev_list} libcups2-dev"
    191 fi
    192 
    193 # apache2.2-bin package was introduced in karmic.
    194 if egrep -q 'Ubuntu (8\.04|8\.10|9\.04)' /etc/issue; then
    195   dev_list="${dev_list} apache2"
    196 else
    197   dev_list="${dev_list} apache2.2-bin"
    198 fi
    199 
    200 # Waits for the user to press 'Y' or 'N'. Either uppercase of lowercase is
    201 # accepted. Returns 0 for 'Y' and 1 for 'N'. If an optional parameter has
    202 # been provided to yes_no(), the function also accepts RETURN as a user input.
    203 # The parameter specifies the exit code that should be returned in that case.
    204 # The function will echo the user's selection followed by a newline character.
    205 # Users can abort the function by pressing CTRL-C. This will call "exit 1".
    206 yes_no() {
    207   local c
    208   while :; do
    209     c="$(trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT
    210          stty -echo iuclc -icanon 2>/dev/null
    211          dd count=1 bs=1 2>/dev/null | od -An -tx1)"
    212     case "$c" in
    213       " 0a") if [ -n "$1" ]; then
    214                [ $1 -eq 0 ] && echo "Y" || echo "N"
    215                return $1
    216              fi
    217              ;;
    218       " 79") echo "Y"
    219              return 0
    220              ;;
    221       " 6e") echo "N"
    222              return 1
    223              ;;
    224       "")    echo "Aborted" >&2
    225              exit 1
    226              ;;
    227       *)     # The user pressed an unrecognized key. As we are not echoing
    228              # any incorrect user input, alert the user by ringing the bell.
    229              (tput bel) 2>/dev/null
    230              ;;
    231     esac
    232   done
    233 }
    234 
    235 if test "$do_inst_syms" = ""
    236 then
    237   echo "This script installs all tools and libraries needed to build Chromium."
    238   echo ""
    239   echo "For most of the libraries, it can also install debugging symbols, which"
    240   echo "will allow you to debug code in the system libraries. Most developers"
    241   echo "won't need these symbols."
    242   echo -n "Do you want me to install them for you (y/N) "
    243   if yes_no 1; then
    244     do_inst_syms=1
    245   fi
    246 fi
    247 if test "$do_inst_syms" = "1"; then
    248   echo "Installing debugging symbols."
    249 else
    250   echo "Skipping installation of debugging symbols."
    251   dbg_list=
    252 fi
    253 
    254 sudo apt-get update
    255 
    256 # We initially run "apt-get" with the --reinstall option and parse its output.
    257 # This way, we can find all the packages that need to be newly installed
    258 # without accidentally promoting any packages from "auto" to "manual".
    259 # We then re-run "apt-get" with just the list of missing packages.
    260 echo "Finding missing packages..."
    261 packages="${dev_list} ${lib_list} ${dbg_list}"
    262 # Intentially leaving $packages unquoted so it's more readable.
    263 echo "Packages required: " $packages
    264 echo
    265 new_list_cmd="sudo apt-get install --reinstall $(echo $packages)"
    266 if new_list="$(yes n | LANG=C $new_list_cmd)"; then
    267   # We probably never hit this following line.
    268   echo "No missing packages, and the packages are up-to-date."
    269 elif [ $? -eq 1 ]; then
    270   # We expect apt-get to have exit status of 1.
    271   # This indicates that we canceled the install with "yes n|".
    272   new_list=$(echo "$new_list" |
    273     sed -e '1,/The following NEW packages will be installed:/d;s/^  //;t;d')
    274   new_list=$(echo "$new_list" | sed 's/ *$//')
    275   if [ -z "$new_list" ] ; then
    276     echo "No missing packages, and the packages are up-to-date."
    277   else
    278     echo "Installing missing packages: $new_list."
    279     sudo apt-get install ${new_list}
    280   fi
    281   echo
    282 else
    283   # An apt-get exit status of 100 indicates that a real error has occurred.
    284 
    285   # I am intentionally leaving out the '"'s around new_list_cmd,
    286   # as this makes it easier to cut and paste the output
    287   echo "The following command failed: " ${new_list_cmd}
    288   echo
    289   echo "It produces the following output:"
    290   yes n | $new_list_cmd || true
    291   echo
    292   echo "You will have to install the above packages yourself."
    293   echo
    294   exit 100
    295 fi
    296 
    297 # Some operating systems already ship gold (on recent Debian and
    298 # Ubuntu you can do "apt-get install binutils-gold" to get it), but
    299 # older releases didn't.  Additionally, gold 2.20 (included in Ubuntu
    300 # Lucid) makes binaries that just segfault, and 2.20.1 does not support
    301 # --map-whole-files.
    302 # So install from source if we don't have a good version.
    303 
    304 case `ld --version` in
    305 *gold*2.2[1-9].*) ;;
    306 * )
    307   if test "$do_inst_gold" = ""
    308   then
    309     echo "Gold is a new linker that links Chrome 5x faster than ld."
    310     echo "Don't use it if you need to link other apps (e.g. valgrind, wine)"
    311     echo -n "REPLACE SYSTEM LINKER ld with gold and back up ld? (y/N) "
    312     if yes_no 1; then
    313       do_inst_gold=1
    314     fi
    315   fi
    316   if test "$do_inst_gold" = "1"
    317   then
    318     # If the system provides a good version of gold, just install it.
    319     if apt-cache show binutils-gold | grep -Eq 'Version: 2.2[1-9].*'; then
    320       echo "Installing binutils-gold. Backing up ld as ld.single."
    321       sudo apt-get install binutils-gold
    322     else
    323       # FIXME: avoid installing as /usr/bin/ld
    324       echo "Building binutils. Backing up ld as ld.orig."
    325       install_gold || exit 99
    326     fi
    327   else
    328     echo "Not installing gold."
    329   fi
    330 esac
    331 
    332 # Install 32bit backwards compatibility support for 64bit systems
    333 if [ "$(uname -m)" = "x86_64" ]; then
    334   if test "$do_inst_lib32" = ""
    335   then
    336     echo "Installing 32bit libraries not already provided by the system"
    337     echo
    338     echo "This is only needed to build a 32-bit Chrome on your 64-bit system."
    339     echo
    340     echo "While we only need to install a relatively small number of library"
    341     echo "files, we temporarily need to download a lot of large *.deb packages"
    342     echo "that contain these files. We will create new *.deb packages that"
    343     echo "include just the 32bit libraries. These files will then be found on"
    344     echo "your system in places like /lib32, /usr/lib32, /usr/lib/debug/lib32,"
    345     echo "/usr/lib/debug/usr/lib32. If you ever need to uninstall these files,"
    346     echo "look for packages named *-ia32.deb."
    347     echo "Do you want me to download all packages needed to build new 32bit"
    348     echo -n "package files (Y/n) "
    349     if yes_no 0; then
    350       do_inst_lib32=1
    351     fi
    352   fi
    353   if test "$do_inst_lib32" != "1"
    354   then
    355     echo "Exiting without installing any 32bit libraries."
    356     exit 0
    357   fi
    358 
    359   # Standard 32bit compatibility libraries
    360   echo "First, installing the limited existing 32-bit support..."
    361   cmp_list="ia32-libs lib32asound2-dev lib32readline5-dev lib32stdc++6 lib32z1
    362             lib32z1-dev libc6-dev-i386 libc6-i386 g++-multilib"
    363   sudo apt-get install $cmp_list
    364 
    365   tmp=/tmp/install-32bit.$$
    366   trap 'rm -rf "${tmp}"' EXIT INT TERM QUIT
    367   mkdir -p "${tmp}/apt/lists/partial" "${tmp}/cache" "${tmp}/partial"
    368   touch "${tmp}/status"
    369 
    370   [ -r /etc/apt/apt.conf ] && cp /etc/apt/apt.conf "${tmp}/apt/"
    371   cat >>"${tmp}/apt/apt.conf" <<EOF
    372         Apt::Architecture "i386";
    373         Dir::Cache "${tmp}/cache";
    374         Dir::Cache::Archives "${tmp}/";
    375         Dir::State::Lists "${tmp}/apt/lists/";
    376         Dir::State::status "${tmp}/status";
    377 EOF
    378 
    379   # Download 32bit packages
    380   echo "Computing list of available 32bit packages..."
    381   sudo apt-get -c="${tmp}/apt/apt.conf" update
    382 
    383   echo "Downloading available 32bit packages..."
    384   sudo apt-get -c="${tmp}/apt/apt.conf" \
    385           --yes --download-only --force-yes --reinstall install \
    386           ${lib_list} ${dbg_list}
    387 
    388   # Open packages, remove everything that is not a library, move the
    389   # library to a lib32 directory and package everything as a *.deb file.
    390   echo "Repackaging and installing 32bit packages for use on 64bit systems..."
    391   for i in ${lib_list} ${dbg_list}; do
    392     orig="$(echo "${tmp}/${i}"_*_i386.deb)"
    393     compat="$(echo "${orig}" |
    394               sed -e 's,\(_[^_/]*_\)i386\(.deb\),-ia32\1amd64\2,')"
    395     rm -rf "${tmp}/staging"
    396     msg="$(fakeroot -u sh -exc '
    397       # Unpack 32bit Debian archive
    398       umask 022
    399       mkdir -p "'"${tmp}"'/staging/dpkg/DEBIAN"
    400       cd "'"${tmp}"'/staging"
    401       ar x "'${orig}'"
    402       tar zCfx dpkg data.tar.gz
    403       tar zCfx dpkg/DEBIAN control.tar.gz
    404 
    405       # Create a posix extended regular expression fragment that will
    406       # recognize the includes which have changed. Should be rare,
    407       # will almost always be empty.
    408       includes=`sed -n -e "s/^[0-9a-z]*  //g" \
    409                        -e "\,usr/include/,p" dpkg/DEBIAN/md5sums |
    410                   xargs -n 1 -I FILE /bin/sh -c \
    411                     "cmp -s dpkg/FILE /FILE || echo FILE" |
    412                   tr "\n" "|" |
    413                   sed -e "s,|$,,"`
    414 
    415       # If empty, set it to not match anything.
    416       test -z "$includes" && includes="^//"
    417 
    418       # Turn the conflicts into an extended RE for removal from the
    419       # Provides line.
    420       conflicts=`sed -n -e "/Conflicts/s/Conflicts: *//;T;s/, */|/g;p" \
    421                    dpkg/DEBIAN/control`
    422 
    423       # Rename package, change architecture, remove conflicts and dependencies
    424       sed -r -i                              \
    425           -e "/Package/s/$/-ia32/"           \
    426           -e "/Architecture/s/:.*$/: amd64/" \
    427           -e "/Depends/s/:.*/: ia32-libs/"   \
    428           -e "/Provides/s/($conflicts)(, *)?//g;T1;s/, *$//;:1"   \
    429           -e "/Recommends/d"                 \
    430           -e "/Conflicts/d"                  \
    431         dpkg/DEBIAN/control
    432 
    433       # Only keep files that live in "lib" directories or the includes
    434       # that have changed.
    435       sed -r -i                                                               \
    436           -e "/\/lib64\//d" -e "/\/.?bin\//d"                                 \
    437           -e "\,$includes,s,[ /]include/,&32/,g;s,include/32/,include32/,g"   \
    438           -e "s, lib/, lib32/,g"                                              \
    439           -e "s,/lib/,/lib32/,g"                                              \
    440           -e "t;d"                                                            \
    441           -e "\,^/usr/lib32/debug\(.*/lib32\),s,^/usr/lib32/debug,/usr/lib/debug," \
    442         dpkg/DEBIAN/md5sums
    443 
    444       # Re-run ldconfig after installation/removal
    445       { echo "#!/bin/sh"; echo "[ \"x\$1\" = xconfigure ]&&ldconfig||:"; } \
    446         >dpkg/DEBIAN/postinst
    447       { echo "#!/bin/sh"; echo "[ \"x\$1\" = xremove ]&&ldconfig||:"; } \
    448         >dpkg/DEBIAN/postrm
    449       chmod 755 dpkg/DEBIAN/postinst dpkg/DEBIAN/postrm
    450 
    451       # Remove any other control files
    452       find dpkg/DEBIAN -mindepth 1 "(" -name control -o -name md5sums -o \
    453                        -name postinst -o -name postrm ")" -o -print |
    454         xargs -r rm -rf
    455 
    456       # Remove any files/dirs that live outside of "lib" directories,
    457       # or are not in our list of changed includes.
    458       find dpkg -mindepth 1 -regextype posix-extended \
    459           "(" -name DEBIAN -o -name lib -o -regex "dpkg/($includes)" ")" \
    460           -prune -o -print | tac |
    461         xargs -r -n 1 sh -c "rm \$0 2>/dev/null || rmdir \$0 2>/dev/null || : "
    462       find dpkg -name lib64 -o -name bin -o -name "?bin" |
    463         tac | xargs -r rm -rf
    464 
    465       # Remove any symbolic links that were broken by the above steps.
    466       find -L dpkg -type l -print | tac | xargs -r rm -rf
    467 
    468       # Rename lib to lib32, but keep debug symbols in /usr/lib/debug/usr/lib32
    469       # That is where gdb looks for them.
    470       find dpkg -type d -o -path "*/lib/*" -print |
    471         xargs -r -n 1 sh -c "
    472           i=\$(echo \"\${0}\" |
    473                sed -e s,/lib/,/lib32/,g \
    474                -e s,/usr/lib32/debug\\\\\(.*/lib32\\\\\),/usr/lib/debug\\\\1,);
    475           mkdir -p \"\${i%/*}\";
    476           mv \"\${0}\" \"\${i}\""
    477 
    478       # Rename include to include32.
    479       [ -d "dpkg/usr/include" ] && mv "dpkg/usr/include" "dpkg/usr/include32"
    480 
    481       # Prune any empty directories
    482       find dpkg -type d | tac | xargs -r -n 1 rmdir 2>/dev/null || :
    483 
    484       # Create our own Debian package
    485       cd ..
    486       dpkg --build staging/dpkg .' 2>&1)"
    487     compat="$(eval echo $(echo "${compat}" |
    488                           sed -e 's,_[^_/]*_amd64.deb,_*_amd64.deb,'))"
    489     [ -r "${compat}" ] || {
    490       echo "${msg}" >&2
    491       echo "Failed to build new Debian archive!" >&2
    492       exit 1
    493     }
    494 
    495     msg="$(sudo dpkg -i "${compat}" 2>&1)" && {
    496         echo "Installed ${compat##*/}"
    497       } || {
    498         # echo "${msg}" >&2
    499         echo "Skipped ${compat##*/}"
    500       }
    501   done
    502 
    503   # Add symbolic links for developing 32bit code
    504   echo "Adding missing symbolic links, enabling 32bit code development..."
    505   for i in $(find /lib32 /usr/lib32 -maxdepth 1 -name \*.so.\* |
    506              sed -e 's/[.]so[.][0-9].*/.so/' |
    507              sort -u); do
    508     [ "x${i##*/}" = "xld-linux.so" ] && continue
    509     [ -r "$i" ] && continue
    510     j="$(ls "$i."* | sed -e 's/.*[.]so[.]\([^.]*\)$/\1/;t;d' |
    511          sort -n | tail -n 1)"
    512     [ -r "$i.$j" ] || continue
    513     sudo ln -s "${i##*/}.$j" "$i"
    514   done
    515 fi
    516