Quench build spew.
[chromium-blink-merge.git] / build / install-chroot.sh
blob155fc798b267237fad721a423b15a9e83c1b7f7e
1 #!/bin/bash -e
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.
7 # This script installs Debian-derived distributions in a chroot environment.
8 # It can for example be used to have an accurate 32bit build and test
9 # environment when otherwise working on a 64bit machine.
10 # N. B. it is unlikely that this script will ever work on anything other than a
11 # Debian-derived system.
13 # Older Debian based systems had both "admin" and "adm" groups, with "admin"
14 # apparently being used in more places. Newer distributions have standardized
15 # on just the "adm" group. Check /etc/group for the prefered name of the
16 # administrator group.
17 admin=$(grep '^admin:' /etc/group >&/dev/null && echo admin || echo adm)
19 usage() {
20 echo "usage: ${0##*/} [-m mirror] [-g group,...] [-s] [-c]"
21 echo "-b dir additional directories that should be bind mounted,"
22 echo ' or "NONE".'
23 echo " Default: if local filesystems present, ask user for help"
24 echo "-g group,... groups that can use the chroot unauthenticated"
25 echo " Default: '${admin}' and current user's group ('$(id -gn)')"
26 echo "-l List all installed chroot environments"
27 echo "-m mirror an alternate repository mirror for package downloads"
28 echo "-s configure default deb-srcs"
29 echo "-c always copy 64bit helper binaries to 32bit chroot"
30 echo "-h this help message"
33 process_opts() {
34 local OPTNAME OPTIND OPTERR OPTARG
35 while getopts ":b:g:lm:sch" OPTNAME; do
36 case "$OPTNAME" in
38 if [ "${OPTARG}" = "NONE" -a -z "${bind_mounts}" ]; then
39 bind_mounts="${OPTARG}"
40 else
41 if [ "${bind_mounts}" = "NONE" -o "${OPTARG}" = "${OPTARG#/}" -o \
42 ! -d "${OPTARG}" ]; then
43 echo "Invalid -b option(s)"
44 usage
45 exit 1
47 bind_mounts="${bind_mounts}
48 ${OPTARG} ${OPTARG} none rw,bind 0 0"
52 [ -n "${OPTARG}" ] &&
53 chroot_groups="${chroot_groups}${chroot_groups:+,}${OPTARG}"
56 list_all_chroots
57 exit
60 if [ -n "${mirror}" ]; then
61 echo "You can only specify exactly one mirror location"
62 usage
63 exit 1
65 mirror="$OPTARG"
68 add_srcs="y"
71 copy_64="y"
74 usage
75 exit 0
77 \:)
78 echo "'-$OPTARG' needs an argument."
79 usage
80 exit 1
83 echo "invalid command-line option: $OPTARG"
84 usage
85 exit 1
87 esac
88 done
90 if [ $# -ge ${OPTIND} ]; then
91 eval echo "Unexpected command line argument: \${${OPTIND}}"
92 usage
93 exit 1
97 list_all_chroots() {
98 for i in /var/lib/chroot/*; do
99 i="${i##*/}"
100 [ "${i}" = "*" ] && continue
101 [ -x "/usr/local/bin/${i%bit}" ] || continue
102 grep -qs "^\[${i%bit}\]\$" /etc/schroot/schroot.conf || continue
103 [ -r "/etc/schroot/script-${i}" -a \
104 -r "/etc/schroot/mount-${i}" ] || continue
105 echo "${i%bit}"
106 done
109 getkey() {
111 trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT HUP
112 stty -echo iuclc -icanon 2>/dev/null
113 dd count=1 bs=1 2>/dev/null
117 chr() {
118 printf "\\$(printf '%03o' "$1")"
121 ord() {
122 printf '%d' $(printf '%c' "$1" | od -tu1 -An)
125 is_network_drive() {
126 stat -c %T -f "$1/" 2>/dev/null |
127 egrep -qs '^nfs|cifs|smbfs'
130 # Check that we are running as a regular user
131 [ "$(id -nu)" = root ] && {
132 echo "Run this script as a regular user and provide your \"sudo\"" \
133 "password if requested" >&2
134 exit 1
137 process_opts "$@"
139 echo "This script will help you through the process of installing a"
140 echo "Debian or Ubuntu distribution in a chroot environment. You will"
141 echo "have to provide your \"sudo\" password when requested."
142 echo
144 # Error handler
145 trap 'exit 1' INT TERM QUIT HUP
146 trap 'sudo apt-get clean; tput bel; echo; echo Failed' EXIT
148 # Install any missing applications that this script relies on. If these packages
149 # are already installed, don't force another "apt-get install". That would
150 # prevent them from being auto-removed, if they ever become eligible for that.
151 # And as this script only needs the packages once, there is no good reason to
152 # introduce a hard dependency on things such as dchroot and debootstrap.
153 dep=
154 for i in dchroot debootstrap libwww-perl; do
155 [ -d /usr/share/doc/"$i" ] || dep="$dep $i"
156 done
157 [ -n "$dep" ] && sudo apt-get -y install $dep
158 sudo apt-get -y install schroot
160 # Create directory for chroot
161 sudo mkdir -p /var/lib/chroot
163 # Find chroot environments that can be installed with debootstrap
164 targets="$(cd /usr/share/debootstrap/scripts
165 ls | grep '^[a-z]*$')"
167 # Ask user to pick one of the available targets
168 echo "The following targets are available to be installed in a chroot:"
169 j=1; for i in $targets; do
170 printf '%4d: %s\n' "$j" "$i"
171 j=$(($j+1))
172 done
173 while :; do
174 printf "Which target would you like to install: "
175 read n
176 [ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev/null && break
177 done
178 j=1; for i in $targets; do
179 [ "$j" -eq "$n" ] && { distname="$i"; break; }
180 j=$(($j+1))
181 done
182 echo
184 # On x86-64, ask whether the user wants to install x86-32 or x86-64
185 archflag=
186 arch=
187 if [ "$(uname -m)" = x86_64 ]; then
188 while :; do
189 echo "You are running a 64bit kernel. This allows you to install either a"
190 printf "32bit or a 64bit chroot environment. %s" \
191 "Which one do you want (32, 64) "
192 read arch
193 [ "${arch}" == 32 -o "${arch}" == 64 ] && break
194 done
195 [ "${arch}" == 32 ] && archflag="--arch i386" || archflag="--arch amd64"
196 arch="${arch}bit"
197 echo
199 target="${distname}${arch}"
201 # Don't accidentally overwrite an existing installation
202 [ -d /var/lib/chroot/"${target}" ] && {
203 while :; do
204 echo "This chroot already exists on your machine."
205 if schroot -l --all-sessions 2>&1 |
206 sed 's/^session://' |
207 grep -qs "^${target%bit}-"; then
208 echo "And it appears to be in active use. Terminate all programs that"
209 echo "are currently using the chroot environment and then re-run this"
210 echo "script."
211 echo "If you still get an error message, you might have stale mounts"
212 echo "that you forgot to delete. You can always clean up mounts by"
213 echo "executing \"${target%bit} -c\"."
214 exit 1
216 echo "I can abort installation, I can overwrite the existing chroot,"
217 echo "or I can delete the old one and then exit. What would you like to"
218 printf "do (a/o/d)? "
219 read choice
220 case "${choice}" in
221 a|A) exit 1;;
222 o|O) sudo rm -rf "/var/lib/chroot/${target}"; break;;
223 d|D) sudo rm -rf "/var/lib/chroot/${target}" \
224 "/usr/local/bin/${target%bit}" \
225 "/etc/schroot/mount-${target}" \
226 "/etc/schroot/script-${target}"
227 sudo sed -ni '/^[[]'"${target%bit}"']$/,${
228 :1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
229 "/etc/schroot/schroot.conf"
230 trap '' INT TERM QUIT HUP
231 trap '' EXIT
232 echo "Deleted!"
233 exit 0;;
234 esac
235 done
236 echo
238 sudo mkdir -p /var/lib/chroot/"${target}"
240 # Offer to include additional standard repositories for Ubuntu-based chroots.
241 alt_repos=
242 grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" && {
243 while :; do
244 echo "Would you like to add ${distname}-updates and ${distname}-security "
245 printf "to the chroot's sources.list (y/n)? "
246 read alt_repos
247 case "${alt_repos}" in
248 y|Y)
249 alt_repos="y"
250 break
252 n|N)
253 break
255 esac
256 done
257 echo
260 # Check for non-standard file system mount points and ask the user whether
261 # they should be imported into the chroot environment
262 # We limit to the first 26 mount points that much some basic heuristics,
263 # because a) that allows us to enumerate choices with a single character,
264 # and b) if we find more than 26 mount points, then these are probably
265 # false-positives and something is very unusual about the system's
266 # configuration. No need to spam the user with even more information that
267 # is likely completely irrelevant.
268 if [ -z "${bind_mounts}" ]; then
269 mounts="$(awk '$2 != "/" && $2 !~ "^/boot" && $2 !~ "^/home" &&
270 $2 !~ "^/media" && $2 !~ "^/run" &&
271 ($3 ~ "ext[2-4]" || $3 == "reiserfs" || $3 == "btrfs" ||
272 $3 == "xfs" || $3 == "jfs" || $3 == "u?msdos" ||
273 $3 == "v?fat" || $3 == "hfs" || $3 == "ntfs" ||
274 $3 ~ "nfs[4-9]?" || $3 == "smbfs" || $3 == "cifs") {
275 print $2
276 }' /proc/mounts |
277 head -n26)"
278 if [ -n "${mounts}" ]; then
279 echo "You appear to have non-standard mount points that you"
280 echo "might want to import into the chroot environment:"
281 echo
282 sel=
283 while :; do
284 # Print a menu, listing all non-default mounts of local or network
285 # file systems.
286 j=1; for m in ${mounts}; do
287 c="$(printf $(printf '\\%03o' $((64+$j))))"
288 echo "$sel" | grep -qs $c &&
289 state="mounted in chroot" || state="$(tput el)"
290 printf " $c) %-40s${state}\n" "$m"
291 j=$(($j+1))
292 done
293 # Allow user to interactively (de-)select any of the entries
294 echo
295 printf "Select mount points that you want to be included or press %s" \
296 "SPACE to continue"
297 c="$(getkey | tr a-z A-Z)"
298 [ "$c" == " " ] && { echo; echo; break; }
299 if [ -z "$c" ] ||
300 [ "$c" '<' 'A' -o $(ord "$c") -gt $((64 + $(ord "$j"))) ]; then
301 # Invalid input, ring the console bell
302 tput bel
303 else
304 # Toggle the selection for the given entry
305 if echo "$sel" | grep -qs $c; then
306 sel="$(printf "$sel" | sed "s/$c//")"
307 else
308 sel="$sel$c"
311 # Reposition cursor to the top of the list of entries
312 tput cuu $(($j + 1))
313 echo
314 done
316 j=1; for m in ${mounts}; do
317 c="$(chr $(($j + 64)))"
318 if echo "$sel" | grep -qs $c; then
319 bind_mounts="${bind_mounts}$m $m none rw,bind 0 0
322 j=$(($j+1))
323 done
326 # Remove stale entry from /etc/schroot/schroot.conf. Entries start
327 # with the target name in square brackets, followed by an arbitrary
328 # number of lines. The entry stops when either the end of file has
329 # been reached, or when the beginning of a new target is encountered.
330 # This means, we cannot easily match for a range of lines in
331 # "sed". Instead, we actually have to iterate over each line and check
332 # whether it is the beginning of a new entry.
333 sudo sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
334 /etc/schroot/schroot.conf
336 # Download base system. This takes some time
337 if [ -z "${mirror}" ]; then
338 grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" &&
339 mirror="http://archive.ubuntu.com/ubuntu" ||
340 mirror="http://ftp.us.debian.org/debian"
343 sudo ${http_proxy:+http_proxy="${http_proxy}"} debootstrap ${archflag} \
344 "${distname}" "/var/lib/chroot/${target}" "$mirror"
346 # Add new entry to /etc/schroot/schroot.conf
347 grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" &&
348 brand="Ubuntu" || brand="Debian"
349 if [ -z "${chroot_groups}" ]; then
350 chroot_groups="${admin},$(id -gn)"
352 # Older versions of schroot wanted a "priority=" line, whereas recent
353 # versions deprecate "priority=" and warn if they see it. We don't have
354 # a good feature test, but scanning for the string "priority=" in the
355 # existing "schroot.conf" file is a good indication of what to do.
356 priority=$(grep -qs 'priority=' /etc/schroot/schroot.conf &&
357 echo 'priority=3' || :)
358 sudo sh -c 'cat >>/etc/schroot/schroot.conf' <<EOF
359 [${target%bit}]
360 description=${brand} ${distname} ${arch}
361 type=directory
362 directory=/var/lib/chroot/${target}
363 users=root
364 groups=${chroot_groups}
365 root-groups=${chroot_groups}
366 personality=linux$([ "${arch}" != 64bit ] && echo 32)
367 script-config=script-${target}
368 ${priority}
372 # Set up a list of mount points that is specific to this
373 # chroot environment.
374 sed '/^FSTAB=/s,"[^"]*","/etc/schroot/mount-'"${target}"'",' \
375 /etc/schroot/script-defaults |
376 sudo sh -c 'cat >/etc/schroot/script-'"${target}"
377 sed '\,^/home[/[:space:]],s/\([,[:space:]]\)bind[[:space:]]/\1rbind /' \
378 /etc/schroot/mount-defaults |
379 sudo sh -c 'cat > /etc/schroot/mount-'"${target}"
381 # Add the extra mount points that the user told us about
382 [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] &&
383 printf "${bind_mounts}" |
384 sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
386 # If this system has a "/media" mountpoint, import it into the chroot
387 # environment. Most modern distributions use this mount point to
388 # automatically mount devices such as CDROMs, USB sticks, etc...
389 if [ -d /media ] &&
390 ! grep -qs '^/media' /etc/schroot/mount-"${target}"; then
391 echo '/media /media none rw,rbind 0 0' |
392 sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
395 # Share /dev/shm, /run and /run/shm.
396 grep -qs '^/dev/shm' /etc/schroot/mount-"${target}" ||
397 echo '/dev/shm /dev/shm none rw,bind 0 0' |
398 sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
399 if [ ! -d "/var/lib/chroot/${target}/run" ] &&
400 ! grep -qs '^/run' /etc/schroot/mount-"${target}"; then
401 echo '/run /run none rw,bind 0 0' |
402 sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
404 if ! grep -qs '^/run/shm' /etc/schroot/mount-"${target}"; then
405 { [ -d /run ] && echo '/run/shm /run/shm none rw,bind 0 0' ||
406 echo '/dev/shm /run/shm none rw,bind 0 0'; } |
407 sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
410 # Set up a special directory that changes contents depending on the target
411 # that is executing.
412 d="$(readlink -f "${HOME}/chroot" 2>/dev/null || echo "${HOME}/chroot")"
413 s="${d}/.${target}"
414 echo "${s} ${d} none rw,bind 0 0" |
415 sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
416 mkdir -p "${s}"
418 # Install a helper script to launch commands in the chroot
419 sudo sh -c 'cat >/usr/local/bin/'"${target%bit}" <<'EOF'
420 #!/bin/bash
422 chroot="${0##*/}"
424 wrap() {
425 # Word-wrap the text passed-in on stdin. Optionally, on continuation lines
426 # insert the same number of spaces as the number of characters in the
427 # parameter(s) passed to this function.
428 # If the "fold" program cannot be found, or if the actual width of the
429 # terminal cannot be determined, this function doesn't attempt to do any
430 # wrapping.
431 local f="$(type -P fold)"
432 [ -z "${f}" ] && { cat; return; }
433 local c="$(stty -a </dev/tty 2>/dev/null |
434 sed 's/.*columns[[:space:]]*\([0-9]*\).*/\1/;t;d')"
435 [ -z "${c}" ] && { cat; return; }
436 local i="$(echo "$*"|sed 's/./ /g')"
437 local j="$(printf %s "${i}"|wc -c)"
438 if [ "${c}" -gt "${j}" ]; then
439 dd bs=1 count="${j}" 2>/dev/null
440 "${f}" -sw "$((${c}-${j}))" | sed '2,$s/^/'"${i}"'/'
441 else
442 "${f}" -sw "${c}"
446 help() {
447 echo "Usage ${0##*/} [-h|--help] [-c|--clean] [-C|--clean-all] [-l|--list] [--] args" | wrap "Usage ${0##*/} "
448 echo " help: print this message" | wrap " "
449 echo " list: list all known chroot environments" | wrap " "
450 echo " clean: remove all old chroot sessions for \"${chroot}\"" | wrap " "
451 echo " clean-all: remove all old chroot sessions for all environments" | wrap " "
452 exit 0
455 clean() {
456 local s t rc
457 rc=0
458 for s in $(schroot -l --all-sessions); do
459 if [ -n "$1" ]; then
460 t="${s#session:}"
461 [ "${t#${chroot}-}" == "${t}" ] && continue
463 if ls -l /proc/*/{cwd,fd} 2>/dev/null |
464 fgrep -qs "/var/lib/schroot/mount/${t}"; then
465 echo "Session \"${t}\" still has active users, not cleaning up" | wrap
466 rc=1
467 continue
469 sudo schroot -c "${s}" -e || rc=1
470 done
471 exit ${rc}
474 list() {
475 for e in $(schroot -l); do
476 e="${e#chroot:}"
477 [ -x "/usr/local/bin/${e}" ] || continue
478 if schroot -l --all-sessions 2>/dev/null |
479 sed 's/^session://' |
480 grep -qs "^${e}-"; then
481 echo "${e} is currently active"
482 else
483 echo "${e}"
485 done
486 exit 0
489 while [ "$#" -ne 0 ]; do
490 case "$1" in
491 --) shift; break;;
492 -h|--help) shift; help;;
493 -l|--list) shift; list;;
494 -c|--clean) shift; clean "${chroot}";;
495 -C|--clean-all) shift; clean;;
496 *) break;;
497 esac
498 done
500 session="$(schroot -c "${chroot}" -b)"
502 if [ $# -eq 0 ]; then
503 schroot -c "${session}" -r -p
504 else
505 p="$1"; shift
506 schroot -c "${session}" -r -p "$p" -- "$@"
508 rc=$?
510 i=$(schroot -c "${session}" -r -p ls -- -id /proc/self/root/. |
511 awk '{ print $1 }') 2>/dev/null
512 while [ -n "$i" ]; do
513 pids=$(ls -id1 /proc/*/root/. 2>/dev/null |
514 sed -e 's,^[^0-9]*'$i'.*/\([1-9][0-9]*\)/.*$,\1,
516 d') >/dev/null 2>&1
517 [ -z "$pids" ] && break
518 kill -9 $pids
519 done
520 schroot -c "${session}" -e
521 exit $rc
523 sudo chown root:root /usr/local/bin/"${target%bit}"
524 sudo chmod 755 /usr/local/bin/"${target%bit}"
526 # Add the standard Ubuntu update repositories if requested.
527 [ "${alt_repos}" = "y" -a \
528 -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
529 sudo sed -i '/^deb .* [^ -]\+ main$/p
530 s/^\(deb .* [^ -]\+\) main/\1-security main/
534 :1;s/-security main/-updates main/
536 d' "/var/lib/chroot/${target}/etc/apt/sources.list"
538 # Add a few more repositories to the chroot
539 [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
540 sudo sed -i 's/ main$/ main restricted universe multiverse/' \
541 "/var/lib/chroot/${target}/etc/apt/sources.list"
543 # Add the Ubuntu "partner" repository, if available
544 if [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
545 HEAD "http://archive.canonical.com/ubuntu/dists/${distname}/partner" \
546 >&/dev/null; then
547 sudo sh -c '
548 echo "deb http://archive.canonical.com/ubuntu" \
549 "'"${distname}"' partner" \
550 >>"/var/lib/chroot/'"${target}"'/etc/apt/sources.list"'
553 # Add source repositories, if the user requested we do so
554 [ "${add_srcs}" = "y" -a \
555 -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
556 sudo sed -i '/^deb[^-]/p
557 s/^deb\([^-]\)/deb-src\1/' \
558 "/var/lib/chroot/${target}/etc/apt/sources.list"
560 # Set apt proxy if host has set http_proxy
561 if [ -n "${http_proxy}" ]; then
562 sudo sh -c '
563 echo "Acquire::http::proxy \"'"${http_proxy}"'\";" \
564 >>"/var/lib/chroot/'"${target}"'/etc/apt/apt.conf"'
567 # Update packages
568 sudo "/usr/local/bin/${target%bit}" /bin/sh -c '
569 apt-get update; apt-get -y dist-upgrade' || :
571 # Install a couple of missing packages
572 for i in debian-keyring ubuntu-keyring locales sudo; do
573 [ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] ||
574 sudo "/usr/local/bin/${target%bit}" apt-get -y install "$i" || :
575 done
577 # Configure locales
578 sudo "/usr/local/bin/${target%bit}" /bin/sh -c '
579 l='"${LANG:-en_US}"'; l="${l%%.*}"
580 [ -r /etc/locale.gen ] &&
581 sed -i "s/^# \($l\)/\1/" /etc/locale.gen
582 locale-gen $LANG en_US en_US.UTF-8' || :
584 # Enable multi-arch support, if available
585 sudo "/usr/local/bin/${target%bit}" dpkg --assert-multi-arch >&/dev/null &&
586 [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && {
587 sudo sed -i 's/ / [arch=amd64,i386] /' \
588 "/var/lib/chroot/${target}/etc/apt/sources.list"
589 [ -d /var/lib/chroot/${target}/etc/dpkg/dpkg.cfg.d/ ] &&
590 sudo "/usr/local/bin/${target%bit}" dpkg --add-architecture \
591 $([ "${arch}" = "32bit" ] && echo amd64 || echo i386) >&/dev/null ||
592 echo foreign-architecture \
593 $([ "${arch}" = "32bit" ] && echo amd64 || echo i386) |
594 sudo sh -c \
595 "cat >'/var/lib/chroot/${target}/etc/dpkg/dpkg.cfg.d/multiarch'"
598 # Configure "sudo" package
599 sudo "/usr/local/bin/${target%bit}" /bin/sh -c '
600 egrep -qs '"'^$(id -nu) '"' /etc/sudoers ||
601 echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers'
603 # Install a few more commonly used packages
604 sudo "/usr/local/bin/${target%bit}" apt-get -y install \
605 autoconf automake1.9 dpkg-dev g++-multilib gcc-multilib gdb less libtool \
606 strace
608 # If running a 32bit environment on a 64bit machine, install a few binaries
609 # as 64bit. This is only done automatically if the chroot distro is the same as
610 # the host, otherwise there might be incompatibilities in build settings or
611 # runtime dependencies. The user can force it with the '-c' flag.
612 host_distro=$(grep -s DISTRIB_CODENAME /etc/lsb-release | \
613 cut -d "=" -f 2)
614 if [ "${copy_64}" = "y" -o \
615 "${host_distro}" = "${distname}" -a "${arch}" = 32bit ] && \
616 file /bin/bash 2>/dev/null | grep -q x86-64; then
617 readlinepkg=$(sudo "/usr/local/bin/${target%bit}" sh -c \
618 'apt-cache search "lib64readline.\$" | sort | tail -n 1 | cut -d " " -f 1')
619 sudo "/usr/local/bin/${target%bit}" apt-get -y install \
620 lib64expat1 lib64ncurses5 ${readlinepkg} lib64z1
621 dep=
622 for i in binutils gdb; do
623 [ -d /usr/share/doc/"$i" ] || dep="$dep $i"
624 done
625 [ -n "$dep" ] && sudo apt-get -y install $dep
626 sudo mkdir -p "/var/lib/chroot/${target}/usr/local/lib/amd64"
627 for i in libbfd libpython; do
628 lib="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } |
629 grep -s "$i" | awk '{ print $3 }')"
630 if [ -n "$lib" -a -r "$lib" ]; then
631 sudo cp "$lib" "/var/lib/chroot/${target}/usr/local/lib/amd64"
633 done
634 for lib in libssl libcrypt; do
635 for path in /usr/lib /usr/lib/x86_64-linux-gnu; do
636 sudo cp $path/$lib* \
637 "/var/lib/chroot/${target}/usr/local/lib/amd64/" >&/dev/null || :
638 done
639 done
640 for i in gdb ld; do
641 sudo cp /usr/bin/$i "/var/lib/chroot/${target}/usr/local/lib/amd64/"
642 sudo sh -c "cat >'/var/lib/chroot/${target}/usr/local/bin/$i'" <<EOF
643 #!/bin/sh
644 exec /lib64/ld-linux-x86-64.so.2 --library-path /usr/local/lib/amd64 \
645 /usr/local/lib/amd64/$i "\$@"
647 sudo chmod 755 "/var/lib/chroot/${target}/usr/local/bin/$i"
648 done
652 # If the install-build-deps.sh script can be found, offer to run it now
653 script="$(dirname $(readlink -f "$0"))/install-build-deps.sh"
654 if [ -x "${script}" ]; then
655 while :; do
656 echo
657 echo "If you plan on building Chrome inside of the new chroot environment,"
658 echo "you now have to install the build dependencies. Do you want me to"
659 printf "start the script that does this for you (y/n)? "
660 read install_deps
661 case "${install_deps}" in
662 y|Y)
663 echo
664 # We prefer running the script in-place, but this might not be
665 # possible, if it lives on a network filesystem that denies
666 # access to root.
667 tmp_script=
668 if ! sudo /usr/local/bin/"${target%bit}" \
669 sh -c "[ -x '${script}' ]" >&/dev/null; then
670 tmp_script="/tmp/${script##*/}"
671 cp "${script}" "${tmp_script}"
673 # Some distributions automatically start an instance of the system-
674 # wide dbus daemon, cron daemon or of the logging daemon, when
675 # installing the Chrome build depencies. This prevents the chroot
676 # session from being closed. So, we always try to shut down any running
677 # instance of dbus and rsyslog.
678 sudo /usr/local/bin/"${target%bit}" sh -c "${script} --no-lib32;
679 rc=$?;
680 /etc/init.d/cron stop >/dev/null 2>&1 || :;
681 /etc/init.d/rsyslog stop >/dev/null 2>&1 || :;
682 /etc/init.d/dbus stop >/dev/null 2>&1 || :;
683 exit $rc"
684 rc=$?
685 [ -n "${tmp_script}" ] && rm -f "${tmp_script}"
686 [ $rc -ne 0 ] && exit $rc
687 break
689 n|N)
690 break
692 esac
693 done
694 echo
697 # Check whether ~/chroot is on a (slow) network file system and offer to
698 # relocate it. Also offer relocation, if the user appears to have multiple
699 # spindles (as indicated by "${bind_mount}" being non-empty).
700 # We only offer this option, if it doesn't look as if a chroot environment
701 # is currently active. Otherwise, relocation is unlikely to work and it
702 # can be difficult for the user to recover from the failed attempt to relocate
703 # the ~/chroot directory.
704 # We don't aim to solve this problem for every configuration,
705 # but try to help with the common cases. For more advanced configuration
706 # options, the user can always manually adjust things.
707 mkdir -p "${HOME}/chroot/"
708 if [ ! -h "${HOME}/chroot" ] &&
709 ! egrep -qs '^[^[:space:]]*/chroot' /etc/fstab &&
710 { [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] ||
711 is_network_drive "${HOME}/chroot"; } &&
712 ! egrep -qs '/var/lib/[^/]*chroot/.*/chroot' /proc/mounts; then
713 echo "${HOME}/chroot is currently located on the same device as your"
714 echo "home directory."
715 echo "This might not be what you want. Do you want me to move it somewhere"
716 echo "else?"
717 # If the computer has multiple spindles, many users configure all or part of
718 # the secondary hard disk to be writable by the primary user of this machine.
719 # Make some reasonable effort to detect this type of configuration and
720 # then offer a good location for where to put the ~/chroot directory.
721 suggest=
722 for i in $(echo "${bind_mounts}"|cut -d ' ' -f 1); do
723 if [ -d "$i" -a -w "$i" -a \( ! -a "$i/chroot" -o -w "$i/chroot/." \) ] &&
724 ! is_network_drive "$i"; then
725 suggest="$i"
726 else
727 for j in "$i/"*; do
728 if [ -d "$j" -a -w "$j" -a \
729 \( ! -a "$j/chroot" -o -w "$j/chroot/." \) ] &&
730 ! is_network_drive "$j"; then
731 suggest="$j"
732 else
733 for k in "$j/"*; do
734 if [ -d "$k" -a -w "$k" -a \
735 \( ! -a "$k/chroot" -o -w "$k/chroot/." \) ] &&
736 ! is_network_drive "$k"; then
737 suggest="$k"
738 break
740 done
742 [ -n "${suggest}" ] && break
743 done
745 [ -n "${suggest}" ] && break
746 done
747 def_suggest="${HOME}"
748 if [ -n "${suggest}" ]; then
749 # For home directories that reside on network drives, make our suggestion
750 # the default option. For home directories that reside on a local drive,
751 # require that the user manually enters the new location.
752 if is_network_drive "${HOME}"; then
753 def_suggest="${suggest}"
754 else
755 echo "A good location would probably be in \"${suggest}\""
758 while :; do
759 printf "Physical location [${def_suggest}]: "
760 read dir
761 [ -z "${dir}" ] && dir="${def_suggest}"
762 [ "${dir%%/}" == "${HOME%%/}" ] && break
763 if ! [ -d "${dir}" -a -w "${dir}" ] ||
764 [ -a "${dir}/chroot" -a ! -w "${dir}/chroot/." ]; then
765 echo "Cannot write to ${dir}/chroot. Please try again"
766 else
767 mv "${HOME}/chroot" "${dir}/chroot"
768 ln -s "${dir}/chroot" "${HOME}/chroot"
769 for i in $(list_all_chroots); do
770 sudo "$i" mkdir -p "${dir}/chroot"
771 done
772 sudo sed -i "s,${HOME}/chroot,${dir}/chroot,g" /etc/schroot/mount-*
773 break
775 done
778 # Clean up package files
779 sudo schroot -c "${target%bit}" -p -- apt-get clean
780 sudo apt-get clean
782 trap '' INT TERM QUIT HUP
783 trap '' EXIT
785 # Let the user know what we did
786 cat <<EOF
789 Successfully installed ${distname} ${arch}
791 You can run programs inside of the chroot by invoking the
792 "/usr/local/bin/${target%bit}" command.
794 This command can be used with arguments, in order to just run a single
795 program inside of the chroot environment (e.g. "${target%bit} make chrome")
796 or without arguments, in order to run an interactive shell session inside
797 of the chroot environment.
799 If you need to run things as "root", you can use "sudo" (e.g. try
800 "sudo ${target%bit} apt-get update").
802 Your home directory is shared between the host and the chroot. But I
803 configured "${HOME}/chroot" to be private to the chroot environment.
804 You can use it for files that need to differ between environments. This
805 would be a good place to store binaries that you have built from your
806 source files.
808 For Chrome, this probably means you want to make your "out" directory a
809 symbolic link that points somewhere inside of "${HOME}/chroot".
811 You still need to run "gclient runhooks" whenever you switch from building
812 outside of the chroot to inside of the chroot. But you will find that you
813 don't have to repeatedly erase and then completely rebuild all your object
814 and binary files.