1#!/bin/bash -e 2 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. 6 7# Script to install everything needed to build chromium (well, ideally, anyway) 8# See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md 9 10usage() { 11 echo "Usage: $0 [--options]" 12 echo "Options:" 13 echo "--[no-]syms: enable or disable installation of debugging symbols" 14 echo "--lib32: enable installation of 32-bit libraries, e.g. for V8 snapshot" 15 echo "--[no-]arm: enable or disable installation of arm cross toolchain" 16 echo "--[no-]chromeos-fonts: enable or disable installation of Chrome OS"\ 17 "fonts" 18 echo "--[no-]nacl: enable or disable installation of prerequisites for"\ 19 "building standalone NaCl and all its toolchains" 20 echo "--no-prompt: silently select standard options/defaults" 21 echo "--quick-check: quickly try to determine if dependencies are installed" 22 echo " (this avoids interactive prompts and sudo commands," 23 echo " so might not be 100% accurate)" 24 echo "--unsupported: attempt installation even on unsupported systems" 25 echo "Script will prompt interactively if options not given." 26 exit 1 27} 28 29# Waits for the user to press 'Y' or 'N'. Either uppercase of lowercase is 30# accepted. Returns 0 for 'Y' and 1 for 'N'. If an optional parameter has 31# been provided to yes_no(), the function also accepts RETURN as a user input. 32# The parameter specifies the exit code that should be returned in that case. 33# The function will echo the user's selection followed by a newline character. 34# Users can abort the function by pressing CTRL-C. This will call "exit 1". 35yes_no() { 36 if [ 0 -ne "${do_default-0}" ] ; then 37 [ $1 -eq 0 ] && echo "Y" || echo "N" 38 return $1 39 fi 40 local c 41 while :; do 42 c="$(trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT 43 stty -echo iuclc -icanon 2>/dev/null 44 dd count=1 bs=1 2>/dev/null | od -An -tx1)" 45 case "$c" in 46 " 0a") if [ -n "$1" ]; then 47 [ $1 -eq 0 ] && echo "Y" || echo "N" 48 return $1 49 fi 50 ;; 51 " 79") echo "Y" 52 return 0 53 ;; 54 " 6e") echo "N" 55 return 1 56 ;; 57 "") echo "Aborted" >&2 58 exit 1 59 ;; 60 *) # The user pressed an unrecognized key. As we are not echoing 61 # any incorrect user input, alert the user by ringing the bell. 62 (tput bel) 2>/dev/null 63 ;; 64 esac 65 done 66} 67 68# Checks whether a particular package is available in the repos. 69# USAGE: $ package_exists <package name> 70package_exists() { 71 [ ! -z "`apt-cache search --names-only "$1"`" ] 72} 73 74# These default to on because (some) bots need them and it keeps things 75# simple for the bot setup if all bots just run the script in its default 76# mode. Developers who don't want stuff they don't need installed on their 77# own workstations can pass --no-arm --no-nacl when running the script. 78do_inst_arm=1 79do_inst_nacl=1 80 81while test "$1" != "" 82do 83 case "$1" in 84 --syms) do_inst_syms=1;; 85 --no-syms) do_inst_syms=0;; 86 --lib32) do_inst_lib32=1;; 87 --arm) do_inst_arm=1;; 88 --no-arm) do_inst_arm=0;; 89 --chromeos-fonts) do_inst_chromeos_fonts=1;; 90 --no-chromeos-fonts) do_inst_chromeos_fonts=0;; 91 --nacl) do_inst_nacl=1;; 92 --no-nacl) do_inst_nacl=0;; 93 --no-prompt) do_default=1 94 do_quietly="-qq --assume-yes" 95 ;; 96 --quick-check) do_quick_check=1;; 97 --unsupported) do_unsupported=1;; 98 *) usage;; 99 esac 100 shift 101done 102 103if test "$do_inst_arm" = "1"; then 104 do_inst_lib32=1 105fi 106 107# Check for lsb_release command in $PATH 108if ! which lsb_release > /dev/null; then 109 echo "ERROR: lsb_release not found in \$PATH" >&2 110 exit 1; 111fi 112 113distro_codename=$(lsb_release --codename --short) 114distro_id=$(lsb_release --id --short) 115supported_codenames="(trusty|xenial|yakkety)" 116supported_ids="(Debian)" 117if [ 0 -eq "${do_unsupported-0}" ] && [ 0 -eq "${do_quick_check-0}" ] ; then 118 if [[ ! $distro_codename =~ $supported_codenames && 119 ! $distro_id =~ $supported_ids ]]; then 120 echo -e "ERROR: The only supported distros are\n" \ 121 "\tUbuntu 14.04 (trusty)\n" \ 122 "\tUbuntu 16.04 (xenial)\n" \ 123 "\tUbuntu 16.10 (yakkety)\n" \ 124 "\tDebian 8 (jessie) or later" >&2 125 exit 1 126 fi 127 128 if ! uname -m | egrep -q "i686|x86_64"; then 129 echo "Only x86 architectures are currently supported" >&2 130 exit 131 fi 132fi 133 134if [ "x$(id -u)" != x0 ] && [ 0 -eq "${do_quick_check-0}" ]; then 135 echo "Running as non-root user." 136 echo "You might have to enter your password one or more times for 'sudo'." 137 echo 138fi 139 140# Packages needed for chromeos only 141chromeos_dev_list="libbluetooth-dev libxkbcommon-dev realpath" 142 143# Packages needed for development 144dev_list="\ 145 bison 146 cdbs 147 curl 148 dpkg-dev 149 elfutils 150 devscripts 151 fakeroot 152 flex 153 fonts-ipafont 154 fonts-thai-tlwg 155 g++ 156 git-core 157 git-svn 158 gperf 159 libasound2-dev 160 libbrlapi-dev 161 libav-tools 162 libbz2-dev 163 libcairo2-dev 164 libcap-dev 165 libcups2-dev 166 libcurl4-gnutls-dev 167 libdrm-dev 168 libelf-dev 169 libffi-dev 170 libgconf2-dev 171 libglib2.0-dev 172 libglu1-mesa-dev 173 libgnome-keyring-dev 174 libgtk2.0-dev 175 libgtk-3-dev 176 libkrb5-dev 177 libnspr4-dev 178 libnss3-dev 179 libpam0g-dev 180 libpci-dev 181 libpulse-dev 182 libsctp-dev 183 libspeechd-dev 184 libsqlite3-dev 185 libssl-dev 186 libudev-dev 187 libwww-perl 188 libxslt1-dev 189 libxss-dev 190 libxt-dev 191 libxtst-dev 192 openbox 193 patch 194 perl 195 pkg-config 196 python 197 python-cherrypy3 198 python-crypto 199 python-dev 200 python-numpy 201 python-opencv 202 python-openssl 203 python-psutil 204 python-yaml 205 rpm 206 ruby 207 subversion 208 ttf-dejavu-core 209 wdiff 210 xcompmgr 211 zip 212 $chromeos_dev_list 213" 214 215# 64-bit systems need a minimum set of 32-bit compat packages for the pre-built 216# NaCl binaries. 217if file -L /sbin/init | grep -q 'ELF 64-bit'; then 218 dev_list="${dev_list} libc6-i386 lib32gcc1 lib32stdc++6" 219fi 220 221# Run-time libraries required by chromeos only 222chromeos_lib_list="libpulse0 libbz2-1.0" 223 224# Full list of required run-time libraries 225lib_list="\ 226 libatk1.0-0 227 libc6 228 libasound2 229 libcairo2 230 libcap2 231 libcups2 232 libexpat1 233 libffi6 234 libfontconfig1 235 libfreetype6 236 libglib2.0-0 237 libgnome-keyring0 238 libgtk2.0-0 239 libgtk-3-0 240 libpam0g 241 libpango1.0-0 242 libpci3 243 libpcre3 244 libpixman-1-0 245 libspeechd2 246 libstdc++6 247 libsqlite3-0 248 libx11-6 249 libx11-xcb1 250 libxau6 251 libxcb1 252 libxcomposite1 253 libxcursor1 254 libxdamage1 255 libxdmcp6 256 libxext6 257 libxfixes3 258 libxi6 259 libxinerama1 260 libxrandr2 261 libxrender1 262 libxtst6 263 zlib1g 264 $chromeos_lib_list 265" 266 267# Debugging symbols for all of the run-time libraries 268dbg_list="\ 269 libatk1.0-dbg 270 libc6-dbg 271 libcairo2-dbg 272 libffi6-dbg 273 libfontconfig1-dbg 274 libglib2.0-0-dbg 275 libgtk2.0-0-dbg 276 libgtk-3-0-dbg 277 libpango1.0-0-dbg 278 libpcre3-dbg 279 libpixman-1-0-dbg 280 libsqlite3-0-dbg 281 libx11-6-dbg 282 libx11-xcb1-dbg 283 libxau6-dbg 284 libxcb1-dbg 285 libxcomposite1-dbg 286 libxcursor1-dbg 287 libxdamage1-dbg 288 libxdmcp6-dbg 289 libxext6-dbg 290 libxi6-dbg 291 libxinerama1-dbg 292 libxrandr2-dbg 293 libxrender1-dbg 294 libxtst6-dbg 295 zlib1g-dbg 296" 297 298if [[ ! $distro_codename =~ "yakkety" ]]; then 299 dbg_list="${dbg_list} libxfixes3-dbg" 300fi 301 302# Find the proper version of libstdc++6-4.x-dbg. 303if [ "x$distro_codename" = "xtrusty" ]; then 304 dbg_list="${dbg_list} libstdc++6-4.8-dbg" 305else 306 dbg_list="${dbg_list} libstdc++6-4.9-dbg" 307fi 308 309# 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf 310lib32_list="linux-libc-dev:i386" 311 312# arm cross toolchain packages needed to build chrome on armhf 313EM_REPO="deb http://emdebian.org/tools/debian/ jessie main" 314EM_SOURCE=$(cat <<EOF 315# Repo added by Chromium $0 316${EM_REPO} 317# deb-src http://emdebian.org/tools/debian/ jessie main 318EOF 319) 320EM_ARCHIVE_KEY_FINGER="084C6C6F39159EDB67969AA87DE089671804772E" 321GPP_ARM_PACKAGE="g++-arm-linux-gnueabihf" 322case $distro_codename in 323 jessie) 324 eval $(apt-config shell APT_SOURCESDIR 'Dir::Etc::sourceparts/d') 325 CROSSTOOLS_LIST="${APT_SOURCESDIR}/crosstools.list" 326 arm_list="libc6-dev:armhf 327 linux-libc-dev:armhf" 328 if test "$do_inst_arm" = "1"; then 329 if $(dpkg-query -W ${GPP_ARM_PACKAGE} &>/dev/null); then 330 arm_list+=" ${GPP_ARM_PACKAGE}" 331 else 332 echo "The Debian Cross-toolchains repository is necessary to" 333 echo "cross-compile Chromium for arm." 334 echo -n "Do you want me to add it for you (y/N) " 335 if yes_no 1; then 336 gpg --keyserver pgp.mit.edu --recv-keys ${EM_ARCHIVE_KEY_FINGER} 337 gpg -a --export ${EM_ARCHIVE_KEY_FINGER} | sudo apt-key add - 338 if ! grep "^${EM_REPO}" "${CROSSTOOLS_LIST}" &>/dev/null; then 339 echo "${EM_SOURCE}" | sudo tee -a "${CROSSTOOLS_LIST}" >/dev/null 340 fi 341 arm_list+=" ${GPP_ARM_PACKAGE}" 342 fi 343 fi 344 fi 345 ;; 346 # All necessary ARM packages are available on the default repos on 347 # Debian 9 and later. 348 *) 349 arm_list="binutils-aarch64-linux-gnu 350 libc6-dev-armhf-cross 351 linux-libc-dev-armhf-cross 352 ${GPP_ARM_PACKAGE}" 353 ;; 354esac 355 356# Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056 357case $distro_codename in 358 trusty) 359 arm_list+=" g++-4.8-multilib-arm-linux-gnueabihf 360 gcc-4.8-multilib-arm-linux-gnueabihf" 361 ;; 362 xenial|yakkety) 363 arm_list+=" g++-5-multilib-arm-linux-gnueabihf 364 gcc-5-multilib-arm-linux-gnueabihf 365 gcc-arm-linux-gnueabihf" 366 ;; 367esac 368 369# Packages to build NaCl, its toolchains, and its ports. 370naclports_list="ant autoconf bison cmake gawk intltool xutils-dev xsltproc" 371nacl_list="\ 372 g++-mingw-w64-i686 373 lib32z1-dev 374 libasound2:i386 375 libcap2:i386 376 libelf-dev:i386 377 libfontconfig1:i386 378 libgconf-2-4:i386 379 libglib2.0-0:i386 380 libgpm2:i386 381 libgtk2.0-0:i386 382 libgtk-3-0:i386 383 libncurses5:i386 384 lib32ncurses5-dev 385 libnss3:i386 386 libpango1.0-0:i386 387 libssl-dev:i386 388 libtinfo-dev 389 libtinfo-dev:i386 390 libtool 391 libxcomposite1:i386 392 libxcursor1:i386 393 libxdamage1:i386 394 libxi6:i386 395 libxrandr2:i386 396 libxss1:i386 397 libxtst6:i386 398 texinfo 399 xvfb 400 ${naclports_list} 401" 402 403if package_exists libssl1.0.0; then 404 nacl_list="${nacl_list} libssl1.0.0:i386" 405else 406 nacl_list="${nacl_list} libssl1.0.2:i386" 407fi 408 409# Find the proper version of packages that depend on mesa. Only one -lts variant 410# of mesa can be installed and everything that depends on it must match. 411 412# Query for the name and status of all mesa LTS variants, filter for only 413# installed packages, extract just the name, and eliminate duplicates (there can 414# be more than one with the same name in the case of multiarch). Expand into an 415# array. 416mesa_packages=($(dpkg-query -Wf'${package} ${status}\n' \ 417 libgl1-mesa-glx-lts-\* 2>/dev/null | \ 418 grep " ok installed" | cut -d " " -f 1 | sort -u)) 419if [ "${#mesa_packages[@]}" -eq 0 ]; then 420 mesa_variant="" 421elif [ "${#mesa_packages[@]}" -eq 1 ]; then 422 # Strip the base package name and leave just "-lts-whatever" 423 mesa_variant="${mesa_packages[0]#libgl1-mesa-glx}" 424else 425 echo "ERROR: unable to determine which libgl1-mesa-glx variant is installed." 426 exit 1 427fi 428dev_list="${dev_list} libgbm-dev${mesa_variant} 429 libgles2-mesa-dev${mesa_variant} libgl1-mesa-dev${mesa_variant} 430 mesa-common-dev${mesa_variant}" 431nacl_list="${nacl_list} libgl1-mesa-glx${mesa_variant}:i386" 432 433# Some package names have changed over time 434if package_exists libpng12-0; then 435 lib_list="${lib_list} libpng12-0" 436else 437 lib_list="${lib_list} libpng16-16" 438fi 439if package_exists libnspr4-dbg; then 440 dbg_list="${dbg_list} libnspr4-dbg libnss3-dbg" 441 lib_list="${lib_list} libnspr4 libnss3" 442else 443 dbg_list="${dbg_list} libnspr4-0d-dbg libnss3-1d-dbg" 444 lib_list="${lib_list} libnspr4-0d libnss3-1d" 445fi 446if package_exists libjpeg-dev; then 447 dev_list="${dev_list} libjpeg-dev" 448else 449 dev_list="${dev_list} libjpeg62-dev" 450fi 451if package_exists libudev1; then 452 dev_list="${dev_list} libudev1" 453 nacl_list="${nacl_list} libudev1:i386" 454else 455 dev_list="${dev_list} libudev0" 456 nacl_list="${nacl_list} libudev0:i386" 457fi 458if package_exists libbrlapi0.6; then 459 dev_list="${dev_list} libbrlapi0.6" 460else 461 dev_list="${dev_list} libbrlapi0.5" 462fi 463if package_exists apache2-bin; then 464 dev_list="${dev_list} apache2-bin" 465else 466 dev_list="${dev_list} apache2.2-bin" 467fi 468if package_exists xfonts-mathml; then 469 dev_list="${dev_list} xfonts-mathml" 470fi 471if package_exists fonts-indic; then 472 dev_list="${dev_list} fonts-indic" 473else 474 dev_list="${dev_list} ttf-indic-fonts" 475fi 476if package_exists php7.0-cgi; then 477 dev_list="${dev_list} php7.0-cgi libapache2-mod-php7.0" 478else 479 dev_list="${dev_list} php5-cgi libapache2-mod-php5" 480fi 481# ttf-mscorefonts-installer is in the Debian contrib repo, which has 482# dependencies on non-free software. Install it only if the user has already 483# enabled contrib. 484if package_exists ttf-mscorefonts-installer; then 485 dev_list="${dev_list} ttf-mscorefonts-installer" 486elif package_exists msttcorefonts; then 487 dev_list="${dev_list} msttcorefonts" 488fi 489# Ubuntu 16.04 has this package deleted. 490if package_exists ttf-kochi-gothic; then 491 dev_list="${dev_list} ttf-kochi-gothic" 492fi 493# Ubuntu 16.04 has this package deleted. 494if package_exists ttf-kochi-mincho; then 495 dev_list="${dev_list} ttf-kochi-mincho" 496fi 497 498# Some packages are only needed if the distribution actually supports 499# installing them. 500if package_exists appmenu-gtk; then 501 lib_list="$lib_list appmenu-gtk" 502fi 503 504# When cross building for arm/Android on 64-bit systems the host binaries 505# that are part of v8 need to be compiled with -m32 which means 506# that basic multilib support is needed. 507if file -L /sbin/init | grep -q 'ELF 64-bit'; then 508 # gcc-multilib conflicts with the arm cross compiler (at least in trusty) but 509 # g++-X.Y-multilib gives us the 32-bit support that we need. Find out the 510 # appropriate value of X and Y by seeing what version the current 511 # distribution's g++-multilib package depends on. 512 multilib_package=$(apt-cache depends g++-multilib --important | \ 513 grep -E --color=never --only-matching '\bg\+\+-[0-9.]+-multilib\b') 514 lib32_list="$lib32_list $multilib_package" 515fi 516 517if test "$do_inst_syms" = "" && test 0 -eq ${do_quick_check-0} 518then 519 echo "This script installs all tools and libraries needed to build Chromium." 520 echo "" 521 echo "For most of the libraries, it can also install debugging symbols, which" 522 echo "will allow you to debug code in the system libraries. Most developers" 523 echo "won't need these symbols." 524 echo -n "Do you want me to install them for you (y/N) " 525 if yes_no 1; then 526 do_inst_syms=1 527 fi 528fi 529if test "$do_inst_syms" = "1"; then 530 echo "Including debugging symbols." 531 # Many debug packages are not available in Debian stretch, 532 # so exclude the ones that are missing. 533 available_dbg_packages="" 534 for package in ${dbg_list}; do 535 if package_exists ${package}; then 536 available_dbg_packages="${available_dbg_packages} ${package}" 537 fi 538 done 539 dbg_list="${available_dbg_packages}" 540else 541 echo "Skipping debugging symbols." 542 dbg_list= 543fi 544 545if test "$do_inst_lib32" = "1" ; then 546 echo "Including 32-bit libraries for ARM/Android." 547else 548 echo "Skipping 32-bit libraries for ARM/Android." 549 lib32_list= 550fi 551 552if test "$do_inst_arm" = "1" ; then 553 echo "Including ARM cross toolchain." 554else 555 echo "Skipping ARM cross toolchain." 556 arm_list= 557fi 558 559if test "$do_inst_nacl" = "1"; then 560 echo "Including NaCl, NaCl toolchain, NaCl ports dependencies." 561else 562 echo "Skipping NaCl, NaCl toolchain, NaCl ports dependencies." 563 nacl_list= 564fi 565 566# The `sort -r -s -t: -k2` sorts all the :i386 packages to the front, to avoid 567# confusing dpkg-query (crbug.com/446172). 568packages="$( 569 echo "${dev_list} ${lib_list} ${dbg_list} ${lib32_list} ${arm_list}"\ 570 "${nacl_list}" | tr " " "\n" | sort -u | sort -r -s -t: -k2 | tr "\n" " " 571)" 572 573if [ 1 -eq "${do_quick_check-0}" ] ; then 574 if ! missing_packages="$(dpkg-query -W -f ' ' ${packages} 2>&1)"; then 575 # Distinguish between packages that actually aren't available to the 576 # system (i.e. not in any repo) and packages that just aren't known to 577 # dpkg (i.e. managed by apt). 578 missing_packages="$(echo "${missing_packages}" | awk '{print $NF}')" 579 not_installed="" 580 unknown="" 581 for p in ${missing_packages}; do 582 if apt-cache show ${p} > /dev/null 2>&1; then 583 not_installed="${p}\n${not_installed}" 584 else 585 unknown="${p}\n${unknown}" 586 fi 587 done 588 if [ -n "${not_installed}" ]; then 589 echo "WARNING: The following packages are not installed:" 590 echo -e "${not_installed}" | sed -e "s/^/ /" 591 fi 592 if [ -n "${unknown}" ]; then 593 echo "WARNING: The following packages are unknown to your system" 594 echo "(maybe missing a repo or need to 'sudo apt-get update'):" 595 echo -e "${unknown}" | sed -e "s/^/ /" 596 fi 597 exit 1 598 fi 599 exit 0 600fi 601 602if test "$do_inst_lib32" = "1" || test "$do_inst_nacl" = "1"; then 603 sudo dpkg --add-architecture i386 604fi 605sudo apt-get update 606 607# We initially run "apt-get" with the --reinstall option and parse its output. 608# This way, we can find all the packages that need to be newly installed 609# without accidentally promoting any packages from "auto" to "manual". 610# We then re-run "apt-get" with just the list of missing packages. 611echo "Finding missing packages..." 612# Intentionally leaving $packages unquoted so it's more readable. 613echo "Packages required: " $packages 614echo 615new_list_cmd="sudo apt-get install --reinstall $(echo $packages)" 616if new_list="$(yes n | LANGUAGE=en LANG=C $new_list_cmd)"; then 617 # We probably never hit this following line. 618 echo "No missing packages, and the packages are up to date." 619elif [ $? -eq 1 ]; then 620 # We expect apt-get to have exit status of 1. 621 # This indicates that we cancelled the install with "yes n|". 622 new_list=$(echo "$new_list" | 623 sed -e '1,/The following NEW packages will be installed:/d;s/^ //;t;d') 624 new_list=$(echo "$new_list" | sed 's/ *$//') 625 if [ -z "$new_list" ] ; then 626 echo "No missing packages, and the packages are up to date." 627 else 628 echo "Installing missing packages: $new_list." 629 sudo apt-get install ${do_quietly-} ${new_list} 630 fi 631 echo 632else 633 # An apt-get exit status of 100 indicates that a real error has occurred. 634 635 # I am intentionally leaving out the '"'s around new_list_cmd, 636 # as this makes it easier to cut and paste the output 637 echo "The following command failed: " ${new_list_cmd} 638 echo 639 echo "It produces the following output:" 640 yes n | $new_list_cmd || true 641 echo 642 echo "You will have to install the above packages yourself." 643 echo 644 exit 100 645fi 646 647# Install the Chrome OS default fonts. This must go after running 648# apt-get, since install-chromeos-fonts depends on curl. 649if test "$do_inst_chromeos_fonts" != "0"; then 650 echo 651 echo "Installing Chrome OS fonts." 652 dir=`echo $0 | sed -r -e 's/\/[^/]+$//'` 653 if ! sudo $dir/linux/install-chromeos-fonts.py; then 654 echo "ERROR: The installation of the Chrome OS default fonts failed." 655 if [ `stat -f -c %T $dir` == "nfs" ]; then 656 echo "The reason is that your repo is installed on a remote file system." 657 else 658 echo "This is expected if your repo is installed on a remote file system." 659 fi 660 echo "It is recommended to install your repo on a local file system." 661 echo "You can skip the installation of the Chrome OS default founts with" 662 echo "the command line option: --no-chromeos-fonts." 663 exit 1 664 fi 665else 666 echo "Skipping installation of Chrome OS fonts." 667fi 668 669echo "Installing locales." 670CHROMIUM_LOCALES="da_DK.UTF-8 fr_FR.UTF-8 he_IL.UTF-8 zh_TW.UTF-8" 671LOCALE_GEN=/etc/locale.gen 672if [ -e ${LOCALE_GEN} ]; then 673 OLD_LOCALE_GEN="$(cat /etc/locale.gen)" 674 for CHROMIUM_LOCALE in ${CHROMIUM_LOCALES}; do 675 sudo sed -i "s/^# ${CHROMIUM_LOCALE}/${CHROMIUM_LOCALE}/" ${LOCALE_GEN} 676 done 677 # Regenerating locales can take a while, so only do it if we need to. 678 if (echo "${OLD_LOCALE_GEN}" | cmp -s ${LOCALE_GEN}); then 679 echo "Locales already up-to-date." 680 else 681 sudo locale-gen 682 fi 683else 684 for CHROMIUM_LOCALE in ${CHROMIUM_LOCALES}; do 685 sudo locale-gen ${CHROMIUM_LOCALE} 686 done 687fi 688