ladybird/Meta/Linters/check_flatpak.py
sideshowbarker c96dec10e3 Meta: Update ICU to 78.3 by bumping the vcpkg baseline
Bump the pinned ICU version from 78.2 to 78.3 — the current release — so
the build works on systems that already ship 78.3. And bump our vcpkg
baseline — because 78.3 is newer than our existing baseline. And pin
freetype to 2.13.3 — because the baseline update otherwise pulls in
2.14.3, which has font-rendering changes that break our layout tests.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/10145
2026-06-19 08:59:16 +02:00

243 lines
7.8 KiB
Python
Executable file

#!/usr/bin/env python3
# Copyright (c) 2025, The Ladybird contributors
#
# SPDX-License-Identifier: BSD-2-Clause
import glob
import json
import os
import re
import subprocess
import sys
import urllib.request
from enum import Enum
VCPKG = "vcpkg.json"
VCPKG_OVERLAYS_PORTS = "Meta/CMake/vcpkg/overlay-ports/*"
VCPKG_REPO = "Build/vcpkg"
VCPKG_BASELINE_URL = "https://raw.githubusercontent.com/microsoft/vcpkg/{}/versions/baseline.json"
FLATPAK_MANIFEST = "Meta/CMake/flatpak/org.ladybird.Ladybird.json"
SELF = "Ladybird"
# List of build tools that are not provided by the Flatpak SDK and therefore in the manifest
# For a vcpkg build these are installed on the host system
flatpak_build_tools = [
"gn",
]
# List of libraries that are transitive dependencies
# These are in the manifest to fetch before building, but not explicitely versioned
flatpak_transitive_deps = [
"libyuv",
]
# List of libraries that are in the Flatpak runtime and therefore not in the manifest
# See: https://docs.flatpak.org/en/latest/available-runtimes.html#check-software-available-in-runtimes
flatpak_runtime_libs = [
"curl",
"dbus",
"fontconfig",
"freetype",
"harfbuzz",
"libjpeg-turbo",
"libproxy",
"nghttp2", # FIXME: This can be removed when the vcpkg overlay is no longer needed.
"qtbase",
"qtmultimedia",
"sqlite3",
"tiff",
"vulkan",
"vulkan-headers",
"zlib",
]
# List of libraries that are in vcpkg but not needed for the Linux platform
vcpkg_not_linux = [
"dirent",
"mman",
"pthread",
]
# List of libraries that are behind vcpkg manifest features and only
# installed for specific GUI frameworks (e.g. GTK), not the Qt flatpak.
vcpkg_feature_only = [
"gtk",
"libadwaita",
"wayland",
"wayland-protocols",
]
class DepMatch(Enum):
Match = (0,)
NoMatch = (1,)
VersionMismatch = (2,)
Excluded = (3,)
baseline_versions = {}
def get_baseline_version(baseline, name):
if baseline not in baseline_versions:
if os.path.isdir(VCPKG_REPO):
# Clear GIT_DIR so git operates on the vcpkg repo, not the parent repo (pre-commit sets GIT_DIR)
env = {k: v for k, v in os.environ.items() if k != "GIT_DIR"}
try:
result = subprocess.run(
["git", "-C", VCPKG_REPO, "show", f"{baseline}:versions/baseline.json"],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
check=True,
env=env,
text=True,
)
baseline_versions[baseline] = json.loads(result.stdout)
except (subprocess.CalledProcessError, json.JSONDecodeError):
pass
if baseline not in baseline_versions:
url = VCPKG_BASELINE_URL.format(baseline)
try:
with urllib.request.urlopen(url) as response:
baseline_versions[baseline] = json.load(response)
except Exception as error:
print(f"Failed to fetch vcpkg baseline {baseline[:7]}: {error}")
baseline_versions[baseline] = {}
port = baseline_versions[baseline].get("default", {}).get(name)
if port and "baseline" in port:
return port["baseline"]
print(f"{name} cannot be matched, vcpkg baseline revision: {baseline[:7]}")
def check_for_match(vcpkg: dict, vcpkg_baseline, name: str, identifier: str) -> DepMatch:
if name == SELF or name in flatpak_build_tools or name in flatpak_transitive_deps:
return DepMatch.Excluded
if name not in vcpkg:
version = get_baseline_version(vcpkg_baseline, name)
if version:
vcpkg[name] = version
if name in vcpkg:
version = vcpkg[name]
normalized_version = re.sub(r"[^A-Za-z0-9]", "", version)
normalized_identifier = re.sub(r"[^A-Za-z0-9]", "", identifier)
if version not in identifier and normalized_version not in normalized_identifier:
return DepMatch.VersionMismatch
else:
return DepMatch.Match
else:
return DepMatch.NoMatch
def check_vcpkg_vs_flatpak_versioning():
def match_and_update(name: str, identifier: str) -> bool:
dep_match = check_for_match(vcpkg, vcpkg_baseline, name, identifier)
if dep_match == DepMatch.Match or dep_match == DepMatch.Excluded:
if name in vcpkg:
del vcpkg[name]
return False
else:
if dep_match == DepMatch.VersionMismatch:
print(f"{name} version mismatch. vcpkg: {vcpkg[name]}, Flatpak: {source['tag']}")
del vcpkg[name]
elif dep_match == DepMatch.NoMatch:
flatpak.append(name)
return True
vcpkg = {}
flatpak = []
mismatch_found = False
with open(VCPKG) as input:
vcpkg_json = json.load(input)
vcpkg_baseline = vcpkg_json["builtin-baseline"]
for package in vcpkg_json["overrides"]:
# Add name/version pair, strip any '#' postfix from the version
vcpkg[package["name"]] = str(package["version"]).split("#")[0]
# Check the vcpkg overlay ports for packages not listed in overrides
for path in glob.glob(VCPKG_OVERLAYS_PORTS):
with open(f"{path}/vcpkg.json") as input:
overlay = json.load(input)
if "name" in overlay and overlay["name"] not in vcpkg and "version" in overlay:
vcpkg[overlay["name"]] = overlay["version"]
with open(FLATPAK_MANIFEST) as input:
for module in json.load(input)["modules"]:
name = module["name"]
for source in module["sources"]:
if "type" in source and source["type"] == "git":
if "tag" in source:
# Get the tag
# Replace '-' with '.': 76-1 vs 76.1
tag = str(source["tag"]).replace("-", ".")
mismatch_found |= match_and_update(name, tag)
break
elif "branch" in source or "x-branch" in source:
# Get the branch
# Strip '_' postfix, replace '/' with '_': chromium/7258_13 vs chromium_7258
branch = str(source.get("branch", source.get("x-branch"))).split("_")[0].replace("/", "_")
mismatch_found |= match_and_update(name, branch)
break
elif "type" in source and source["type"] == "archive":
mismatch_found |= match_and_update(name, source["url"])
break
else:
if not (name == SELF or name in flatpak_build_tools or name in flatpak_transitive_deps):
flatpak.append(name)
# Remove excluded dependencies from the vcpkg list
for name in flatpak_runtime_libs + vcpkg_not_linux + vcpkg_feature_only:
if name in vcpkg:
del vcpkg[name]
if len(vcpkg):
mismatch_found = True
print(f"There are {len(vcpkg)} vcpkg dependencies that have no match in flatpak")
for name in vcpkg.keys():
print(f"- {name}")
if len(flatpak):
mismatch_found = True
print(f"There are {len(flatpak)} flatpak dependencies that have no match in vcpkg")
for name in flatpak:
print(f"- {name}")
return mismatch_found
def main():
file_list = sys.argv[1:] if len(sys.argv) > 1 else [VCPKG]
did_fail = False
if VCPKG in file_list or FLATPAK_MANIFEST in file_list:
did_fail = check_vcpkg_vs_flatpak_versioning()
# TODO: Add linting of Flatpak and AppStream manifest
# See #5594, bullet point "Missing lint job in CI to ensure Flatpak and AppStream manifests are up to snuff"
if did_fail:
sys.exit(1)
if __name__ == "__main__":
main()