main
Kar 2025-09-12 11:17:47 +00:00
commit 625bdee0ec
1 changed files with 522 additions and 0 deletions

522
install-build-deps-arch.py Normal file
View File

@ -0,0 +1,522 @@
#!/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 on Arch Linux
# including items requiring sudo privileges.
import argparse
import functools
import logging
import os
import shutil
import subprocess
import sys
logging.basicConfig(stream=sys.stderr,
level=logging.INFO,
format='%(name)s [%(levelname)s]: %(message)s')
logger = logging.getLogger(os.path.basename(sys.argv[0]))
@functools.lru_cache(maxsize=1)
def build_pacman_package_list():
logger.info("Building pacman package list.")
output = subprocess.check_output(["pacman", "-Q"]).decode()
return set(line.split()[0] for line in output.strip().splitlines())
def package_exists_in_repos(package_name: str) -> bool:
"""Check if package exists in repositories"""
result = subprocess.run(["pacman", "-Si", package_name],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return result.returncode == 0
def package_exists(package_name: str) -> bool:
# Check if package is installed
if package_name in build_pacman_package_list():
return True
# Check if package exists in repos
return package_exists_in_repos(package_name)
def parse_args(argv):
parser = argparse.ArgumentParser(
description="Install Chromium build dependencies on Arch Linux.")
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("--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("--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(
"--aur-helper",
default="yay",
help="AUR helper to use (default: yay)",
)
options = parser.parse_args(argv)
if options.arm:
options.lib32 = True
return options
def check_arch_linux():
try:
with open("/etc/os-release") as f:
content = f.read()
if "ID=arch" not in content and "ID_LIKE=arch" not in content:
logger.error("This script is designed for Arch Linux and derivatives")
sys.exit(1)
except FileNotFoundError:
logger.error("Cannot determine OS. This script is for Arch Linux.")
sys.exit(1)
def check_architecture():
architecture = subprocess.check_output(["uname", "-m"]).decode().strip()
if architecture not in ["i686", "x86_64", 'aarch64']:
logger.error("Only x86 and ARM64 architectures are currently supported")
sys.exit(1)
def check_root():
if os.geteuid() != 0:
logger.info("Running as non-root user.")
logger.info(
"You might have to enter your password one or more times for 'sudo'.\n")
def check_aur_helper(options):
if not shutil.which(options.aur_helper):
logger.error(f"AUR helper '{options.aur_helper}' not found.")
logger.error("Please install an AUR helper like 'yay' or 'paru'.")
logger.error("You can install yay with:")
logger.error(" git clone https://aur.archlinux.org/yay.git")
logger.error(" cd yay && makepkg -si")
sys.exit(1)
def pacman_update(options):
if options.lib32:
# Enable multilib repository
logger.info("Checking multilib repository...")
with open("/etc/pacman.conf", "r") as f:
config = f.read()
if "[multilib]" not in config or config.find("[multilib]") > config.find("#[multilib]"):
logger.info("Enabling multilib repository...")
subprocess.check_call([
"sudo", "sed", "-i",
"/^#\\[multilib\\]/,/^#Include = \\/etc\\/pacman.d\\/mirrorlist/ s/^#//",
"/etc/pacman.conf"
])
subprocess.check_call(["sudo", "pacman", "-Sy"])
# Core packages needed for Chromium development - verified Arch package names only
def get_core_packages():
"""Return core packages that definitely exist in Arch repos"""
return [
# Build essentials
"base-devel",
"git",
"python",
"curl",
"wget",
"unzip",
"zip",
"p7zip",
"bzip2",
"xz",
"patch",
"perl",
"ruby",
"nodejs",
"npm",
"bison",
"flex",
"gperf",
"pkgconf",
"nasm",
"yasm",
# Core libraries
"alsa-lib",
"at-spi2-core",
"cairo",
"cups",
"dbus",
"expat",
"fontconfig",
"freetype2",
"glib2",
"gtk3",
"krb5",
"libcap",
"libdrm",
"libelf",
"libevdev",
"libffi",
"mesa",
"libglvnd",
"libice",
"libinput",
"libjpeg-turbo",
"libpng",
"libpulse",
"libsm",
"libx11",
"libxau",
"libxcb",
"libxcomposite",
"libxcursor",
"libxdamage",
"libxdmcp",
"libxext",
"libxfixes",
"libxi",
"libxinerama",
"libxrandr",
"libxrender",
"libxshmfence",
"libxt",
"libxtst",
"nspr",
"nss",
"pam",
"pango",
"sqlite",
"systemd-libs",
"util-linux",
"vulkan-headers",
"vulkan-icd-loader",
"wayland",
"xorg-server",
"xorg-server-xvfb",
"zlib",
]
def get_optional_packages():
"""Return optional packages - only add if they exist"""
candidates = [
"bluez-libs",
"speech-dispatcher",
"libxss", # X11 screensaver
"pciutils", # PCI utilities
"xcompmgr", # Composite manager
"fd", # Find alternative
"ripgrep", # Fast grep
"lighttpd", # Web server
"openbox", # Window manager
]
packages = []
for pkg in candidates:
if package_exists_in_repos(pkg):
packages.append(pkg)
else:
logger.debug(f"Optional package '{pkg}' not found, skipping.")
return packages
def dev_list():
"""Get development packages"""
packages = get_core_packages() + get_optional_packages()
return packages
def lib_list():
"""Get runtime library packages"""
packages = [
"atk",
"at-spi2-atk",
"cairo",
"cups",
"dbus",
"expat",
"fontconfig",
"freetype2",
"glib2",
"gtk3",
"libdrm",
"libglvnd",
"libpulse",
"libx11",
"libxcb",
"libxcomposite",
"libxcursor",
"libxdamage",
"libxext",
"libxfixes",
"libxi",
"libxinerama",
"libxrandr",
"libxrender",
"libxtst",
"mesa",
"pango",
"wayland",
"zlib",
]
return packages
def lib32_list(options):
if not options.lib32:
logger.info("Skipping 32-bit libraries.")
return []
logger.info("Including 32-bit libraries.")
packages = [
"lib32-alsa-lib",
"lib32-atk",
"lib32-cairo",
"lib32-dbus",
"lib32-expat",
"lib32-fontconfig",
"lib32-freetype2",
"lib32-gcc-libs",
"lib32-glib2",
"lib32-glibc",
"lib32-gtk3",
"lib32-libdrm",
"lib32-libglvnd",
"lib32-libx11",
"lib32-libxcb",
"lib32-libxcomposite",
"lib32-libxcursor",
"lib32-libxdamage",
"lib32-libxext",
"lib32-libxfixes",
"lib32-libxi",
"lib32-libxinerama",
"lib32-libxrandr",
"lib32-libxrender",
"lib32-libxtst",
"lib32-mesa",
"lib32-nspr",
"lib32-nss",
"lib32-pango",
"lib32-zlib",
]
return packages
def arm_list(options):
if not options.arm:
logger.info("Skipping ARM cross toolchain.")
return []
logger.info("Including ARM cross toolchain.")
# ARM cross toolchain packages (these are AUR packages)
packages = [
"arm-linux-gnueabihf-gcc",
"arm-linux-gnueabihf-glibc",
"arm-linux-gnueabihf-binutils",
"arm-linux-gnueabihf-linux-api-headers",
]
return packages
def dbg_list(options):
if not options.syms:
logger.info("Skipping debugging symbols.")
return []
logger.info("Including debugging symbols.")
# Arch doesn't have separate debug packages like Debian/Ubuntu
logger.info("Note: Debug symbols in Arch are typically included in packages")
logger.info("or available through debug repositories. No additional packages needed.")
return []
def package_list(options):
packages = (dev_list() + lib_list() + dbg_list(options) +
lib32_list(options))
# ARM packages are from AUR, handle separately
arm_packages = arm_list(options) if options.arm else []
return list(set(packages)), arm_packages
def missing_packages(packages):
installed = build_pacman_package_list()
missing = []
for pkg in packages:
if pkg not in installed:
# Double-check that the package actually exists in repos
if package_exists_in_repos(pkg):
missing.append(pkg)
else:
logger.warning(f"Package '{pkg}' does not exist in repositories, skipping.")
return missing
def quick_check(options):
if not options.quick_check:
return
regular_packages, aur_packages = package_list(options)
missing_regular = missing_packages(regular_packages)
missing_aur = missing_packages(aur_packages)
if not missing_regular and not missing_aur:
sys.exit(0)
if missing_regular:
logger.warning("The following official packages are not installed:")
logger.warning(" ".join(missing_regular))
if missing_aur:
logger.warning("The following AUR packages are not installed:")
logger.warning(" ".join(missing_aur))
sys.exit(1)
def install_packages(options):
regular_packages, aur_packages = package_list(options)
# Install regular packages with pacman
missing_regular = missing_packages(regular_packages)
if missing_regular:
logger.info(f"Installing {len(missing_regular)} regular packages...")
cmd = ["sudo", "pacman", "-S", "--needed"]
if options.no_prompt:
cmd.append("--noconfirm")
subprocess.check_call(cmd + missing_regular)
else:
logger.info("All regular packages are already installed.")
# Install AUR packages
missing_aur = missing_packages(aur_packages)
if missing_aur:
logger.info(f"Installing {len(missing_aur)} AUR packages...")
cmd = [options.aur_helper, "-S", "--needed"]
if options.no_prompt:
cmd.append("--noconfirm")
subprocess.check_call(cmd + missing_aur)
else:
if aur_packages:
logger.info("All AUR packages are already installed.")
def install_chromeos_fonts(options):
if not options.chromeos_fonts:
logger.info("Skipping installation of Chrome OS fonts.")
return
logger.info("Installing Chrome OS fonts.")
# Check if we have the font installation script
script_dir = os.path.abspath(os.path.dirname(__file__))
font_script = os.path.join(script_dir, "linux", "install-chromeos-fonts.py")
if os.path.exists(font_script):
try:
subprocess.check_call(["sudo", font_script])
except subprocess.CalledProcessError:
logger.error("The installation of the Chrome OS default fonts failed.")
logger.info("You can skip this with --no-chromeos-fonts.")
else:
logger.warning("Chrome OS font installation script not found.")
logger.info("This is normal if you're not building from the full Chromium source tree.")
def install_locales():
logger.info("Installing locales.")
# Arch Linux locale setup is different from Debian/Ubuntu
CHROMIUM_LOCALES = [
"da_DK.UTF-8", "en_US.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):
with open(LOCALE_GEN, 'r') as f:
current_config = f.read()
needs_update = False
for locale in CHROMIUM_LOCALES:
if f"#{locale}" in current_config and f"\n{locale}" not in current_config:
subprocess.check_call([
"sudo", "sed", "-i",
f"s/^#{locale}/{locale}/",
LOCALE_GEN
])
needs_update = True
if needs_update:
subprocess.check_call(["sudo", "locale-gen"])
else:
logger.info("Locales already up-to-date.")
else:
logger.warning("locale.gen not found. Locales may need manual configuration.")
def main():
options = parse_args(sys.argv[1:])
check_arch_linux()
check_architecture()
quick_check(options)
check_root()
check_aur_helper(options)
pacman_update(options)
install_packages(options)
install_chromeos_fonts(options)
install_locales()
logger.info("Chromium build dependencies installation complete!")
return 0
if __name__ == "__main__":
sys.exit(main())