diff options
Diffstat (limited to 'build/install-chroot.sh')
-rwxr-xr-x | build/install-chroot.sh | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/build/install-chroot.sh b/build/install-chroot.sh new file mode 100755 index 0000000..ad0dafa --- /dev/null +++ b/build/install-chroot.sh @@ -0,0 +1,221 @@ +#!/bin/bash -e + +# Copyright (c) 2010 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script installs Debian-derived distributions in a chroot environment. +# It can for example be used to have an accurate 32bit build and test +# environment when otherwise working on a 64bit machine. +# N. B. it is unlikely that this script will ever work on anything other than a +# Debian-derived system. + +# Check that we are running as a regular user +[ "$(id -nu)" = root ] && { + echo "Run this script as a regular user and provide your \"sudo\"" \ + "password if requested" >&2 + exit 1 +} +mkdir -p "$HOME/chroot/" + +# Error handler +trap 'exit 1' INT TERM QUIT +trap 'sudo apt-get clean; tput bel; echo; echo Failed' EXIT + +# Install any missing applications that this script relies on. If these packages +# are already installed, don't force another "apt-get install". That would +# prevent them from being auto-removed, if they ever become eligible for that. +# And as this script only needs the packages once, there is no good reason to +# introduce a hard dependency on things such as dchroot and debootstrap. +dep= +for i in dchroot debootstrap; do + [ -d /usr/share/doc/"$i" ] || dep="$dep $i" +done +[ -n "$dep" ] && sudo apt-get -y install $dep +sudo apt-get -y install schroot + +# Create directory for chroot +sudo mkdir -p /var/lib/chroot + +# Find chroot environments that can be installed with debootstrap +targets="$(cd /usr/share/debootstrap/scripts + ls | grep '^[a-z]*$')" + +# Ask user to pick one of the available targets +echo "The following targets are available to be installed in a chroot:" +j=1; for i in $targets; do + printf '%4d: %s\n' "$j" "$i" + j=$(($j+1)) +done +while :; do + printf "Which target would you like to install: " + read n + [ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev/null && break +done +j=1; for i in $targets; do + [ "$j" -eq "$n" ] && { distname="$i"; break; } + j=$(($j+1)) +done + +# On x86-64, ask whether the user wants to install x86-32 or x86-64 +archflag= +arch= +if [ "$(uname -m)" = x86_64 ]; then + while :; do + echo "You are running a 64bit kernel. This allows you to install either a" + printf "32bit or a 64bit chroot environment. %s" \ + "Which one do you want (32, 64) " + read arch + [ "${arch}" == 32 -o "${arch}" == 64 ] && break + done + [ "${arch}" == 32 ] && archflag="--arch i386" || archflag="--arch amd64" + arch="${arch}bit" +fi +target="${distname}${arch}" + +# Don't overwrite an existing installation +[ -d /var/lib/chroot/"${target}" ] && { + echo "This chroot already exists on your machine." >&2 + echo "Delete /var/lib/chroot/${target} if you want to start over." >&2 + exit 1 +} +sudo mkdir -p /var/lib/chroot/"${target}" + +# Remove stale entry from /etc/schroot/schroot.conf. Entries start +# with the target name in square brackets, followed by an arbitrary +# number of lines. The entry stops when either the end of file has +# been reached, or when the beginning of a new target is encountered. +# This means, we cannot easily match for a range of lines in +# "sed". Instead, we actually have to iterate over each line and check +# whether it is the beginning of a new entry. +sudo sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p' \ + /etc/schroot/schroot.conf + +# Download base system. This takes some time +grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null && + mirror="http://archive.ubuntu.com/ubuntu" || + mirror="http://ftp.us.debian.org/debian" + sudo debootstrap ${archflag} "${distname}" /var/lib/chroot/"${target}" \ + "$mirror" + +# Add new entry to /etc/schroot/schroot.conf +grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null && + brand="Ubuntu" || brand="Debian" +sudo sh -c 'cat >>/etc/schroot/schroot.conf' <<EOF +[${target%bit}] +description=${brand} ${distname} ${arch} +type=directory +directory=/var/lib/chroot/${target} +priority=3 +users=root +groups=admin +root-groups=admin +personality=linux$([ "${arch}" != 64bit ] && echo 32) +script-config=script-${target} + +EOF + +# Set up a special directory that changes contents depending on the target +# that is executing. +sed '/^FSTAB=/s,/mount-defaults",/mount-'"${target}"'",' \ + /etc/schroot/script-defaults | + sudo sh -c 'cat >/etc/schroot/script-'"${target}" +sudo cp /etc/schroot/mount-defaults /etc/schroot/mount-"${target}" +echo "$HOME/chroot/.${target} $HOME/chroot none rw,bind 0 0" | + sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" +mkdir -p "$HOME/chroot/.${target}" + +# Install a helper script to launch commands in the chroot +sudo sh -c 'cat >/usr/local/bin/'"${target%bit}" <<EOF +#!/bin/bash +if [ \$# -eq 0 ]; then + exec schroot -c ${target%bit} -p +else + p="\$1"; shift + exec schroot -c ${target%bit} -p "\$p" -- "\$@" +fi +exit 1 +EOF +sudo chown root:root /usr/local/bin/"${target%bit}" +sudo chmod 755 /usr/local/bin/"${target%bit}" + +# Add a few more repositories to the chroot +[ -r /var/lib/chroot/${target}/etc/apt/sources.list ] && +sudo sed -i 's/ main$/ main restricted universe multiverse/ + p + t1 + d + :1;s/^deb/deb-src/ + t + d' /var/lib/chroot/${target}/etc/apt/sources.list + +# Update packages +sudo schroot -c "${target%bit}" -p -- /bin/sh -c ' + apt-get update; apt-get -y dist-upgrade' || : + +# Install a couple of missing packages +for i in debian-keyring ubuntu-keyring locales sudo; do + [ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] || + sudo schroot -c "${target%bit}" -p -- apt-get -y install "$i" || : +done + +# Configure locales +sudo schroot -c "${target%bit}" -p -- /bin/sh -c ' + l='"${LANG:-en_US}"'; l="${l%%.*}" + [ -r /etc/locale.gen ] && + sed -i "s/^# \($l\)/\1/" /etc/locale.gen + locale-gen $LANG en_US en_US.UTF-8' || : + +# Configure "sudo" package +sudo schroot -c "${target%bit}" -p -- /bin/sh -c ' + egrep '"'^$(id -nu) '"' /etc/sudoers >/dev/null 2>&1 || + echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers' + +# Install a few more commonly used packages +sudo schroot -c "${target%bit}" -p -- apt-get -y install \ + autoconf automake1.9 dpkg-dev g++-multilib gcc-multilib gdb less libtool \ + strace + +# If running a 32bit environment on a 64bit machine, install a few binaries +# as 64bit. +if [ "${arch}" = 32bit ] && file /bin/bash 2>/dev/null | grep -q x86-64; then + sudo schroot -c "${target%bit}" -p -- apt-get -y install \ + lib64expat1 lib64ncurses5 lib64readline6 lib64z1 + dep= + for i in binutils gdb strace; do + [ -d /usr/share/doc/"$i" ] || dep="$dep $i" + done + [ -n "$dep" ] && sudo apt-get -y install $dep + sudo cp /usr/bin/gdb /var/lib/chroot/${target}/usr/local/bin/ + sudo cp /usr/bin/ld /var/lib/chroot/${target}/usr/local/bin/ + for i in libbfd libpython; do + lib="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } | + grep "$i" | awk '{ print $3 }')" + if [ -n "$lib" -a -r "$lib" ]; then + sudo cp "$lib" /var/lib/chroot/${target}/usr/lib64/ + fi + done + for lib in libssl libcrypt; do + sudo cp /usr/lib/$lib* /var/lib/chroot/${target}/usr/lib64/ || : + done +fi + +# Clean up package files +sudo schroot -c "${target%bit}" -p -- apt-get clean +sudo apt-get clean + +# Let the user know what we did +trap '' INT TERM QUIT +trap '' EXIT +cat <<EOF + + +Successfully installed ${distname} ${arch} + +You can run programs inside of the chroot by invoking the "${target%bit}" +command. + +Your home directory is shared between the host and the chroot. But I configured +$HOME/chroot to be private to the chroot environment. You can use it +for files that need to differ between environments. +EOF |