Skip to content

Commit c5fb251

Browse files
committed
common/scripts: add script to generate distfiles from meson wrap files, vextract_subproject function
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.
1 parent ff4c6dc commit c5fb251

File tree

3 files changed

+137
-1
lines changed

3 files changed

+137
-1
lines changed

Manual.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,8 @@ additional paths to be searched when linking target binaries to be introspected.
11071107
- `meson` creates a cross file, `${XBPS_WRAPPERDIR}/meson/xbps_meson.cross`, which configures
11081108
meson for cross builds. This is particularly useful for building packages that wrap meson
11091109
invocations (e.g., `python3-pep517` packages that use a meson backend) and is added by default
1110-
for packages that use the `meson` build style.
1110+
for packages that use the `meson` build style. It also creates the `vextract_subproject` function,
1111+
which extracts a distfile and sets it up as a vendored meson wrap.
11111112

11121113
- `numpy` configures the environment for cross-compilation of python packages that provide
11131114
compiled extensions linking to NumPy C libraries. If the `meson` build helper is also

common/build-helper/meson.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# This build helper writes a Meson cross-file, allowing other build styles
22
# to properly drive cross-builds in Meson when appropriate
33

4+
# helper function to extract and set up a subproject
5+
vextract_subproject() {
6+
local source_filename="$1" directory="$2" patch_directory="$3"
7+
vsrcextract -C "subprojects/${directory}" "${source_filename}"
8+
cp -t "subprojects/${directory}" "subprojects/packagefiles/${patch_directory}/meson.build"
9+
}
10+
411
# Action is only taken for cross builds
512
[ -z "$CROSS_BUILD" ] && return 0
613

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/usr/bin/python3
2+
3+
import sys
4+
from abc import ABC, abstractmethod
5+
from configparser import ConfigParser
6+
from dataclasses import dataclass
7+
from pathlib import Path
8+
9+
@dataclass
10+
class Wrap(ABC):
11+
src_path: Path
12+
13+
directory: str | None = None
14+
patch_url: str | None = None
15+
patch_fallback_url: str | None = None
16+
patch_filename: str | None = None
17+
patch_hash: str | None = None
18+
patch_directory: str | None = None
19+
diff_files: str | None = None
20+
method: str | None = None
21+
22+
@property
23+
@abstractmethod
24+
def distfile(self):
25+
raise NotImplementedError
26+
27+
@property
28+
@abstractmethod
29+
def checksum(self):
30+
raise NotImplementedError
31+
32+
@property
33+
@abstractmethod
34+
def filename(self):
35+
raise NotImplementedError
36+
37+
38+
@dataclass
39+
class WrapFile(Wrap):
40+
source_url: str | None = None
41+
source_fallback_url: str | None = None
42+
source_filename: str | None = None
43+
source_hash: str | None = None
44+
lead_directory_missing: str | None = None
45+
46+
@property
47+
def distfile(self):
48+
if self.source_url:
49+
return f"{self.source_url}>{self.filename}"
50+
raise ValueError(f"missing source_url in wrap {self.src_path}")
51+
52+
@property
53+
def checksum(self):
54+
if self.source_hash:
55+
return self.source_hash
56+
raise ValueError(f"missing source_hash in wrap {self.src_path}")
57+
58+
@property
59+
def filename(self):
60+
if self.source_filename:
61+
return self.source_filename
62+
raise ValueError(f"missing source_filename in wrap {self.src_path}")
63+
64+
65+
def read_wrap(p: Path) -> Wrap:
66+
wrap = ConfigParser()
67+
with p.open() as f:
68+
wrap.read_file(f)
69+
70+
for sec in wrap.sections():
71+
if sec.startswith("wrap-"):
72+
break
73+
else:
74+
raise ValueError(f"missing 'wrap-*' section in wrap {p}")
75+
76+
match sec:
77+
case "wrap-file":
78+
cls = WrapFile
79+
case "wrap-git":
80+
raise NotImplementedError
81+
case "wrap-hg":
82+
raise NotImplementedError
83+
case "wrap-svn":
84+
raise NotImplementedError
85+
case _:
86+
raise NotImplementedError
87+
88+
return cls(src_path=p, **dict(wrap.items(sec)))
89+
90+
91+
def print_delim(initial: str, delim: str | tuple[str, str], fmt: str, contents: list[str]):
92+
if isinstance(delim, tuple):
93+
s_delim, e_delim = delim
94+
else:
95+
s_delim, e_delim = delim, delim
96+
print(f"""{initial}{s_delim}
97+
{"\n".join(fmt.format(v=v) for v in contents)}
98+
{e_delim}""")
99+
100+
101+
if __name__ == "__main__":
102+
distfiles = []
103+
checksums = []
104+
skip_extracts = []
105+
subprojs = []
106+
107+
if len(sys.argv[1:]) < 1:
108+
print(f"usage: {sys.argv[0]} <wrap files...>")
109+
exit()
110+
111+
for arg in sys.argv[1:]:
112+
wrap_path = Path(arg)
113+
if wrap_path.is_file():
114+
try:
115+
wrap = read_wrap(wrap_path)
116+
117+
distfiles.append(wrap.distfile)
118+
checksums.append(wrap.checksum)
119+
skip_extracts.append(wrap.filename)
120+
subprojs.append((wrap.filename, wrap.directory, wrap.patch_directory))
121+
except ValueError as e:
122+
print("=> ERROR:", e, file=sys.stderr)
123+
124+
print_delim("distfiles+=", '"', " {v}", distfiles)
125+
print_delim("checksum+=", '"', " {v}", checksums)
126+
print_delim("skip_extraction+=", '"', " {v}", skip_extracts)
127+
print()
128+
print_delim("_extract_subprojects() ", ("{", "}"), "\tvextract_subproject '{v[0]}' '{v[1]}' '{v[2]}'", subprojs)

0 commit comments

Comments
 (0)