mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 06:16:30 +03:00
915 lines
25 KiB
Python
Executable File
915 lines
25 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright 2023 The Chromium Authors
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
# Script to install everything needed to build chromium
|
|
# including items requiring sudo privileges.
|
|
# See https://chromium.googlesource.com/chromium/src/+/main/docs/linux/build_instructions.md
|
|
|
|
import argparse
|
|
import functools
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
@functools.lru_cache(maxsize=1)
|
|
def build_apt_package_list():
|
|
print("Building apt package list.", file=sys.stderr)
|
|
output = subprocess.check_output(["apt-cache", "dumpavail"]).decode()
|
|
arch_map = {"i386": ":i386"}
|
|
package_regex = re.compile(r"^Package: (.+?)$.+?^Architecture: (.+?)$",
|
|
re.M | re.S)
|
|
return set(package + arch_map.get(arch, "")
|
|
for package, arch in re.findall(package_regex, output))
|
|
|
|
|
|
def package_exists(package_name: str) -> bool:
|
|
return package_name in build_apt_package_list()
|
|
|
|
|
|
def parse_args(argv):
|
|
parser = argparse.ArgumentParser(
|
|
description="Install Chromium build dependencies.")
|
|
parser.add_argument("--syms",
|
|
action="store_true",
|
|
help="Enable installation of debugging symbols")
|
|
parser.add_argument(
|
|
"--no-syms",
|
|
action="store_false",
|
|
dest="syms",
|
|
help="Disable installation of debugging symbols",
|
|
)
|
|
parser.add_argument(
|
|
"--lib32",
|
|
action="store_true",
|
|
help="Enable installation of 32-bit libraries, e.g. for V8 snapshot",
|
|
)
|
|
parser.add_argument(
|
|
"--android",
|
|
action="store_true",
|
|
help="Enable installation of android dependencies",
|
|
)
|
|
parser.add_argument(
|
|
"--no-android",
|
|
action="store_false",
|
|
dest="android",
|
|
help="Disable installation of android dependencies",
|
|
)
|
|
parser.add_argument("--arm",
|
|
action="store_true",
|
|
help="Enable installation of arm cross toolchain")
|
|
parser.add_argument(
|
|
"--no-arm",
|
|
action="store_false",
|
|
dest="arm",
|
|
help="Disable installation of arm cross toolchain",
|
|
)
|
|
parser.add_argument(
|
|
"--chromeos-fonts",
|
|
action="store_true",
|
|
help="Enable installation of Chrome OS fonts",
|
|
)
|
|
parser.add_argument(
|
|
"--no-chromeos-fonts",
|
|
action="store_false",
|
|
dest="chromeos_fonts",
|
|
help="Disable installation of Chrome OS fonts",
|
|
)
|
|
parser.add_argument(
|
|
"--nacl",
|
|
action="store_true",
|
|
help="Enable installation of prerequisites for building NaCl",
|
|
)
|
|
parser.add_argument(
|
|
"--no-nacl",
|
|
action="store_false",
|
|
dest="nacl",
|
|
help="Disable installation of prerequisites for building NaCl",
|
|
)
|
|
parser.add_argument(
|
|
"--backwards-compatible",
|
|
action="store_true",
|
|
help=
|
|
"Enable installation of packages that are no longer currently needed and"
|
|
+ "have been removed from this script. Useful for bisection.",
|
|
)
|
|
parser.add_argument(
|
|
"--no-backwards-compatible",
|
|
action="store_false",
|
|
dest="backwards_compatible",
|
|
help=
|
|
"Disable installation of packages that are no longer currently needed and"
|
|
+ "have been removed from this script.",
|
|
)
|
|
parser.add_argument("--no-prompt",
|
|
action="store_true",
|
|
help="Automatic yes to prompts")
|
|
parser.add_argument(
|
|
"--quick-check",
|
|
action="store_true",
|
|
help="Quickly try to determine if dependencies are installed",
|
|
)
|
|
parser.add_argument(
|
|
"--unsupported",
|
|
action="store_true",
|
|
help="Attempt installation even on unsupported systems",
|
|
)
|
|
|
|
options = parser.parse_args(argv)
|
|
|
|
if options.arm or options.android:
|
|
options.lib32 = True
|
|
|
|
return options
|
|
|
|
|
|
def check_lsb_release():
|
|
if not shutil.which("lsb_release"):
|
|
print("ERROR: lsb_release not found in $PATH", file=sys.stderr)
|
|
print("try: sudo apt-get install lsb-release", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
@functools.lru_cache(maxsize=1)
|
|
def distro_codename():
|
|
return subprocess.check_output(["lsb_release", "--codename",
|
|
"--short"]).decode().strip()
|
|
|
|
|
|
def check_distro(options):
|
|
if options.unsupported or options.quick_check:
|
|
return
|
|
|
|
distro_id = subprocess.check_output(["lsb_release", "--id",
|
|
"--short"]).decode().strip()
|
|
|
|
supported_codenames = ["bionic", "focal", "jammy"]
|
|
supported_ids = ["Debian"]
|
|
|
|
if (distro_codename() not in supported_codenames
|
|
and distro_id not in supported_ids):
|
|
print(
|
|
"WARNING: The following distributions are supported,",
|
|
"but distributions not in the list below can also try to install",
|
|
"dependencies by passing the `--unsupported` parameter",
|
|
"\tUbuntu 18.04 LTS (bionic with EoL April 2028)",
|
|
"\tUbuntu 20.04 LTS (focal with EoL April 2030)",
|
|
"\tUbuntu 22.04 LTS (jammy with EoL April 2032)",
|
|
"\tDebian 10 (buster) or later",
|
|
sep="\n",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
|
|
|
|
def check_architecture():
|
|
architecture = subprocess.check_output(["uname", "-m"]).decode().strip()
|
|
if architecture not in ["i686", "x86_64"]:
|
|
print("Only x86 architectures are currently supported", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
def check_root():
|
|
if os.geteuid() != 0:
|
|
print("Running as non-root user.", file=sys.stderr)
|
|
print("You might have to enter your password one or more times for 'sudo'.",
|
|
file=sys.stderr)
|
|
print(file=sys.stderr)
|
|
|
|
|
|
def apt_update(options):
|
|
if options.lib32 or options.nacl:
|
|
subprocess.check_call(["sudo", "dpkg", "--add-architecture", "i386"])
|
|
subprocess.check_call(["sudo", "apt-get", "update"])
|
|
|
|
|
|
# Packages needed for development
|
|
def dev_list():
|
|
packages = [
|
|
"binutils",
|
|
"bison",
|
|
"bzip2",
|
|
"cdbs",
|
|
"curl",
|
|
"dbus-x11",
|
|
"devscripts",
|
|
"dpkg-dev",
|
|
"elfutils",
|
|
"fakeroot",
|
|
"flex",
|
|
"git-core",
|
|
"gperf",
|
|
"libasound2-dev",
|
|
"libatspi2.0-dev",
|
|
"libbrlapi-dev",
|
|
"libbz2-dev",
|
|
"libc6-dev",
|
|
"libcairo2-dev",
|
|
"libcap-dev",
|
|
"libcups2-dev",
|
|
"libcurl4-gnutls-dev",
|
|
"libdrm-dev",
|
|
"libelf-dev",
|
|
"libevdev-dev",
|
|
"libffi-dev",
|
|
"libfuse2",
|
|
"libgbm-dev",
|
|
"libglib2.0-dev",
|
|
"libglu1-mesa-dev",
|
|
"libgtk-3-dev",
|
|
"libkrb5-dev",
|
|
"libnspr4-dev",
|
|
"libnss3-dev",
|
|
"libpam0g-dev",
|
|
"libpci-dev",
|
|
"libpulse-dev",
|
|
"libsctp-dev",
|
|
"libspeechd-dev",
|
|
"libsqlite3-dev",
|
|
"libssl-dev",
|
|
"libsystemd-dev",
|
|
"libudev-dev",
|
|
"libva-dev",
|
|
"libwww-perl",
|
|
"libxshmfence-dev",
|
|
"libxslt1-dev",
|
|
"libxss-dev",
|
|
"libxt-dev",
|
|
"libxtst-dev",
|
|
"lighttpd",
|
|
"locales",
|
|
"openbox",
|
|
"p7zip",
|
|
"patch",
|
|
"perl",
|
|
"pkg-config",
|
|
"rpm",
|
|
"ruby",
|
|
"subversion",
|
|
"uuid-dev",
|
|
"wdiff",
|
|
"x11-utils",
|
|
"xcompmgr",
|
|
"xz-utils",
|
|
"zip",
|
|
]
|
|
|
|
# Packages needed for chromeos only
|
|
packages += [
|
|
"libbluetooth-dev",
|
|
"libxkbcommon-dev",
|
|
"mesa-common-dev",
|
|
"zstd",
|
|
]
|
|
|
|
if package_exists("realpath"):
|
|
packages.append("realpath")
|
|
|
|
if package_exists("libjpeg-dev"):
|
|
packages.append("libjpeg-dev")
|
|
else:
|
|
packages.append("libjpeg62-dev")
|
|
|
|
if package_exists("libudev1"):
|
|
packages.append("libudev1")
|
|
else:
|
|
packages.append("libudev0")
|
|
|
|
if package_exists("libbrlapi0.8"):
|
|
packages.append("libbrlapi0.8")
|
|
elif package_exists("libbrlapi0.7"):
|
|
packages.append("libbrlapi0.7")
|
|
elif package_exists("libbrlapi0.6"):
|
|
packages.append("libbrlapi0.6")
|
|
else:
|
|
packages.append("libbrlapi0.5")
|
|
|
|
if package_exists("libav-tools"):
|
|
packages.append("libav-tools")
|
|
|
|
if package_exists("libvulkan-dev"):
|
|
packages.append("libvulkan-dev")
|
|
|
|
if package_exists("libinput-dev"):
|
|
packages.append("libinput-dev")
|
|
|
|
# Cross-toolchain strip is needed for building the sysroots.
|
|
if package_exists("binutils-arm-linux-gnueabihf"):
|
|
packages.append("binutils-arm-linux-gnueabihf")
|
|
if package_exists("binutils-aarch64-linux-gnu"):
|
|
packages.append("binutils-aarch64-linux-gnu")
|
|
if package_exists("binutils-mipsel-linux-gnu"):
|
|
packages.append("binutils-mipsel-linux-gnu")
|
|
if package_exists("binutils-mips64el-linux-gnuabi64"):
|
|
packages.append("binutils-mips64el-linux-gnuabi64")
|
|
|
|
# 64-bit systems need a minimum set of 32-bit compat packages for the
|
|
# pre-built NaCl binaries.
|
|
if "ELF 64-bit" in subprocess.check_output(["file", "-L",
|
|
"/sbin/init"]).decode():
|
|
packages.extend(["libc6-i386", "lib32stdc++6"])
|
|
|
|
# lib32gcc-s1 used to be called lib32gcc1 in older distros.
|
|
if package_exists("lib32gcc-s1"):
|
|
packages.append("lib32gcc-s1")
|
|
elif package_exists("lib32gcc1"):
|
|
packages.append("lib32gcc1")
|
|
|
|
return packages
|
|
|
|
|
|
# List of required run-time libraries
|
|
def lib_list():
|
|
packages = [
|
|
"lib32z1",
|
|
"libasound2",
|
|
"libatk1.0-0",
|
|
"libatspi2.0-0",
|
|
"libc6",
|
|
"libcairo2",
|
|
"libcap2",
|
|
"libcgi-session-perl",
|
|
"libcups2",
|
|
"libdrm2",
|
|
"libegl1",
|
|
"libevdev2",
|
|
"libexpat1",
|
|
"libfontconfig1",
|
|
"libfreetype6",
|
|
"libgbm1",
|
|
"libglib2.0-0",
|
|
"libgl1",
|
|
"libgtk-3-0",
|
|
"libncurses5",
|
|
"libpam0g",
|
|
"libpango-1.0-0",
|
|
"libpangocairo-1.0-0",
|
|
"libpci3",
|
|
"libpcre3",
|
|
"libpixman-1-0",
|
|
"libspeechd2",
|
|
"libstdc++6",
|
|
"libsqlite3-0",
|
|
"libuuid1",
|
|
"libwayland-egl1",
|
|
"libwayland-egl1-mesa",
|
|
"libx11-6",
|
|
"libx11-xcb1",
|
|
"libxau6",
|
|
"libxcb1",
|
|
"libxcomposite1",
|
|
"libxcursor1",
|
|
"libxdamage1",
|
|
"libxdmcp6",
|
|
"libxext6",
|
|
"libxfixes3",
|
|
"libxi6",
|
|
"libxinerama1",
|
|
"libxrandr2",
|
|
"libxrender1",
|
|
"libxtst6",
|
|
"x11-utils",
|
|
"xvfb",
|
|
"zlib1g",
|
|
]
|
|
|
|
# Run-time libraries required by chromeos only
|
|
packages += [
|
|
"libpulse0",
|
|
"libbz2-1.0",
|
|
]
|
|
|
|
if package_exists("libffi8"):
|
|
packages.append("libffi8")
|
|
elif package_exists("libffi7"):
|
|
packages.append("libffi7")
|
|
elif package_exists("libffi6"):
|
|
packages.append("libffi6")
|
|
|
|
if package_exists("libpng16-16"):
|
|
packages.append("libpng16-16")
|
|
else:
|
|
packages.append("libpng12-0")
|
|
|
|
if package_exists("libnspr4"):
|
|
packages.extend(["libnspr4", "libnss3"])
|
|
else:
|
|
packages.extend(["libnspr4-0d", "libnss3-1d"])
|
|
|
|
if package_exists("appmenu-gtk"):
|
|
packages.append("appmenu-gtk")
|
|
if package_exists("libgnome-keyring0"):
|
|
packages.append("libgnome-keyring0")
|
|
if package_exists("libgnome-keyring-dev"):
|
|
packages.append("libgnome-keyring-dev")
|
|
if package_exists("libvulkan1"):
|
|
packages.append("libvulkan1")
|
|
if package_exists("libinput10"):
|
|
packages.append("libinput10")
|
|
|
|
return packages
|
|
|
|
|
|
def lib32_list(options):
|
|
if not options.lib32:
|
|
print("Skipping 32-bit libraries.", file=sys.stderr)
|
|
return []
|
|
print("Including 32-bit libraries.", file=sys.stderr)
|
|
|
|
packages = [
|
|
# 32-bit libraries needed for a 32-bit build
|
|
# includes some 32-bit libraries required by the Android SDK
|
|
# See https://developer.android.com/sdk/installing/index.html?pkg=tools
|
|
"libasound2:i386",
|
|
"libatk-bridge2.0-0:i386",
|
|
"libatk1.0-0:i386",
|
|
"libatspi2.0-0:i386",
|
|
"libdbus-1-3:i386",
|
|
"libegl1:i386",
|
|
"libgl1:i386",
|
|
"libglib2.0-0:i386",
|
|
"libncurses5:i386",
|
|
"libnss3:i386",
|
|
"libpango-1.0-0:i386",
|
|
"libpangocairo-1.0-0:i386",
|
|
"libstdc++6:i386",
|
|
"libwayland-egl1:i386",
|
|
"libx11-xcb1:i386",
|
|
"libxcomposite1:i386",
|
|
"libxdamage1:i386",
|
|
"libxkbcommon0:i386",
|
|
"libxrandr2:i386",
|
|
"libxtst6:i386",
|
|
"zlib1g:i386",
|
|
# 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf
|
|
"linux-libc-dev:i386",
|
|
"libpci3:i386",
|
|
]
|
|
|
|
# When cross building for arm/Android on 64-bit systems the host binaries
|
|
# that are part of v8 need to be compiled with -m32 which means
|
|
# that basic multilib support is needed.
|
|
if "ELF 64-bit" in subprocess.check_output(["file", "-L",
|
|
"/sbin/init"]).decode():
|
|
# gcc-multilib conflicts with the arm cross compiler but
|
|
# g++-X.Y-multilib gives us the 32-bit support that we need. Find out the
|
|
# appropriate value of X and Y by seeing what version the current
|
|
# distribution's g++-multilib package depends on.
|
|
lines = subprocess.check_output(
|
|
["apt-cache", "depends", "g++-multilib", "--important"]).decode()
|
|
pattern = re.compile(r"g\+\+-[0-9.]+-multilib")
|
|
packages += re.findall(pattern, lines)
|
|
|
|
return packages
|
|
|
|
|
|
# Packages that have been removed from this script. Regardless of configuration
|
|
# or options passed to this script, whenever a package is removed, it should be
|
|
# added here.
|
|
def backwards_compatible_list(options):
|
|
if not options.backwards_compatible:
|
|
print("Skipping backwards compatible packages.", file=sys.stderr)
|
|
return []
|
|
print("Including backwards compatible packages.", file=sys.stderr)
|
|
|
|
packages = [
|
|
"7za",
|
|
"fonts-indic",
|
|
"fonts-ipafont",
|
|
"fonts-stix",
|
|
"fonts-thai-tlwg",
|
|
"fonts-tlwg-garuda",
|
|
"g++",
|
|
"g++-4.8-multilib-arm-linux-gnueabihf",
|
|
"gcc-4.8-multilib-arm-linux-gnueabihf",
|
|
"g++-9-multilib-arm-linux-gnueabihf",
|
|
"gcc-9-multilib-arm-linux-gnueabihf",
|
|
"gcc-arm-linux-gnueabihf",
|
|
"g++-10-multilib-arm-linux-gnueabihf",
|
|
"gcc-10-multilib-arm-linux-gnueabihf",
|
|
"g++-10-arm-linux-gnueabihf",
|
|
"gcc-10-arm-linux-gnueabihf",
|
|
"git-svn",
|
|
"language-pack-da",
|
|
"language-pack-fr",
|
|
"language-pack-he",
|
|
"language-pack-zh-hant",
|
|
"libappindicator-dev",
|
|
"libappindicator1",
|
|
"libappindicator3-1",
|
|
"libappindicator3-dev",
|
|
"libdconf-dev",
|
|
"libdconf1",
|
|
"libdconf1:i386",
|
|
"libexif-dev",
|
|
"libexif12",
|
|
"libexif12:i386",
|
|
"libgbm-dev",
|
|
"libgbm-dev-lts-trusty",
|
|
"libgbm-dev-lts-xenial",
|
|
"libgconf-2-4:i386",
|
|
"libgconf2-dev",
|
|
"libgl1-mesa-dev",
|
|
"libgl1-mesa-dev-lts-trusty",
|
|
"libgl1-mesa-dev-lts-xenial",
|
|
"libgl1-mesa-glx:i386",
|
|
"libgl1-mesa-glx-lts-trusty:i386",
|
|
"libgl1-mesa-glx-lts-xenial:i386",
|
|
"libgles2-mesa-dev",
|
|
"libgles2-mesa-dev-lts-trusty",
|
|
"libgles2-mesa-dev-lts-xenial",
|
|
"libgtk-3-0:i386",
|
|
"libgtk2.0-0",
|
|
"libgtk2.0-0:i386",
|
|
"libgtk2.0-dev",
|
|
"mesa-common-dev",
|
|
"mesa-common-dev-lts-trusty",
|
|
"mesa-common-dev-lts-xenial",
|
|
"msttcorefonts",
|
|
"python-dev",
|
|
"python-setuptools",
|
|
"snapcraft",
|
|
"ttf-dejavu-core",
|
|
"ttf-indic-fonts",
|
|
"ttf-kochi-gothic",
|
|
"ttf-kochi-mincho",
|
|
"ttf-mscorefonts-installer",
|
|
"xfonts-mathml",
|
|
]
|
|
|
|
if package_exists("python-is-python2"):
|
|
packages.extend(["python-is-python2", "python2-dev"])
|
|
else:
|
|
packages.append("python")
|
|
|
|
if package_exists("python-crypto"):
|
|
packages.append("python-crypto")
|
|
|
|
if package_exists("python-numpy"):
|
|
packages.append("python-numpy")
|
|
|
|
if package_exists("python-openssl"):
|
|
packages.append("python-openssl")
|
|
|
|
if package_exists("python-psutil"):
|
|
packages.append("python-psutil")
|
|
|
|
if package_exists("python-yaml"):
|
|
packages.append("python-yaml")
|
|
|
|
if package_exists("apache2.2-bin"):
|
|
packages.append("apache2.2-bin")
|
|
else:
|
|
packages.append("apache2-bin")
|
|
|
|
php_versions = [
|
|
("php8.1-cgi", "libapache2-mod-php8.1"),
|
|
("php8.0-cgi", "libapache2-mod-php8.0"),
|
|
("php7.4-cgi", "libapache2-mod-php7.4"),
|
|
("php7.3-cgi", "libapache2-mod-php7.3"),
|
|
("php7.2-cgi", "libapache2-mod-php7.2"),
|
|
("php7.1-cgi", "libapache2-mod-php7.1"),
|
|
("php7.0-cgi", "libapache2-mod-php7.0"),
|
|
("php5-cgi", "libapache2-mod-php5"),
|
|
]
|
|
|
|
for php_cgi, mod_php in php_versions:
|
|
if package_exists(php_cgi):
|
|
packages.extend([php_cgi, mod_php])
|
|
break
|
|
|
|
return [package for package in packages if package_exists(package)]
|
|
|
|
|
|
def arm_list(options):
|
|
if not options.arm:
|
|
print("Skipping ARM cross toolchain.", file=sys.stderr)
|
|
return []
|
|
print("Including ARM cross toolchain.", file=sys.stderr)
|
|
|
|
# arm cross toolchain packages needed to build chrome on armhf
|
|
packages = [
|
|
"libc6-dev-armhf-cross",
|
|
"linux-libc-dev-armhf-cross",
|
|
"g++-arm-linux-gnueabihf",
|
|
]
|
|
|
|
# Work around for dependency issue Ubuntu: http://crbug.com/435056
|
|
if distro_codename() == "bionic":
|
|
packages.extend([
|
|
"g++-5-multilib-arm-linux-gnueabihf",
|
|
"gcc-5-multilib-arm-linux-gnueabihf",
|
|
"gcc-arm-linux-gnueabihf",
|
|
])
|
|
elif distro_codename() == "focal":
|
|
packages.extend([
|
|
"g++-10-multilib-arm-linux-gnueabihf",
|
|
"gcc-10-multilib-arm-linux-gnueabihf",
|
|
"gcc-arm-linux-gnueabihf",
|
|
])
|
|
elif distro_codename() == "jammy":
|
|
packages.extend([
|
|
"gcc-arm-linux-gnueabihf",
|
|
"g++-11-arm-linux-gnueabihf",
|
|
"gcc-11-arm-linux-gnueabihf",
|
|
])
|
|
|
|
return packages
|
|
|
|
|
|
def nacl_list(options):
|
|
if not options.nacl:
|
|
print("Skipping NaCl, NaCl toolchain, NaCl ports dependencies.",
|
|
file=sys.stderr)
|
|
return []
|
|
print("Including NaCl, NaCl toolchain, NaCl ports dependencies.",
|
|
file=sys.stderr)
|
|
|
|
packages = [
|
|
"g++-mingw-w64-i686",
|
|
"lib32z1-dev",
|
|
"libasound2:i386",
|
|
"libcap2:i386",
|
|
"libelf-dev:i386",
|
|
"libfontconfig1:i386",
|
|
"libglib2.0-0:i386",
|
|
"libgpm2:i386",
|
|
"libncurses5:i386",
|
|
"lib32ncurses5-dev",
|
|
"libnss3:i386",
|
|
"libpango-1.0-0:i386",
|
|
"libssl-dev:i386",
|
|
"libtinfo-dev",
|
|
"libtinfo-dev:i386",
|
|
"libtool",
|
|
"libuuid1:i386",
|
|
"libxcomposite1:i386",
|
|
"libxcursor1:i386",
|
|
"libxdamage1:i386",
|
|
"libxi6:i386",
|
|
"libxrandr2:i386",
|
|
"libxss1:i386",
|
|
"libxtst6:i386",
|
|
"texinfo",
|
|
"xvfb",
|
|
# Packages to build NaCl, its toolchains, and its ports.
|
|
"ant",
|
|
"autoconf",
|
|
"bison",
|
|
"cmake",
|
|
"gawk",
|
|
"intltool",
|
|
"xutils-dev",
|
|
"xsltproc",
|
|
]
|
|
|
|
# Some package names have changed over time
|
|
if package_exists("libssl-dev"):
|
|
packages.append("libssl-dev:i386")
|
|
elif package_exists("libssl1.1"):
|
|
packages.append("libssl1.1:i386")
|
|
elif package_exists("libssl1.0.2"):
|
|
packages.append("libssl1.0.2:i386")
|
|
else:
|
|
packages.append("libssl1.0.0:i386")
|
|
|
|
if package_exists("libtinfo5"):
|
|
packages.append("libtinfo5")
|
|
|
|
if package_exists("libudev1"):
|
|
packages.append("libudev1:i386")
|
|
else:
|
|
packages.append("libudev0:i386")
|
|
|
|
return packages
|
|
|
|
|
|
# Debian is in the process of transitioning to automatic debug packages, which
|
|
# have the -dbgsym suffix (https://wiki.debian.org/AutomaticDebugPackages).
|
|
# Untransitioned packages have the -dbg suffix. And on some systems, neither
|
|
# will be available, so exclude the ones that are missing.
|
|
def dbg_package_name(package):
|
|
if package_exists(package + "-dbgsym"):
|
|
return [package + "-dbgsym"]
|
|
if package_exists(package + "-dbg"):
|
|
return [package + "-dbg"]
|
|
return []
|
|
|
|
|
|
def dbg_list(options):
|
|
if not options.syms:
|
|
print("Skipping debugging symbols.", file=sys.stderr)
|
|
return []
|
|
print("Including debugging symbols.", file=sys.stderr)
|
|
|
|
packages = [
|
|
dbg_package for package in lib_list()
|
|
for dbg_package in dbg_package_name(package)
|
|
]
|
|
|
|
# Debugging symbols packages not following common naming scheme
|
|
if not dbg_package_name("libstdc++6"):
|
|
for version in ["8", "7", "6", "5", "4.9", "4.8", "4.7", "4.6"]:
|
|
if package_exists("libstdc++6-%s-dbg" % version):
|
|
packages.append("libstdc++6-%s-dbg" % version)
|
|
break
|
|
|
|
if not dbg_package_name("libatk1.0-0"):
|
|
packages.extend(dbg_package_name("libatk1.0"))
|
|
|
|
if not dbg_package_name("libpango-1.0-0"):
|
|
packages.extend(dbg_package_name("libpango1.0-dev"))
|
|
|
|
return packages
|
|
|
|
|
|
def package_list(options):
|
|
packages = (dev_list() + lib_list() + dbg_list(options) +
|
|
lib32_list(options) + arm_list(options) + nacl_list(options) +
|
|
backwards_compatible_list(options))
|
|
|
|
# Sort all the :i386 packages to the front, to avoid confusing dpkg-query
|
|
# (https://crbug.com/446172).
|
|
return sorted(set(packages), key=lambda x: (not x.endswith(":i386"), x))
|
|
|
|
|
|
def missing_packages(packages):
|
|
try:
|
|
subprocess.run(
|
|
["dpkg-query", "-W", "-f", " "] + packages,
|
|
check=True,
|
|
capture_output=True,
|
|
)
|
|
return []
|
|
except subprocess.CalledProcessError as e:
|
|
return [
|
|
line.split(" ")[-1] for line in e.stderr.decode().strip().splitlines()
|
|
]
|
|
|
|
|
|
def package_is_installable(package):
|
|
result = subprocess.run(["apt-cache", "show", package], capture_output=True)
|
|
return result.returncode == 0
|
|
|
|
|
|
def quick_check(options):
|
|
if not options.quick_check:
|
|
return
|
|
|
|
missing = missing_packages(package_list(options))
|
|
if not missing:
|
|
sys.exit(0)
|
|
|
|
not_installed = []
|
|
unknown = []
|
|
for p in missing:
|
|
if package_is_installable(p):
|
|
not_installed.append(p)
|
|
else:
|
|
unknown.append(p)
|
|
|
|
if not_installed:
|
|
print("WARNING: The following packages are not installed:", file=sys.stderr)
|
|
print(" ".join(not_installed), file=sys.stderr)
|
|
|
|
if unknown:
|
|
print("WARNING: The following packages are unknown to your system",
|
|
file=sys.stderr)
|
|
print("(maybe missing a repo or need to 'sudo apt-get update'):",
|
|
file=sys.stderr)
|
|
print(" ".join(unknown), file=sys.stderr)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
def find_missing_packages(options):
|
|
print("Finding missing packages...", file=sys.stderr)
|
|
|
|
packages = package_list(options)
|
|
packages_str = " ".join(packages)
|
|
print("Packages required: " + packages_str, file=sys.stderr)
|
|
|
|
query_cmd = ["apt-get", "--just-print", "install"] + packages
|
|
env = os.environ.copy()
|
|
env["LANGUAGE"] = "en"
|
|
env["LANG"] = "C"
|
|
cmd_output = subprocess.check_output(query_cmd, env=env).decode()
|
|
lines = cmd_output.splitlines()
|
|
|
|
install = []
|
|
for pattern in (
|
|
"The following NEW packages will be installed:",
|
|
"The following packages will be upgraded:",
|
|
):
|
|
if pattern in lines:
|
|
for line in lines[lines.index(pattern) + 1:]:
|
|
if not line.startswith(" "):
|
|
break
|
|
install += line.strip().split(" ")
|
|
return install
|
|
|
|
|
|
def install_packages(options):
|
|
try:
|
|
packages = find_missing_packages(options)
|
|
if packages:
|
|
quiet = ["-qq", "--assume-yes"] if options.no_prompt else []
|
|
subprocess.check_call(["sudo", "apt-get", "install"] + quiet + packages)
|
|
print(file=sys.stderr)
|
|
else:
|
|
print("No missing packages, and the packages are up to date.",
|
|
file=sys.stderr)
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
# An apt-get exit status of 100 indicates that a real error has occurred.
|
|
print("`apt-get --just-print install ...` failed", file=sys.stderr)
|
|
print("It produced the following output:", file=sys.stderr)
|
|
print(e.output.decode(), file=sys.stderr)
|
|
print(file=sys.stderr)
|
|
print("You will have to install the above packages yourself.",
|
|
file=sys.stderr)
|
|
print(file=sys.stderr)
|
|
sys.exit(100)
|
|
|
|
|
|
# Install the Chrome OS default fonts. This must go after running
|
|
# apt-get, since install-chromeos-fonts depends on curl.
|
|
def install_chromeos_fonts(options):
|
|
if not options.chromeos_fonts:
|
|
print("Skipping installation of Chrome OS fonts.", file=sys.stderr)
|
|
return
|
|
print("Installing Chrome OS fonts.", file=sys.stderr)
|
|
|
|
dir = os.path.abspath(os.path.dirname(__file__))
|
|
|
|
try:
|
|
subprocess.check_call(
|
|
["sudo",
|
|
os.path.join(dir, "linux", "install-chromeos-fonts.py")])
|
|
except subprocess.CalledProcessError:
|
|
print("ERROR: The installation of the Chrome OS default fonts failed.",
|
|
file=sys.stderr)
|
|
if (subprocess.check_output(
|
|
["stat", "-f", "-c", "%T", dir], ).decode().startswith("nfs")):
|
|
print(
|
|
"The reason is that your repo is installed on a remote file system.",
|
|
file=sys.stderr)
|
|
else:
|
|
print(
|
|
"This is expected if your repo is installed on a remote file system.",
|
|
file=sys.stderr)
|
|
|
|
print("It is recommended to install your repo on a local file system.",
|
|
file=sys.stderr)
|
|
print("You can skip the installation of the Chrome OS default fonts with",
|
|
file=sys.stderr)
|
|
print("the command line option: --no-chromeos-fonts.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
def install_locales():
|
|
print("Installing locales.", file=sys.stderr)
|
|
CHROMIUM_LOCALES = [
|
|
"da_DK.UTF-8", "fr_FR.UTF-8", "he_IL.UTF-8", "zh_TW.UTF-8"
|
|
]
|
|
LOCALE_GEN = "/etc/locale.gen"
|
|
if os.path.exists(LOCALE_GEN):
|
|
old_locale_gen = open(LOCALE_GEN).read()
|
|
for locale in CHROMIUM_LOCALES:
|
|
subprocess.check_call(
|
|
["sudo", "sed", "-i",
|
|
"s/^# %s/%s/" % (locale, locale), LOCALE_GEN])
|
|
|
|
# Regenerating locales can take a while, so only do it if we need to.
|
|
locale_gen = open(LOCALE_GEN).read()
|
|
if locale_gen != old_locale_gen:
|
|
subprocess.check_call(["sudo", "locale-gen"])
|
|
else:
|
|
print("Locales already up-to-date.", file=sys.stderr)
|
|
else:
|
|
for locale in CHROMIUM_LOCALES:
|
|
subprocess.check_call(["sudo", "locale-gen", locale])
|
|
|
|
|
|
def main():
|
|
options = parse_args(sys.argv[1:])
|
|
check_lsb_release()
|
|
check_distro(options)
|
|
check_architecture()
|
|
quick_check(options)
|
|
check_root()
|
|
apt_update(options)
|
|
install_packages(options)
|
|
install_chromeos_fonts(options)
|
|
install_locales()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|