Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(928)

Side by Side Diff: build/install-chroot.sh

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

Powered by Google App Engine
This is Rietveld 408576698