1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/trunk/build/install-chroot.sh Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,809 @@ 1.4 +#!/bin/bash -e 1.5 + 1.6 +# Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.7 +# Use of this source code is governed by a BSD-style license that can be 1.8 +# found in the LICENSE file. 1.9 + 1.10 +# This script installs Debian-derived distributions in a chroot environment. 1.11 +# It can for example be used to have an accurate 32bit build and test 1.12 +# environment when otherwise working on a 64bit machine. 1.13 +# N. B. it is unlikely that this script will ever work on anything other than a 1.14 +# Debian-derived system. 1.15 + 1.16 +# Older Debian based systems had both "admin" and "adm" groups, with "admin" 1.17 +# apparently being used in more places. Newer distributions have standardized 1.18 +# on just the "adm" group. Check /etc/group for the prefered name of the 1.19 +# administrator group. 1.20 +admin=$(grep '^admin:' /etc/group >&/dev/null && echo admin || echo adm) 1.21 + 1.22 +usage() { 1.23 + echo "usage: ${0##*/} [-m mirror] [-g group,...] [-s] [-c]" 1.24 + echo "-b dir additional directories that should be bind mounted," 1.25 + echo ' or "NONE".' 1.26 + echo " Default: if local filesystems present, ask user for help" 1.27 + echo "-g group,... groups that can use the chroot unauthenticated" 1.28 + echo " Default: '${admin}' and current user's group ('$(id -gn)')" 1.29 + echo "-l List all installed chroot environments" 1.30 + echo "-m mirror an alternate repository mirror for package downloads" 1.31 + echo "-s configure default deb-srcs" 1.32 + echo "-c always copy 64bit helper binaries to 32bit chroot" 1.33 + echo "-h this help message" 1.34 +} 1.35 + 1.36 +process_opts() { 1.37 + local OPTNAME OPTIND OPTERR OPTARG 1.38 + while getopts ":b:g:lm:sch" OPTNAME; do 1.39 + case "$OPTNAME" in 1.40 + b) 1.41 + if [ "${OPTARG}" = "NONE" -a -z "${bind_mounts}" ]; then 1.42 + bind_mounts="${OPTARG}" 1.43 + else 1.44 + if [ "${bind_mounts}" = "NONE" -o "${OPTARG}" = "${OPTARG#/}" -o \ 1.45 + ! -d "${OPTARG}" ]; then 1.46 + echo "Invalid -b option(s)" 1.47 + usage 1.48 + exit 1 1.49 + fi 1.50 + bind_mounts="${bind_mounts} 1.51 +${OPTARG} ${OPTARG} none rw,bind 0 0" 1.52 + fi 1.53 + ;; 1.54 + g) 1.55 + [ -n "${OPTARG}" ] && 1.56 + chroot_groups="${chroot_groups}${chroot_groups:+,}${OPTARG}" 1.57 + ;; 1.58 + l) 1.59 + list_all_chroots 1.60 + exit 1.61 + ;; 1.62 + m) 1.63 + if [ -n "${mirror}" ]; then 1.64 + echo "You can only specify exactly one mirror location" 1.65 + usage 1.66 + exit 1 1.67 + fi 1.68 + mirror="$OPTARG" 1.69 + ;; 1.70 + s) 1.71 + add_srcs="y" 1.72 + ;; 1.73 + c) 1.74 + copy_64="y" 1.75 + ;; 1.76 + h) 1.77 + usage 1.78 + exit 0 1.79 + ;; 1.80 + \:) 1.81 + echo "'-$OPTARG' needs an argument." 1.82 + usage 1.83 + exit 1 1.84 + ;; 1.85 + *) 1.86 + echo "invalid command-line option: $OPTARG" 1.87 + usage 1.88 + exit 1 1.89 + ;; 1.90 + esac 1.91 + done 1.92 + 1.93 + if [ $# -ge ${OPTIND} ]; then 1.94 + eval echo "Unexpected command line argument: \${${OPTIND}}" 1.95 + usage 1.96 + exit 1 1.97 + fi 1.98 +} 1.99 + 1.100 +list_all_chroots() { 1.101 + for i in /var/lib/chroot/*; do 1.102 + i="${i##*/}" 1.103 + [ "${i}" = "*" ] && continue 1.104 + [ -x "/usr/local/bin/${i%bit}" ] || continue 1.105 + grep -qs "^\[${i%bit}\]\$" /etc/schroot/schroot.conf || continue 1.106 + [ -r "/etc/schroot/script-${i}" -a \ 1.107 + -r "/etc/schroot/mount-${i}" ] || continue 1.108 + echo "${i%bit}" 1.109 + done 1.110 +} 1.111 + 1.112 +getkey() { 1.113 + ( 1.114 + trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT HUP 1.115 + stty -echo iuclc -icanon 2>/dev/null 1.116 + dd count=1 bs=1 2>/dev/null 1.117 + ) 1.118 +} 1.119 + 1.120 +chr() { 1.121 + printf "\\$(printf '%03o' "$1")" 1.122 +} 1.123 + 1.124 +ord() { 1.125 + printf '%d' $(printf '%c' "$1" | od -tu1 -An) 1.126 +} 1.127 + 1.128 +is_network_drive() { 1.129 + stat -c %T -f "$1/" 2>/dev/null | 1.130 + egrep -qs '^nfs|cifs|smbfs' 1.131 +} 1.132 + 1.133 +# Check that we are running as a regular user 1.134 +[ "$(id -nu)" = root ] && { 1.135 + echo "Run this script as a regular user and provide your \"sudo\"" \ 1.136 + "password if requested" >&2 1.137 + exit 1 1.138 +} 1.139 + 1.140 +process_opts "$@" 1.141 + 1.142 +echo "This script will help you through the process of installing a" 1.143 +echo "Debian or Ubuntu distribution in a chroot environment. You will" 1.144 +echo "have to provide your \"sudo\" password when requested." 1.145 +echo 1.146 + 1.147 +# Error handler 1.148 +trap 'exit 1' INT TERM QUIT HUP 1.149 +trap 'sudo apt-get clean; tput bel; echo; echo Failed' EXIT 1.150 + 1.151 +# Install any missing applications that this script relies on. If these packages 1.152 +# are already installed, don't force another "apt-get install". That would 1.153 +# prevent them from being auto-removed, if they ever become eligible for that. 1.154 +# And as this script only needs the packages once, there is no good reason to 1.155 +# introduce a hard dependency on things such as dchroot and debootstrap. 1.156 +dep= 1.157 +for i in dchroot debootstrap libwww-perl; do 1.158 + [ -d /usr/share/doc/"$i" ] || dep="$dep $i" 1.159 +done 1.160 +[ -n "$dep" ] && sudo apt-get -y install $dep 1.161 +sudo apt-get -y install schroot 1.162 + 1.163 +# Create directory for chroot 1.164 +sudo mkdir -p /var/lib/chroot 1.165 + 1.166 +# Find chroot environments that can be installed with debootstrap 1.167 +targets="$(cd /usr/share/debootstrap/scripts 1.168 + ls | grep '^[a-z]*$')" 1.169 + 1.170 +# Ask user to pick one of the available targets 1.171 +echo "The following targets are available to be installed in a chroot:" 1.172 +j=1; for i in $targets; do 1.173 + printf '%4d: %s\n' "$j" "$i" 1.174 + j=$(($j+1)) 1.175 +done 1.176 +while :; do 1.177 + printf "Which target would you like to install: " 1.178 + read n 1.179 + [ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev/null && break 1.180 +done 1.181 +j=1; for i in $targets; do 1.182 + [ "$j" -eq "$n" ] && { distname="$i"; break; } 1.183 + j=$(($j+1)) 1.184 +done 1.185 +echo 1.186 + 1.187 +# On x86-64, ask whether the user wants to install x86-32 or x86-64 1.188 +archflag= 1.189 +arch= 1.190 +if [ "$(uname -m)" = x86_64 ]; then 1.191 + while :; do 1.192 + echo "You are running a 64bit kernel. This allows you to install either a" 1.193 + printf "32bit or a 64bit chroot environment. %s" \ 1.194 + "Which one do you want (32, 64) " 1.195 + read arch 1.196 + [ "${arch}" == 32 -o "${arch}" == 64 ] && break 1.197 + done 1.198 + [ "${arch}" == 32 ] && archflag="--arch i386" || archflag="--arch amd64" 1.199 + arch="${arch}bit" 1.200 + echo 1.201 +fi 1.202 +target="${distname}${arch}" 1.203 + 1.204 +# Don't accidentally overwrite an existing installation 1.205 +[ -d /var/lib/chroot/"${target}" ] && { 1.206 + while :; do 1.207 + echo "This chroot already exists on your machine." 1.208 + if schroot -l --all-sessions 2>&1 | 1.209 + sed 's/^session://' | 1.210 + grep -qs "^${target%bit}-"; then 1.211 + echo "And it appears to be in active use. Terminate all programs that" 1.212 + echo "are currently using the chroot environment and then re-run this" 1.213 + echo "script." 1.214 + echo "If you still get an error message, you might have stale mounts" 1.215 + echo "that you forgot to delete. You can always clean up mounts by" 1.216 + echo "executing \"${target%bit} -c\"." 1.217 + exit 1 1.218 + fi 1.219 + echo "I can abort installation, I can overwrite the existing chroot," 1.220 + echo "or I can delete the old one and then exit. What would you like to" 1.221 + printf "do (a/o/d)? " 1.222 + read choice 1.223 + case "${choice}" in 1.224 + a|A) exit 1;; 1.225 + o|O) sudo rm -rf "/var/lib/chroot/${target}"; break;; 1.226 + d|D) sudo rm -rf "/var/lib/chroot/${target}" \ 1.227 + "/usr/local/bin/${target%bit}" \ 1.228 + "/etc/schroot/mount-${target}" \ 1.229 + "/etc/schroot/script-${target}" 1.230 + sudo sed -ni '/^[[]'"${target%bit}"']$/,${ 1.231 + :1;n;/^[[]/b2;b1;:2;p;n;b2};p' \ 1.232 + "/etc/schroot/schroot.conf" 1.233 + trap '' INT TERM QUIT HUP 1.234 + trap '' EXIT 1.235 + echo "Deleted!" 1.236 + exit 0;; 1.237 + esac 1.238 + done 1.239 + echo 1.240 +} 1.241 +sudo mkdir -p /var/lib/chroot/"${target}" 1.242 + 1.243 +# Offer to include additional standard repositories for Ubuntu-based chroots. 1.244 +alt_repos= 1.245 +grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" && { 1.246 + while :; do 1.247 + echo "Would you like to add ${distname}-updates and ${distname}-security " 1.248 + printf "to the chroot's sources.list (y/n)? " 1.249 + read alt_repos 1.250 + case "${alt_repos}" in 1.251 + y|Y) 1.252 + alt_repos="y" 1.253 + break 1.254 + ;; 1.255 + n|N) 1.256 + break 1.257 + ;; 1.258 + esac 1.259 + done 1.260 + echo 1.261 +} 1.262 + 1.263 +# Check for non-standard file system mount points and ask the user whether 1.264 +# they should be imported into the chroot environment 1.265 +# We limit to the first 26 mount points that much some basic heuristics, 1.266 +# because a) that allows us to enumerate choices with a single character, 1.267 +# and b) if we find more than 26 mount points, then these are probably 1.268 +# false-positives and something is very unusual about the system's 1.269 +# configuration. No need to spam the user with even more information that 1.270 +# is likely completely irrelevant. 1.271 +if [ -z "${bind_mounts}" ]; then 1.272 + mounts="$(awk '$2 != "/" && $2 !~ "^/boot" && $2 !~ "^/home" && 1.273 + $2 !~ "^/media" && $2 !~ "^/run" && 1.274 + ($3 ~ "ext[2-4]" || $3 == "reiserfs" || $3 == "btrfs" || 1.275 + $3 == "xfs" || $3 == "jfs" || $3 == "u?msdos" || 1.276 + $3 == "v?fat" || $3 == "hfs" || $3 == "ntfs" || 1.277 + $3 ~ "nfs[4-9]?" || $3 == "smbfs" || $3 == "cifs") { 1.278 + print $2 1.279 + }' /proc/mounts | 1.280 + head -n26)" 1.281 + if [ -n "${mounts}" ]; then 1.282 + echo "You appear to have non-standard mount points that you" 1.283 + echo "might want to import into the chroot environment:" 1.284 + echo 1.285 + sel= 1.286 + while :; do 1.287 + # Print a menu, listing all non-default mounts of local or network 1.288 + # file systems. 1.289 + j=1; for m in ${mounts}; do 1.290 + c="$(printf $(printf '\\%03o' $((64+$j))))" 1.291 + echo "$sel" | grep -qs $c && 1.292 + state="mounted in chroot" || state="$(tput el)" 1.293 + printf " $c) %-40s${state}\n" "$m" 1.294 + j=$(($j+1)) 1.295 + done 1.296 + # Allow user to interactively (de-)select any of the entries 1.297 + echo 1.298 + printf "Select mount points that you want to be included or press %s" \ 1.299 + "SPACE to continue" 1.300 + c="$(getkey | tr a-z A-Z)" 1.301 + [ "$c" == " " ] && { echo; echo; break; } 1.302 + if [ -z "$c" ] || 1.303 + [ "$c" '<' 'A' -o $(ord "$c") -gt $((64 + $(ord "$j"))) ]; then 1.304 + # Invalid input, ring the console bell 1.305 + tput bel 1.306 + else 1.307 + # Toggle the selection for the given entry 1.308 + if echo "$sel" | grep -qs $c; then 1.309 + sel="$(printf "$sel" | sed "s/$c//")" 1.310 + else 1.311 + sel="$sel$c" 1.312 + fi 1.313 + fi 1.314 + # Reposition cursor to the top of the list of entries 1.315 + tput cuu $(($j + 1)) 1.316 + echo 1.317 + done 1.318 + fi 1.319 + j=1; for m in ${mounts}; do 1.320 + c="$(chr $(($j + 64)))" 1.321 + if echo "$sel" | grep -qs $c; then 1.322 + bind_mounts="${bind_mounts}$m $m none rw,bind 0 0 1.323 +" 1.324 + fi 1.325 + j=$(($j+1)) 1.326 + done 1.327 +fi 1.328 + 1.329 +# Remove stale entry from /etc/schroot/schroot.conf. Entries start 1.330 +# with the target name in square brackets, followed by an arbitrary 1.331 +# number of lines. The entry stops when either the end of file has 1.332 +# been reached, or when the beginning of a new target is encountered. 1.333 +# This means, we cannot easily match for a range of lines in 1.334 +# "sed". Instead, we actually have to iterate over each line and check 1.335 +# whether it is the beginning of a new entry. 1.336 +sudo sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p' \ 1.337 + /etc/schroot/schroot.conf 1.338 + 1.339 +# Download base system. This takes some time 1.340 +if [ -z "${mirror}" ]; then 1.341 + grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" && 1.342 + mirror="http://archive.ubuntu.com/ubuntu" || 1.343 + mirror="http://ftp.us.debian.org/debian" 1.344 +fi 1.345 + 1.346 +sudo ${http_proxy:+http_proxy="${http_proxy}"} debootstrap ${archflag} \ 1.347 + "${distname}" "/var/lib/chroot/${target}" "$mirror" 1.348 + 1.349 +# Add new entry to /etc/schroot/schroot.conf 1.350 +grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" && 1.351 + brand="Ubuntu" || brand="Debian" 1.352 +if [ -z "${chroot_groups}" ]; then 1.353 + chroot_groups="${admin},$(id -gn)" 1.354 +fi 1.355 +# Older versions of schroot wanted a "priority=" line, whereas recent 1.356 +# versions deprecate "priority=" and warn if they see it. We don't have 1.357 +# a good feature test, but scanning for the string "priority=" in the 1.358 +# existing "schroot.conf" file is a good indication of what to do. 1.359 +priority=$(grep -qs 'priority=' /etc/schroot/schroot.conf && 1.360 + echo 'priority=3' || :) 1.361 +sudo sh -c 'cat >>/etc/schroot/schroot.conf' <<EOF 1.362 +[${target%bit}] 1.363 +description=${brand} ${distname} ${arch} 1.364 +type=directory 1.365 +directory=/var/lib/chroot/${target} 1.366 +users=root 1.367 +groups=${chroot_groups} 1.368 +root-groups=${chroot_groups} 1.369 +personality=linux$([ "${arch}" != 64bit ] && echo 32) 1.370 +script-config=script-${target} 1.371 +${priority} 1.372 + 1.373 +EOF 1.374 + 1.375 +# Set up a list of mount points that is specific to this 1.376 +# chroot environment. 1.377 +sed '/^FSTAB=/s,"[^"]*","/etc/schroot/mount-'"${target}"'",' \ 1.378 + /etc/schroot/script-defaults | 1.379 + sudo sh -c 'cat >/etc/schroot/script-'"${target}" 1.380 +sed '\,^/home[/[:space:]],s/\([,[:space:]]\)bind[[:space:]]/\1rbind /' \ 1.381 + /etc/schroot/mount-defaults | 1.382 + sudo sh -c 'cat > /etc/schroot/mount-'"${target}" 1.383 + 1.384 +# Add the extra mount points that the user told us about 1.385 +[ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] && 1.386 + printf "${bind_mounts}" | 1.387 + sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" 1.388 + 1.389 +# If this system has a "/media" mountpoint, import it into the chroot 1.390 +# environment. Most modern distributions use this mount point to 1.391 +# automatically mount devices such as CDROMs, USB sticks, etc... 1.392 +if [ -d /media ] && 1.393 + ! grep -qs '^/media' /etc/schroot/mount-"${target}"; then 1.394 + echo '/media /media none rw,rbind 0 0' | 1.395 + sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" 1.396 +fi 1.397 + 1.398 +# Share /dev/shm and possibly /run/shm 1.399 +grep -qs '^/dev/shm' /etc/schroot/mount-"${target}" || 1.400 + echo '/dev/shm /dev/shm none rw,bind 0 0' | 1.401 + sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" 1.402 +if [ -d "/var/lib/chroot/${target}/run" ] && 1.403 + ! grep -qs '^/run/shm' /etc/schroot/mount-"${target}"; then 1.404 + { [ -d /run ] && echo '/run/shm /run/shm none rw,bind 0 0' || 1.405 + echo '/dev/shm /run/shm none rw,bind 0 0'; } | 1.406 + sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" 1.407 +fi 1.408 + 1.409 +# Set up a special directory that changes contents depending on the target 1.410 +# that is executing. 1.411 +d="$(readlink -f "${HOME}/chroot" 2>/dev/null || echo "${HOME}/chroot")" 1.412 +s="${d}/.${target}" 1.413 +echo "${s} ${d} none rw,bind 0 0" | 1.414 + sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" 1.415 +mkdir -p "${s}" 1.416 + 1.417 +# Install a helper script to launch commands in the chroot 1.418 +sudo sh -c 'cat >/usr/local/bin/'"${target%bit}" <<'EOF' 1.419 +#!/bin/bash 1.420 + 1.421 +chroot="${0##*/}" 1.422 + 1.423 +wrap() { 1.424 + # Word-wrap the text passed-in on stdin. Optionally, on continuation lines 1.425 + # insert the same number of spaces as the number of characters in the 1.426 + # parameter(s) passed to this function. 1.427 + # If the "fold" program cannot be found, or if the actual width of the 1.428 + # terminal cannot be determined, this function doesn't attempt to do any 1.429 + # wrapping. 1.430 + local f="$(type -P fold)" 1.431 + [ -z "${f}" ] && { cat; return; } 1.432 + local c="$(stty -a </dev/tty 2>/dev/null | 1.433 + sed 's/.*columns[[:space:]]*\([0-9]*\).*/\1/;t;d')" 1.434 + [ -z "${c}" ] && { cat; return; } 1.435 + local i="$(echo "$*"|sed 's/./ /g')" 1.436 + local j="$(printf %s "${i}"|wc -c)" 1.437 + if [ "${c}" -gt "${j}" ]; then 1.438 + dd bs=1 count="${j}" 2>/dev/null 1.439 + "${f}" -sw "$((${c}-${j}))" | sed '2,$s/^/'"${i}"'/' 1.440 + else 1.441 + "${f}" -sw "${c}" 1.442 + fi 1.443 +} 1.444 + 1.445 +help() { 1.446 + echo "Usage ${0##*/} [-h|--help] [-c|--clean] [-C|--clean-all] [-l|--list] [--] args" | wrap "Usage ${0##*/} " 1.447 + echo " help: print this message" | wrap " " 1.448 + echo " list: list all known chroot environments" | wrap " " 1.449 + echo " clean: remove all old chroot sessions for \"${chroot}\"" | wrap " " 1.450 + echo " clean-all: remove all old chroot sessions for all environments" | wrap " " 1.451 + exit 0 1.452 +} 1.453 + 1.454 +clean() { 1.455 + local s t rc 1.456 + rc=0 1.457 + for s in $(schroot -l --all-sessions); do 1.458 + if [ -n "$1" ]; then 1.459 + t="${s#session:}" 1.460 + [ "${t#${chroot}-}" == "${t}" ] && continue 1.461 + fi 1.462 + if ls -l /proc/*/{cwd,fd} 2>/dev/null | 1.463 + fgrep -qs "/var/lib/schroot/mount/${t}"; then 1.464 + echo "Session \"${t}\" still has active users, not cleaning up" | wrap 1.465 + rc=1 1.466 + continue 1.467 + fi 1.468 + sudo schroot -c "${s}" -e || rc=1 1.469 + done 1.470 + exit ${rc} 1.471 +} 1.472 + 1.473 +list() { 1.474 + for e in $(schroot -l); do 1.475 + e="${e#chroot:}" 1.476 + [ -x "/usr/local/bin/${e}" ] || continue 1.477 + if schroot -l --all-sessions 2>/dev/null | 1.478 + sed 's/^session://' | 1.479 + grep -qs "^${e}-"; then 1.480 + echo "${e} is currently active" 1.481 + else 1.482 + echo "${e}" 1.483 + fi 1.484 + done 1.485 + exit 0 1.486 +} 1.487 + 1.488 +while [ "$#" -ne 0 ]; do 1.489 + case "$1" in 1.490 + --) shift; break;; 1.491 + -h|--help) shift; help;; 1.492 + -l|--list) shift; list;; 1.493 + -c|--clean) shift; clean "${chroot}";; 1.494 + -C|--clean-all) shift; clean;; 1.495 + *) break;; 1.496 + esac 1.497 +done 1.498 + 1.499 +session="$(schroot -c "${chroot}" -b)" 1.500 + 1.501 +if [ $# -eq 0 ]; then 1.502 + schroot -c "${session}" -r -p 1.503 +else 1.504 + p="$1"; shift 1.505 + schroot -c "${session}" -r -p "$p" -- "$@" 1.506 +fi 1.507 +rc=$? 1.508 + 1.509 +i=$(schroot -c "${session}" -r -p ls -- -id /proc/self/root/. | 1.510 + awk '{ print $1 }') 2>/dev/null 1.511 +while [ -n "$i" ]; do 1.512 + pids=$(ls -id1 /proc/*/root/. 2>/dev/null | 1.513 + sed -e 's,^[^0-9]*'$i'.*/\([1-9][0-9]*\)/.*$,\1, 1.514 + t 1.515 + d') >/dev/null 2>&1 1.516 + [ -z "$pids" ] && break 1.517 + kill -9 $pids 1.518 +done 1.519 +schroot -c "${session}" -e 1.520 +exit $rc 1.521 +EOF 1.522 +sudo chown root:root /usr/local/bin/"${target%bit}" 1.523 +sudo chmod 755 /usr/local/bin/"${target%bit}" 1.524 + 1.525 +# Add the standard Ubuntu update repositories if requested. 1.526 +[ "${alt_repos}" = "y" -a \ 1.527 + -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && 1.528 +sudo sed -i '/^deb .* [^ -]\+ main$/p 1.529 + s/^\(deb .* [^ -]\+\) main/\1-security main/ 1.530 + p 1.531 + t1 1.532 + d 1.533 + :1;s/-security main/-updates main/ 1.534 + t 1.535 + d' "/var/lib/chroot/${target}/etc/apt/sources.list" 1.536 + 1.537 +# Add a few more repositories to the chroot 1.538 +[ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && 1.539 +sudo sed -i 's/ main$/ main restricted universe multiverse/' \ 1.540 + "/var/lib/chroot/${target}/etc/apt/sources.list" 1.541 + 1.542 +# Add the Ubuntu "partner" repository, if available 1.543 +if [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && 1.544 + HEAD "http://archive.canonical.com/ubuntu/dists/${distname}/partner" \ 1.545 + >&/dev/null; then 1.546 + sudo sh -c ' 1.547 + echo "deb http://archive.canonical.com/ubuntu" \ 1.548 + "'"${distname}"' partner" \ 1.549 + >>"/var/lib/chroot/'"${target}"'/etc/apt/sources.list"' 1.550 +fi 1.551 + 1.552 +# Add source repositories, if the user requested we do so 1.553 +[ "${add_srcs}" = "y" -a \ 1.554 + -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && 1.555 +sudo sed -i '/^deb[^-]/p 1.556 + s/^deb\([^-]\)/deb-src\1/' \ 1.557 + "/var/lib/chroot/${target}/etc/apt/sources.list" 1.558 + 1.559 +# Set apt proxy if host has set http_proxy 1.560 +if [ -n "${http_proxy}" ]; then 1.561 + sudo sh -c ' 1.562 + echo "Acquire::http::proxy \"'"${http_proxy}"'\";" \ 1.563 + >>"/var/lib/chroot/'"${target}"'/etc/apt/apt.conf"' 1.564 +fi 1.565 + 1.566 +# Update packages 1.567 +sudo "/usr/local/bin/${target%bit}" /bin/sh -c ' 1.568 + apt-get update; apt-get -y dist-upgrade' || : 1.569 + 1.570 +# Install a couple of missing packages 1.571 +for i in debian-keyring ubuntu-keyring locales sudo; do 1.572 + [ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] || 1.573 + sudo "/usr/local/bin/${target%bit}" apt-get -y install "$i" || : 1.574 +done 1.575 + 1.576 +# Configure locales 1.577 +sudo "/usr/local/bin/${target%bit}" /bin/sh -c ' 1.578 + l='"${LANG:-en_US}"'; l="${l%%.*}" 1.579 + [ -r /etc/locale.gen ] && 1.580 + sed -i "s/^# \($l\)/\1/" /etc/locale.gen 1.581 + locale-gen $LANG en_US en_US.UTF-8' || : 1.582 + 1.583 +# Enable multi-arch support, if available 1.584 +sudo "/usr/local/bin/${target%bit}" dpkg --assert-multi-arch >&/dev/null && 1.585 + [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && { 1.586 + sudo sed -i 's/ / [arch=amd64,i386] /' \ 1.587 + "/var/lib/chroot/${target}/etc/apt/sources.list" 1.588 + [ -d /var/lib/chroot/${target}/etc/dpkg/dpkg.cfg.d/ ] && 1.589 + echo foreign-architecture \ 1.590 + $([ "${arch}" = "32bit" ] && echo amd64 || echo i386) | 1.591 + sudo sh -c "cat >'/var/lib/chroot/${target}/etc/dpkg/dpkg.cfg.d/multiarch'" 1.592 +} 1.593 + 1.594 +# Configure "sudo" package 1.595 +sudo "/usr/local/bin/${target%bit}" /bin/sh -c ' 1.596 + egrep -qs '"'^$(id -nu) '"' /etc/sudoers || 1.597 + echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers' 1.598 + 1.599 +# Install a few more commonly used packages 1.600 +sudo "/usr/local/bin/${target%bit}" apt-get -y install \ 1.601 + autoconf automake1.9 dpkg-dev g++-multilib gcc-multilib gdb less libtool \ 1.602 + strace 1.603 + 1.604 +# If running a 32bit environment on a 64bit machine, install a few binaries 1.605 +# as 64bit. This is only done automatically if the chroot distro is the same as 1.606 +# the host, otherwise there might be incompatibilities in build settings or 1.607 +# runtime dependencies. The user can force it with the '-c' flag. 1.608 +host_distro=$(grep -s DISTRIB_CODENAME /etc/lsb-release | \ 1.609 + cut -d "=" -f 2) 1.610 +if [ "${copy_64}" = "y" -o \ 1.611 + "${host_distro}" = "${distname}" -a "${arch}" = 32bit ] && \ 1.612 + file /bin/bash 2>/dev/null | grep -q x86-64; then 1.613 + readlinepkg=$(sudo "/usr/local/bin/${target%bit}" sh -c \ 1.614 + 'apt-cache search "lib64readline.\$" | sort | tail -n 1 | cut -d " " -f 1') 1.615 + sudo "/usr/local/bin/${target%bit}" apt-get -y install \ 1.616 + lib64expat1 lib64ncurses5 ${readlinepkg} lib64z1 1.617 + dep= 1.618 + for i in binutils gdb; do 1.619 + [ -d /usr/share/doc/"$i" ] || dep="$dep $i" 1.620 + done 1.621 + [ -n "$dep" ] && sudo apt-get -y install $dep 1.622 + sudo mkdir -p "/var/lib/chroot/${target}/usr/local/lib/amd64" 1.623 + for i in libbfd libpython; do 1.624 + lib="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } | 1.625 + grep -s "$i" | awk '{ print $3 }')" 1.626 + if [ -n "$lib" -a -r "$lib" ]; then 1.627 + sudo cp "$lib" "/var/lib/chroot/${target}/usr/local/lib/amd64" 1.628 + fi 1.629 + done 1.630 + for lib in libssl libcrypt; do 1.631 + for path in /usr/lib /usr/lib/x86_64-linux-gnu; do 1.632 + sudo cp $path/$lib* \ 1.633 + "/var/lib/chroot/${target}/usr/local/lib/amd64/" >&/dev/null || : 1.634 + done 1.635 + done 1.636 + for i in gdb ld; do 1.637 + sudo cp /usr/bin/$i "/var/lib/chroot/${target}/usr/local/lib/amd64/" 1.638 + sudo sh -c "cat >'/var/lib/chroot/${target}/usr/local/bin/$i'" <<EOF 1.639 +#!/bin/sh 1.640 +exec /lib64/ld-linux-x86-64.so.2 --library-path /usr/local/lib/amd64 \ 1.641 + /usr/local/lib/amd64/$i "\$@" 1.642 +EOF 1.643 + sudo chmod 755 "/var/lib/chroot/${target}/usr/local/bin/$i" 1.644 + done 1.645 +fi 1.646 + 1.647 + 1.648 +# If the install-build-deps.sh script can be found, offer to run it now 1.649 +script="$(dirname $(readlink -f "$0"))/install-build-deps.sh" 1.650 +if [ -x "${script}" ]; then 1.651 + while :; do 1.652 + echo 1.653 + echo "If you plan on building Chrome inside of the new chroot environment," 1.654 + echo "you now have to install the build dependencies. Do you want me to" 1.655 + printf "start the script that does this for you (y/n)? " 1.656 + read install_deps 1.657 + case "${install_deps}" in 1.658 + y|Y) 1.659 + echo 1.660 + # We prefer running the script in-place, but this might not be 1.661 + # possible, if it lives on a network filesystem that denies 1.662 + # access to root. 1.663 + tmp_script= 1.664 + if ! sudo /usr/local/bin/"${target%bit}" \ 1.665 + sh -c "[ -x '${script}' ]" >&/dev/null; then 1.666 + tmp_script="/tmp/${script##*/}" 1.667 + cp "${script}" "${tmp_script}" 1.668 + fi 1.669 + # Some distributions automatically start an instance of the system- 1.670 + # wide dbus daemon, cron daemon or of the logging daemon, when 1.671 + # installing the Chrome build depencies. This prevents the chroot 1.672 + # session from being closed. So, we always try to shut down any running 1.673 + # instance of dbus and rsyslog. 1.674 + sudo /usr/local/bin/"${target%bit}" sh -c "${script} --no-lib32; 1.675 + rc=$?; 1.676 + /etc/init.d/cron stop >/dev/null 2>&1 || :; 1.677 + /etc/init.d/rsyslog stop >/dev/null 2>&1 || :; 1.678 + /etc/init.d/dbus stop >/dev/null 2>&1 || :; 1.679 + exit $rc" 1.680 + rc=$? 1.681 + [ -n "${tmp_script}" ] && rm -f "${tmp_script}" 1.682 + [ $rc -ne 0 ] && exit $rc 1.683 + break 1.684 + ;; 1.685 + n|N) 1.686 + break 1.687 + ;; 1.688 + esac 1.689 + done 1.690 + echo 1.691 +fi 1.692 + 1.693 +# Check whether ~/chroot is on a (slow) network file system and offer to 1.694 +# relocate it. Also offer relocation, if the user appears to have multiple 1.695 +# spindles (as indicated by "${bind_mount}" being non-empty). 1.696 +# We only offer this option, if it doesn't look as if a chroot environment 1.697 +# is currently active. Otherwise, relocation is unlikely to work and it 1.698 +# can be difficult for the user to recover from the failed attempt to relocate 1.699 +# the ~/chroot directory. 1.700 +# We don't aim to solve this problem for every configuration, 1.701 +# but try to help with the common cases. For more advanced configuration 1.702 +# options, the user can always manually adjust things. 1.703 +mkdir -p "${HOME}/chroot/" 1.704 +if [ ! -h "${HOME}/chroot" ] && 1.705 + ! egrep -qs '^[^[:space:]]*/chroot' /etc/fstab && 1.706 + { [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] || 1.707 + is_network_drive "${HOME}/chroot"; } && 1.708 + ! egrep -qs '/var/lib/[^/]*chroot/.*/chroot' /proc/mounts; then 1.709 + echo "${HOME}/chroot is currently located on the same device as your" 1.710 + echo "home directory." 1.711 + echo "This might not be what you want. Do you want me to move it somewhere" 1.712 + echo "else?" 1.713 + # If the computer has multiple spindles, many users configure all or part of 1.714 + # the secondary hard disk to be writable by the primary user of this machine. 1.715 + # Make some reasonable effort to detect this type of configuration and 1.716 + # then offer a good location for where to put the ~/chroot directory. 1.717 + suggest= 1.718 + for i in $(echo "${bind_mounts}"|cut -d ' ' -f 1); do 1.719 + if [ -d "$i" -a -w "$i" -a \( ! -a "$i/chroot" -o -w "$i/chroot/." \) ] && 1.720 + ! is_network_drive "$i"; then 1.721 + suggest="$i" 1.722 + else 1.723 + for j in "$i/"*; do 1.724 + if [ -d "$j" -a -w "$j" -a \ 1.725 + \( ! -a "$j/chroot" -o -w "$j/chroot/." \) ] && 1.726 + ! is_network_drive "$j"; then 1.727 + suggest="$j" 1.728 + else 1.729 + for k in "$j/"*; do 1.730 + if [ -d "$k" -a -w "$k" -a \ 1.731 + \( ! -a "$k/chroot" -o -w "$k/chroot/." \) ] && 1.732 + ! is_network_drive "$k"; then 1.733 + suggest="$k" 1.734 + break 1.735 + fi 1.736 + done 1.737 + fi 1.738 + [ -n "${suggest}" ] && break 1.739 + done 1.740 + fi 1.741 + [ -n "${suggest}" ] && break 1.742 + done 1.743 + def_suggest="${HOME}" 1.744 + if [ -n "${suggest}" ]; then 1.745 + # For home directories that reside on network drives, make our suggestion 1.746 + # the default option. For home directories that reside on a local drive, 1.747 + # require that the user manually enters the new location. 1.748 + if is_network_drive "${HOME}"; then 1.749 + def_suggest="${suggest}" 1.750 + else 1.751 + echo "A good location would probably be in \"${suggest}\"" 1.752 + fi 1.753 + fi 1.754 + while :; do 1.755 + printf "Physical location [${def_suggest}]: " 1.756 + read dir 1.757 + [ -z "${dir}" ] && dir="${def_suggest}" 1.758 + [ "${dir%%/}" == "${HOME%%/}" ] && break 1.759 + if ! [ -d "${dir}" -a -w "${dir}" ] || 1.760 + [ -a "${dir}/chroot" -a ! -w "${dir}/chroot/." ]; then 1.761 + echo "Cannot write to ${dir}/chroot. Please try again" 1.762 + else 1.763 + mv "${HOME}/chroot" "${dir}/chroot" 1.764 + ln -s "${dir}/chroot" "${HOME}/chroot" 1.765 + for i in $(list_all_chroots); do 1.766 + sudo "$i" mkdir -p "${dir}/chroot" 1.767 + done 1.768 + sudo sed -i "s,${HOME}/chroot,${dir}/chroot,g" /etc/schroot/mount-* 1.769 + break 1.770 + fi 1.771 + done 1.772 +fi 1.773 + 1.774 +# Clean up package files 1.775 +sudo schroot -c /usr/local/bin/"${target%bit}" -p -- apt-get clean 1.776 +sudo apt-get clean 1.777 + 1.778 +trap '' INT TERM QUIT HUP 1.779 +trap '' EXIT 1.780 + 1.781 +# Let the user know what we did 1.782 +cat <<EOF 1.783 + 1.784 + 1.785 +Successfully installed ${distname} ${arch} 1.786 + 1.787 +You can run programs inside of the chroot by invoking the 1.788 +"/usr/local/bin/${target%bit}" command. 1.789 + 1.790 +This command can be used with arguments, in order to just run a single 1.791 +program inside of the chroot environment (e.g. "${target%bit} make chrome") 1.792 +or without arguments, in order to run an interactive shell session inside 1.793 +of the chroot environment. 1.794 + 1.795 +If you need to run things as "root", you can use "sudo" (e.g. try 1.796 +"sudo ${target%bit} apt-get update"). 1.797 + 1.798 +Your home directory is shared between the host and the chroot. But I 1.799 +configured "${HOME}/chroot" to be private to the chroot environment. 1.800 +You can use it for files that need to differ between environments. This 1.801 +would be a good place to store binaries that you have built from your 1.802 +source files. 1.803 + 1.804 +For Chrome, this probably means you want to make your "out" directory a 1.805 +symbolic link that points somewhere inside of "${HOME}/chroot". 1.806 + 1.807 +You still need to run "gclient runhooks" whenever you switch from building 1.808 +outside of the chroot to inside of the chroot. But you will find that you 1.809 +don't have to repeatedly erase and then completely rebuild all your object 1.810 +and binary files. 1.811 + 1.812 +EOF