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 preferred name of the
16 # administrator group.
17 admin
=$
(grep '^admin:' /etc
/group
>&/dev
/null
&& echo admin ||
echo adm
)
20 echo "usage: ${0##*/} [-m mirror] [-g group,...] [-s] [-c]"
21 echo "-b dir additional directories that should be bind mounted,"
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"
34 local OPTNAME OPTIND OPTERR OPTARG
35 while getopts ":b:g:lm:sch" OPTNAME
; do
38 if [ "${OPTARG}" = "NONE" -a -z "${bind_mounts}" ]; then
39 bind_mounts
="${OPTARG}"
41 if [ "${bind_mounts}" = "NONE" -o "${OPTARG}" = "${OPTARG#/}" -o \
42 ! -d "${OPTARG}" ]; then
43 echo "Invalid -b option(s)"
47 bind_mounts
="${bind_mounts}
48 ${OPTARG} ${OPTARG} none rw,bind 0 0"
53 chroot_groups
="${chroot_groups}${chroot_groups:+,}${OPTARG}"
60 if [ -n "${mirror}" ]; then
61 echo "You can only specify exactly one mirror location"
78 echo "'-$OPTARG' needs an argument."
83 echo "invalid command-line option: $OPTARG"
90 if [ $# -ge ${OPTIND} ]; then
91 eval echo "Unexpected command line argument: \${${OPTIND}}"
98 for i
in /var
/lib
/chroot
/*; do
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
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
118 printf "\\$(printf '%03o' "$1")"
122 printf '%d' $
(printf '%c' "$1" |
od -tu1 -An)
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
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."
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.
154 for i
in dchroot debootstrap libwww-perl
; do
155 [ -d /usr
/share
/doc
/"$i" ] || dep
="$dep $i"
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"
174 printf "Which target would you like to install: "
176 [ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev
/null
&& break
178 j
=1; for i
in $targets; do
179 [ "$j" -eq "$n" ] && { distname
="$i"; break; }
184 # On x86-64, ask whether the user wants to install x86-32 or x86-64
187 if [ "$(uname -m)" = x86_64
]; then
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) "
193 [ "${arch}" == 32 -o "${arch}" == 64 ] && break
195 [ "${arch}" == 32 ] && archflag
="--arch i386" || archflag
="--arch amd64"
199 target
="${distname}${arch}"
201 # Don't accidentally overwrite an existing installation
202 [ -d /var
/lib
/chroot
/"${target}" ] && {
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"
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\"."
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)? "
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 "/etc/schroot/${target}"
228 sudo
sed -ni '/^[[]'"${target%bit}"']$/,${
229 :1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
230 "/etc/schroot/schroot.conf"
231 trap '' INT TERM QUIT HUP
239 sudo mkdir
-p /var
/lib
/chroot
/"${target}"
241 # Offer to include additional standard repositories for Ubuntu-based chroots.
243 grep -qs ubuntu.com
/usr
/share
/debootstrap
/scripts
/"${distname}" && {
245 echo "Would you like to add ${distname}-updates and ${distname}-security "
246 printf "to the chroot's sources.list (y/n)? "
248 case "${alt_repos}" in
261 # Check for non-standard file system mount points and ask the user whether
262 # they should be imported into the chroot environment
263 # We limit to the first 26 mount points that much some basic heuristics,
264 # because a) that allows us to enumerate choices with a single character,
265 # and b) if we find more than 26 mount points, then these are probably
266 # false-positives and something is very unusual about the system's
267 # configuration. No need to spam the user with even more information that
268 # is likely completely irrelevant.
269 if [ -z "${bind_mounts}" ]; then
270 mounts
="$(awk '$2 != "/" && $2 !~ "^
/boot
" && $2 !~ "^
/home
" &&
271 $2 !~ "^
/media
" && $2 !~ "^
/run
" &&
272 ($3 ~ "ext
[2-4]" || $3 == "reiserfs
" || $3 == "btrfs
" ||
273 $3 == "xfs
" || $3 == "jfs
" || $3 == "u?msdos
" ||
274 $3 == "v?fat
" || $3 == "hfs
" || $3 == "ntfs
" ||
275 $3 ~ "nfs
[4-9]?
" || $3 == "smbfs
" || $3 == "cifs
") {
279 if [ -n "${mounts}" ]; then
280 echo "You appear to have non-standard mount points that you"
281 echo "might want to import into the chroot environment:"
285 # Print a menu, listing all non-default mounts of local or network
287 j
=1; for m
in ${mounts}; do
288 c
="$(printf $(printf '\\%03o' $((64+$j))))"
289 echo "$sel" |
grep -qs $c &&
290 state
="mounted in chroot" || state
="$(tput el)"
291 printf " $c) %-40s${state}\n" "$m"
294 # Allow user to interactively (de-)select any of the entries
296 printf "Select mount points that you want to be included or press %s" \
298 c
="$(getkey | tr a-z A-Z)"
299 [ "$c" == " " ] && { echo; echo; break; }
301 [ "$c" '<' 'A' -o $
(ord
"$c") -gt $
((64 + $
(ord
"$j"))) ]; then
302 # Invalid input, ring the console bell
305 # Toggle the selection for the given entry
306 if echo "$sel" |
grep -qs $c; then
307 sel
="$(printf "$sel" | sed "s
/$c//")"
312 # Reposition cursor to the top of the list of entries
317 j
=1; for m
in ${mounts}; do
318 c
="$(chr $(($j + 64)))"
319 if echo "$sel" |
grep -qs $c; then
320 bind_mounts
="${bind_mounts}$m $m none rw,bind 0 0
327 # Remove stale entry from /etc/schroot/schroot.conf. Entries start
328 # with the target name in square brackets, followed by an arbitrary
329 # number of lines. The entry stops when either the end of file has
330 # been reached, or when the beginning of a new target is encountered.
331 # This means, we cannot easily match for a range of lines in
332 # "sed". Instead, we actually have to iterate over each line and check
333 # whether it is the beginning of a new entry.
334 sudo
sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
335 /etc
/schroot
/schroot.conf
337 # Download base system. This takes some time
338 if [ -z "${mirror}" ]; then
339 grep -qs ubuntu.com
/usr
/share
/debootstrap
/scripts
/"${distname}" &&
340 mirror
="http://archive.ubuntu.com/ubuntu" ||
341 mirror
="http://ftp.us.debian.org/debian"
344 sudo
${http_proxy:+http_proxy="${http_proxy}"} debootstrap
${archflag} \
345 "${distname}" "/var/lib/chroot/${target}" "$mirror"
347 # Add new entry to /etc/schroot/schroot.conf
348 grep -qs ubuntu.com
/usr
/share
/debootstrap
/scripts
/"${distname}" &&
349 brand
="Ubuntu" || brand
="Debian"
350 if [ -z "${chroot_groups}" ]; then
351 chroot_groups
="${admin},$(id -gn)"
354 if [ -d '/etc/schroot/default' ]; then
356 fstab
="/etc/schroot/${target}/fstab"
359 fstab
="/etc/schroot/mount-${target}"
362 if [ "$new_version" = "1" ]; then
363 sudo
cp -ar /etc
/schroot
/default
/etc
/schroot
/${target}
365 sudo sh
-c 'cat >>/etc/schroot/schroot.conf' <<EOF
367 description=${brand} ${distname} ${arch}
369 directory=/var/lib/chroot/${target}
371 groups=${chroot_groups}
372 root-groups=${chroot_groups}
373 personality=linux$([ "${arch}" != 64bit ] && echo 32)
377 [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] &&
378 printf "${bind_mounts}" |
379 sudo sh
-c "cat >>${fstab}"
381 # Older versions of schroot wanted a "priority=" line, whereas recent
382 # versions deprecate "priority=" and warn if they see it. We don't have
383 # a good feature test, but scanning for the string "priority=" in the
384 # existing "schroot.conf" file is a good indication of what to do.
385 priority
=$
(grep -qs 'priority=' /etc
/schroot
/schroot.conf
&&
386 echo 'priority=3' ||
:)
387 sudo sh
-c 'cat >>/etc/schroot/schroot.conf' <<EOF
389 description=${brand} ${distname} ${arch}
391 directory=/var/lib/chroot/${target}
393 groups=${chroot_groups}
394 root-groups=${chroot_groups}
395 personality=linux$([ "${arch}" != 64bit ] && echo 32)
396 script-config=script-${target}
401 # Set up a list of mount points that is specific to this
402 # chroot environment.
403 sed '/^FSTAB=/s,"[^"]*","'"${fstab}"'",' \
404 /etc
/schroot
/script-defaults |
405 sudo sh
-c 'cat >/etc/schroot/script-'"${target}"
406 sed '\,^/home[/[:space:]],s/\([,[:space:]]\)bind[[:space:]]/\1rbind /' \
407 /etc
/schroot
/mount-defaults |
408 sudo sh
-c "cat > ${fstab}"
411 # Add the extra mount points that the user told us about
412 [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] &&
413 printf "${bind_mounts}" |
414 sudo sh
-c 'cat >>'"${fstab}"
416 # If this system has a "/media" mountpoint, import it into the chroot
417 # environment. Most modern distributions use this mount point to
418 # automatically mount devices such as CDROMs, USB sticks, etc...
420 ! grep -qs '^/media' "${fstab}"; then
421 echo '/media /media none rw,rbind 0 0' |
422 sudo sh
-c 'cat >>'"${fstab}"
425 # Share /dev/shm, /run and /run/shm.
426 grep -qs '^/dev/shm' "${fstab}" ||
427 echo '/dev/shm /dev/shm none rw,bind 0 0' |
428 sudo sh
-c 'cat >>'"${fstab}"
429 if [ ! -d "/var/lib/chroot/${target}/run" ] &&
430 ! grep -qs '^/run' "${fstab}"; then
431 echo '/run /run none rw,bind 0 0' |
432 sudo sh
-c 'cat >>'"${fstab}"
434 if ! grep -qs '^/run/shm' "${fstab}"; then
435 { [ -d /run
] && echo '/run/shm /run/shm none rw,bind 0 0' ||
436 echo '/dev/shm /run/shm none rw,bind 0 0'; } |
437 sudo sh
-c 'cat >>'"${fstab}"
440 # Set up a special directory that changes contents depending on the target
442 d
="$(readlink -f "${HOME}/chroot
" 2>/dev/null || echo "${HOME}/chroot
")"
444 echo "${s} ${d} none rw,bind 0 0" |
445 sudo sh
-c 'cat >>'"${target}"
448 # Install a helper script to launch commands in the chroot
449 sudo sh
-c 'cat >/usr/local/bin/'"${target%bit}" <<'EOF'
455 # Word-wrap the text passed-in on stdin. Optionally, on continuation lines
456 # insert the same number of spaces as the number of characters in the
457 # parameter(s) passed to this function.
458 # If the "fold" program cannot be found, or if the actual width of the
459 # terminal cannot be determined, this function doesn't attempt to do any
461 local f="$(type -P fold)"
462 [ -z "${f}" ] && { cat; return; }
463 local c="$(stty -a </dev/tty 2>/dev/null |
464 sed 's/.*columns[[:space:]]*\([0-9]*\).*/\1/;t;d')"
465 [ -z "${c}" ] && { cat; return; }
466 local i="$(echo "$*"|sed 's/./ /g')"
467 local j="$(printf %s "${i}"|wc -c)"
468 if [ "${c}" -gt "${j}" ]; then
469 dd bs=1 count="${j}" 2>/dev/null
470 "${f}" -sw "$((${c}-${j}))" | sed '2,$s/^/'"${i}"'/'
477 echo "Usage ${0##*/} [-h|--help] [-c|--clean] [-C|--clean-all] [-l|--list] [--] args" | wrap "Usage ${0##*/} "
478 echo " help: print this message" | wrap " "
479 echo " list: list all known chroot environments" | wrap " "
480 echo " clean: remove all old chroot sessions for \"${chroot}\"" | wrap " "
481 echo " clean-all: remove all old chroot sessions for all environments" | wrap " "
488 for s in $(schroot -l --all-sessions); do
491 [ "${t#${chroot}-}" == "${t}" ] && continue
493 if ls -l /proc/*/{cwd,fd} 2>/dev/null |
494 fgrep -qs "/var/lib/schroot/mount/${t}"; then
495 echo "Session \"${t}\" still has active users, not cleaning up" | wrap
499 sudo schroot -c "${s}" -e || rc=1
505 for e in $(schroot -l); do
507 [ -x "/usr/local/bin/${e}" ] || continue
508 if schroot -l --all-sessions 2>/dev/null |
509 sed 's/^session://' |
510 grep -qs "^${e}-"; then
511 echo "${e} is currently active"
519 while [ "$#" -ne 0 ]; do
522 -h|--help) shift; help;;
523 -l|--list) shift; list;;
524 -c|--clean) shift; clean "${chroot}";;
525 -C|--clean-all) shift; clean;;
530 # Start a new chroot session and keep track of the session id. We inject this
531 # id into all processes that run inside the chroot. Unless they go out of their
532 # way to clear their environment, we can then later identify our child and
533 # grand-child processes by scanning their environment.
534 session="$(schroot -c "${chroot}" -b)"
535 export CHROOT_SESSION_ID="${session}"
537 # Set GOMA_TMP_DIR for better handling of goma inside chroot.
538 export GOMA_TMP_DIR="/tmp/goma_tmp_$CHROOT_SESSION_ID"
539 mkdir -p "$GOMA_TMP_DIR"
541 if [ $# -eq 0 ]; then
542 # Run an interactive shell session
543 schroot -c "${session}" -r -p
545 # Run a command inside of the chroot environment
547 schroot -c "${session}" -r -p "$p" -- "$@"
551 # Compute the inode of the root directory inside of the chroot environment.
552 i=$(schroot -c "${session}" -r -p ls -- -id /proc/self/root/. |
553 awk '{ print $1 }') 2>/dev/null
555 while [ -n "$i" ]; do
556 # Identify processes by the inode number of their root directory. Then
557 # remove all processes that we know belong to other sessions. We use
558 # "sort | uniq -u" to do what amounts to a "set substraction operation".
559 pids=$({ ls -id1 /proc/*/root/. 2>/dev/null |
560 sed -e 's,^[^0-9]*'$i'.*/\([1-9][0-9]*\)/.*$,\1,
563 echo "${other_pids}";
564 echo "${other_pids}"; } | sort | uniq -u) >/dev/null 2>&1
565 # Kill all processes that are still left running in the session. This is
566 # typically an assortment of daemon processes that were started
567 # automatically. They result in us being unable to tear down the session
569 [ -z "${pids}" ] && break
571 # Unfortunately, the way that schroot sets up sessions has the
572 # side-effect of being unable to tell one session apart from another.
573 # This can result in us attempting to kill processes in other sessions.
574 # We make a best-effort to avoid doing so.
575 k="$( ( xargs -0 -n1 </proc/$j/environ ) 2>/dev/null |
576 sed 's/^CHROOT_SESSION_ID=/x/;t1;d;:1;q')"
577 if [ -n "${k}" -a "${k#x}" != "${session}" ]; then
578 other_pids="${other_pids}
585 # End the chroot session. This should clean up all temporary files. But if we
586 # earlier failed to terminate all (daemon) processes inside of the session,
587 # deleting the session could fail. When that happens, the user has to manually
588 # clean up the stale files by invoking us with "--clean" after having killed
589 # all running processes.
590 schroot -c "${session}" -e
591 # Since no goma processes are running, we can remove goma directory.
592 rm -rf "$GOMA_TMP_DIR"
595 sudo chown root
:root
/usr
/local
/bin
/"${target%bit}"
596 sudo
chmod 755 /usr
/local
/bin
/"${target%bit}"
598 # Add the standard Ubuntu update repositories if requested.
599 [ "${alt_repos}" = "y" -a \
600 -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
601 sudo
sed -i '/^deb .* [^ -]\+ main$/p
602 s/^\(deb .* [^ -]\+\) main/\1-security main/
606 :1;s/-security main/-updates main/
608 d' "/var/lib/chroot/${target}/etc/apt/sources.list"
610 # Add a few more repositories to the chroot
611 [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
612 sudo
sed -i 's/ main$/ main restricted universe multiverse/' \
613 "/var/lib/chroot/${target}/etc/apt/sources.list"
615 # Add the Ubuntu "partner" repository, if available
616 if [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
617 HEAD
"http://archive.canonical.com/ubuntu/dists/${distname}/partner" \
620 echo "deb http://archive.canonical.com/ubuntu" \
621 "'"${distname}"' partner" \
622 >>"/var/lib/chroot/'"${target}"'/etc/apt/sources.list"'
625 # Add source repositories, if the user requested we do so
626 [ "${add_srcs}" = "y" -a \
627 -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
628 sudo
sed -i '/^deb[^-]/p
629 s/^deb\([^-]\)/deb-src\1/' \
630 "/var/lib/chroot/${target}/etc/apt/sources.list"
632 # Set apt proxy if host has set http_proxy
633 if [ -n "${http_proxy}" ]; then
635 echo "Acquire::http::proxy \"'"${http_proxy}"'\";" \
636 >>"/var/lib/chroot/'"${target}"'/etc/apt/apt.conf"'
640 sudo
"/usr/local/bin/${target%bit}" /bin
/sh
-c '
641 apt-get update; apt-get -y dist-upgrade' ||
:
643 # Install a couple of missing packages
644 for i
in debian-keyring ubuntu-keyring locales sudo
; do
645 [ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] ||
646 sudo
"/usr/local/bin/${target%bit}" apt-get
-y install "$i" ||
:
650 sudo
"/usr/local/bin/${target%bit}" /bin
/sh
-c '
651 l='"${LANG:-en_US}"'; l="${l%%.*}"
652 [ -r /etc/locale.gen ] &&
653 sed -i "s/^# \($l\)/\1/" /etc/locale.gen
654 locale-gen $LANG en_US en_US.UTF-8' ||
:
656 # Enable multi-arch support, if available
657 sudo
"/usr/local/bin/${target%bit}" dpkg
--assert-multi-arch >&/dev
/null
&&
658 [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && {
659 sudo
sed -i 's/ / [arch=amd64,i386] /' \
660 "/var/lib/chroot/${target}/etc/apt/sources.list"
661 [ -d /var
/lib
/chroot
/${target}/etc
/dpkg
/dpkg.cfg.d
/ ] &&
662 sudo
"/usr/local/bin/${target%bit}" dpkg
--add-architecture \
663 $
([ "${arch}" = "32bit" ] && echo amd64 ||
echo i386
) >&/dev
/null ||
664 echo foreign-architecture \
665 $
([ "${arch}" = "32bit" ] && echo amd64 ||
echo i386
) |
667 "cat >'/var/lib/chroot/${target}/etc/dpkg/dpkg.cfg.d/multiarch'"
670 # Configure "sudo" package
671 sudo
"/usr/local/bin/${target%bit}" /bin
/sh
-c '
672 egrep -qs '"'^$(id -nu) '"' /etc/sudoers ||
673 echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers'
675 # Install a few more commonly used packages
676 sudo
"/usr/local/bin/${target%bit}" apt-get
-y install \
677 autoconf automake1.9 dpkg-dev g
++-multilib gcc-multilib gdb
less libtool \
680 # If running a 32bit environment on a 64bit machine, install a few binaries
681 # as 64bit. This is only done automatically if the chroot distro is the same as
682 # the host, otherwise there might be incompatibilities in build settings or
683 # runtime dependencies. The user can force it with the '-c' flag.
684 host_distro
=$
(grep -s DISTRIB_CODENAME
/etc
/lsb-release | \
686 if [ "${copy_64}" = "y" -o \
687 "${host_distro}" = "${distname}" -a "${arch}" = 32bit
] && \
688 file /bin
/bash
2>/dev
/null |
grep -q x86-64
; then
689 readlinepkg
=$
(sudo
"/usr/local/bin/${target%bit}" sh
-c \
690 'apt-cache search "lib64readline.\$" | sort | tail -n 1 | cut -d " " -f 1')
691 sudo
"/usr/local/bin/${target%bit}" apt-get
-y install \
692 lib64expat1 lib64ncurses5
${readlinepkg} lib64z1 lib64stdc
++6
694 for i
in binutils gdb
; do
695 [ -d /usr
/share
/doc
/"$i" ] || dep
="$dep $i"
697 [ -n "$dep" ] && sudo apt-get
-y install $dep
698 sudo mkdir
-p "/var/lib/chroot/${target}/usr/local/lib/amd64"
699 for i
in libbfd libpython
; do
700 lib
="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } |
701 grep -s "$i" | awk '{ print $3 }')"
702 if [ -n "$lib" -a -r "$lib" ]; then
703 sudo
cp "$lib" "/var/lib/chroot/${target}/usr/local/lib/amd64"
706 for lib
in libssl libcrypt
; do
707 for path
in /usr
/lib
/usr
/lib
/x86_64-linux-gnu
; do
708 sudo
cp $path/$lib* \
709 "/var/lib/chroot/${target}/usr/local/lib/amd64/" >&/dev
/null ||
:
713 sudo
cp /usr
/bin
/$i "/var/lib/chroot/${target}/usr/local/lib/amd64/"
714 sudo sh
-c "cat >'/var/lib/chroot/${target}/usr/local/bin/$i'" <<EOF
716 exec /lib64/ld-linux-x86-64.so.2 --library-path /usr/local/lib/amd64 \
717 /usr/local/lib/amd64/$i "\$@"
719 sudo
chmod 755 "/var/lib/chroot/${target}/usr/local/bin/$i"
724 # If the install-build-deps.sh script can be found, offer to run it now
725 script="$(dirname $(readlink -f "$0"))/install-build-deps.sh"
726 if [ -x "${script}" ]; then
729 echo "If you plan on building Chrome inside of the new chroot environment,"
730 echo "you now have to install the build dependencies. Do you want me to"
731 printf "start the script that does this for you (y/n)? "
733 case "${install_deps}" in
736 # We prefer running the script in-place, but this might not be
737 # possible, if it lives on a network filesystem that denies
740 if ! sudo
/usr
/local
/bin
/"${target%bit}" \
741 sh
-c "[ -x '${script}' ]" >&/dev
/null
; then
742 tmp_script
="/tmp/${script##*/}"
743 cp "${script}" "${tmp_script}"
745 # Some distributions automatically start an instance of the system-
746 # wide dbus daemon, cron daemon or of the logging daemon, when
747 # installing the Chrome build depencies. This prevents the chroot
748 # session from being closed. So, we always try to shut down any running
749 # instance of dbus and rsyslog.
750 sudo
/usr
/local
/bin
/"${target%bit}" sh
-c "${script};
752 /etc/init.d/cron stop >/dev/null 2>&1 || :;
753 /etc/init.d/rsyslog stop >/dev/null 2>&1 || :;
754 /etc/init.d/dbus stop >/dev/null 2>&1 || :;
757 [ -n "${tmp_script}" ] && rm -f "${tmp_script}"
758 [ $rc -ne 0 ] && exit $rc
769 # Check whether ~/chroot is on a (slow) network file system and offer to
770 # relocate it. Also offer relocation, if the user appears to have multiple
771 # spindles (as indicated by "${bind_mount}" being non-empty).
772 # We only offer this option, if it doesn't look as if a chroot environment
773 # is currently active. Otherwise, relocation is unlikely to work and it
774 # can be difficult for the user to recover from the failed attempt to relocate
775 # the ~/chroot directory.
776 # We don't aim to solve this problem for every configuration,
777 # but try to help with the common cases. For more advanced configuration
778 # options, the user can always manually adjust things.
779 mkdir
-p "${HOME}/chroot/"
780 if [ ! -h "${HOME}/chroot" ] &&
781 ! egrep -qs '^[^[:space:]]*/chroot' /etc
/fstab
&&
782 { [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] ||
783 is_network_drive
"${HOME}/chroot"; } &&
784 ! egrep -qs '/var/lib/[^/]*chroot/.*/chroot' /proc
/mounts
; then
785 echo "${HOME}/chroot is currently located on the same device as your"
786 echo "home directory."
787 echo "This might not be what you want. Do you want me to move it somewhere"
789 # If the computer has multiple spindles, many users configure all or part of
790 # the secondary hard disk to be writable by the primary user of this machine.
791 # Make some reasonable effort to detect this type of configuration and
792 # then offer a good location for where to put the ~/chroot directory.
794 for i
in $
(echo "${bind_mounts}"|cut
-d ' ' -f 1); do
795 if [ -d "$i" -a -w "$i" -a \
( ! -a "$i/chroot" -o -w "$i/chroot/." \
) ] &&
796 ! is_network_drive
"$i"; then
800 if [ -d "$j" -a -w "$j" -a \
801 \
( ! -a "$j/chroot" -o -w "$j/chroot/." \
) ] &&
802 ! is_network_drive
"$j"; then
806 if [ -d "$k" -a -w "$k" -a \
807 \
( ! -a "$k/chroot" -o -w "$k/chroot/." \
) ] &&
808 ! is_network_drive
"$k"; then
814 [ -n "${suggest}" ] && break
817 [ -n "${suggest}" ] && break
819 def_suggest
="${HOME}"
820 if [ -n "${suggest}" ]; then
821 # For home directories that reside on network drives, make our suggestion
822 # the default option. For home directories that reside on a local drive,
823 # require that the user manually enters the new location.
824 if is_network_drive
"${HOME}"; then
825 def_suggest
="${suggest}"
827 echo "A good location would probably be in \"${suggest}\""
831 printf "Physical location [${def_suggest}]: "
833 [ -z "${dir}" ] && dir
="${def_suggest}"
834 [ "${dir%%/}" == "${HOME%%/}" ] && break
835 if ! [ -d "${dir}" -a -w "${dir}" ] ||
836 [ -a "${dir}/chroot" -a ! -w "${dir}/chroot/." ]; then
837 echo "Cannot write to ${dir}/chroot. Please try again"
839 mv "${HOME}/chroot" "${dir}/chroot"
840 ln -s "${dir}/chroot" "${HOME}/chroot"
841 for i
in $
(list_all_chroots
); do
842 sudo
"$i" mkdir
-p "${dir}/chroot"
844 sudo
sed -i "s,${HOME}/chroot,${dir}/chroot,g" /etc
/schroot
/mount-
*
850 # Clean up package files
851 sudo schroot
-c "${target%bit}" -p -- apt-get clean
854 trap '' INT TERM QUIT HUP
857 # Let the user know what we did
861 Successfully installed ${distname} ${arch}
863 You can run programs inside of the chroot by invoking the
864 "/usr/local/bin/${target%bit}" command.
866 This command can be used with arguments, in order to just run a single
867 program inside of the chroot environment (e.g. "${target%bit} make chrome")
868 or without arguments, in order to run an interactive shell session inside
869 of the chroot environment.
871 If you need to run things as "root", you can use "sudo" (e.g. try
872 "sudo ${target%bit} apt-get update").
874 Your home directory is shared between the host and the chroot. But I
875 configured "${HOME}/chroot" to be private to the chroot environment.
876 You can use it for files that need to differ between environments. This
877 would be a good place to store binaries that you have built from your
880 For Chrome, this probably means you want to make your "out" directory a
881 symbolic link that points somewhere inside of "${HOME}/chroot".
883 You still need to run "gclient runhooks" whenever you switch from building
884 outside of the chroot to inside of the chroot. But you will find that you
885 don't have to repeatedly erase and then completely rebuild all your object