From 501a33441d6376328bee544417c4c574fdfe2cd8 Mon Sep 17 00:00:00 2001 From: classabbyamp Date: Mon, 8 Dec 2025 21:42:45 -0500 Subject: [PATCH] common/scripts: add script to generate distfiles from meson wrap files useful for mesa, where there are a signficant number of crates referenced via meson wrap files, but this could be generally useful for other meson-based packages that do a similar thing for vendored libraries. This could be further extended in the future to add support for git/hg/svn wraps by adding subclasses of `Wrap` that support those metadata options. setting `MESON_PACKAGE_CACHE_DIR` allows meson to look for tarballs for wraps it needs automatically. --- Manual.md | 5 +- common/build-helper/meson.sh | 3 + common/scripts/gen-wrap-distfiles.py | 120 +++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100755 common/scripts/gen-wrap-distfiles.py diff --git a/Manual.md b/Manual.md index f85137f40edb61..99add3036c1772 100644 --- a/Manual.md +++ b/Manual.md @@ -1107,7 +1107,10 @@ additional paths to be searched when linking target binaries to be introspected. - `meson` creates a cross file, `${XBPS_WRAPPERDIR}/meson/xbps_meson.cross`, which configures meson for cross builds. This is particularly useful for building packages that wrap meson invocations (e.g., `python3-pep517` packages that use a meson backend) and is added by default -for packages that use the `meson` build style. +for packages that use the `meson` build style. It also sets `$MESON_PACKAGE_CACHE_DIR` to +`$XBPS_SRCDISTDIR/$pkgname-$version/` so libraries specified as meson wraps can be added to +distfiles and will be automatically used by meson. See also `common/scripts/gen-wrap-distfiles.py` +for a script that generates distfiles entries for wraps. - `numpy` configures the environment for cross-compilation of python packages that provide compiled extensions linking to NumPy C libraries. If the `meson` build helper is also diff --git a/common/build-helper/meson.sh b/common/build-helper/meson.sh index 79e22a2bf14839..69b30555fce672 100644 --- a/common/build-helper/meson.sh +++ b/common/build-helper/meson.sh @@ -1,6 +1,9 @@ # This build helper writes a Meson cross-file, allowing other build styles # to properly drive cross-builds in Meson when appropriate +# allows meson to automatically unpack wrapped dependencies specified in distfiles +export MESON_PACKAGE_CACHE_DIR="${XBPS_SRCDISTDIR}/${pkgname}-${version}/" + # Action is only taken for cross builds [ -z "$CROSS_BUILD" ] && return 0 diff --git a/common/scripts/gen-wrap-distfiles.py b/common/scripts/gen-wrap-distfiles.py new file mode 100755 index 00000000000000..4efe93e2372c99 --- /dev/null +++ b/common/scripts/gen-wrap-distfiles.py @@ -0,0 +1,120 @@ +#!/usr/bin/python3 + +import sys +from abc import ABC, abstractmethod +from configparser import ConfigParser +from dataclasses import dataclass +from pathlib import Path + +@dataclass +class Wrap(ABC): + src_path: Path + + directory: str | None = None + patch_url: str | None = None + patch_fallback_url: str | None = None + patch_filename: str | None = None + patch_hash: str | None = None + patch_directory: str | None = None + diff_files: str | None = None + method: str | None = None + + @property + @abstractmethod + def distfile(self): + raise NotImplementedError + + @property + @abstractmethod + def checksum(self): + raise NotImplementedError + + @property + @abstractmethod + def filename(self): + raise NotImplementedError + + +@dataclass +class WrapFile(Wrap): + source_url: str | None = None + source_fallback_url: str | None = None + source_filename: str | None = None + source_hash: str | None = None + lead_directory_missing: str | None = None + + @property + def distfile(self): + if self.source_url: + return f"{self.source_url}>{self.filename}" + raise ValueError(f"missing source_url in wrap {self.src_path}") + + @property + def checksum(self): + if self.source_hash: + return self.source_hash + raise ValueError(f"missing source_hash in wrap {self.src_path}") + + @property + def filename(self): + if self.source_filename: + return self.source_filename + raise ValueError(f"missing source_filename in wrap {self.src_path}") + + +def read_wrap(p: Path) -> Wrap: + wrap = ConfigParser() + with p.open() as f: + wrap.read_file(f) + + for sec in wrap.sections(): + if sec.startswith("wrap-"): + break + else: + raise ValueError(f"missing 'wrap-*' section in wrap {p}") + + match sec: + case "wrap-file": + cls = WrapFile + case "wrap-git": + raise NotImplementedError + case "wrap-hg": + raise NotImplementedError + case "wrap-svn": + raise NotImplementedError + case _: + raise NotImplementedError + + return cls(src_path=p, **dict(wrap.items(sec))) + + +def print_list(var: str, contents: list[str]): + print(f"""{var}+=" + {"\n ".join(contents)} +\"""") + + +if __name__ == "__main__": + distfiles = [] + checksums = [] + skip_extracts = [] + + if len(sys.argv[1:]) < 1: + print(f"usage: {sys.argv[0]} ") + exit() + + for arg in sys.argv[1:]: + wrap_path = Path(arg) + if wrap_path.is_file(): + try: + wrap = read_wrap(wrap_path) + + distfiles.append(wrap.distfile) + checksums.append(wrap.checksum) + skip_extracts.append(wrap.filename) + except ValueError as e: + print("=> ERROR:", e, file=sys.stderr) + + print_list("distfiles", distfiles) + print_list("checksum", checksums) + print_list("skip_extraction", skip_extracts)