Skip to content

Commit 2486864

Browse files
committed
mmpack-build: Guess build-depends
Add mechanism to automatically guess build depends and update the source package specs accordingly during mmpack source tarball build. The guess mechanism is configured by the section 'guess-build-depends' in mmpack/sources-strap file. Change-Id: I7e5a7ef2be678e1a130de29257ea45250adc52b7
1 parent 15555ca commit 2486864

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

docs/specs/package-sources-strap.rst

+45
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,38 @@ others.
5050
:patches:
5151
list of patch files to applied on upstream sources after fetching them
5252

53+
:guess-build-depends:
54+
Contains a dictionnary representing the configuration of the mechanism
55+
guessing the build-depends to add in package specs.
56+
57+
The guess-build-depends section
58+
```````````````````````````````
59+
It is possible to avoid to explicitly specify the build dependencies in the
60+
package specs and to guess them from project sources. In such a case the
61+
build-depends section of mmpack/specs is added when the mmpack source package
62+
is created, the guessed dependencies being specified in addition to possible
63+
build dependencies set already in package specs. The guess mechanism performed
64+
per build system (not all are supported).
65+
66+
Several fields control the guess mechanism:
67+
68+
:from:
69+
string or list of string of all build system that must be inspected. Can be
70+
python or all. If unset, all build system section listed are implied
71+
72+
<build-system>
73+
Only python is currently supported.
74+
75+
The <build-system> section
76+
..........................
77+
:ignore:
78+
list of guessed used dependencies that must not generate a mmpack build
79+
dependency.
80+
81+
:remap:
82+
dictionary of used dependencies associated to the mmpack package name to
83+
use in the build-depends list. Use it to fix a bad guessed package name.
84+
5385

5486
Token expansion
5587
---------------
@@ -73,3 +105,16 @@ Examples
73105
method: tar
74106
url: https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.24.0.tar.xz
75107
sha256: 9f71d61973626d8b28c4cdf8e2484b4bf13870ed643fed982d68b2cfd754371b
108+
109+
.. code-block:: yaml
110+
111+
guess-build-depends:
112+
from: python
113+
114+
.. code-block:: yaml
115+
116+
guess-build-depends:
117+
python:
118+
ignore: [Setuptools]
119+
remap:
120+
PyYaml: python3-yaml

src/mmpack_build/builddeps_guess.py

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# @mindmaze_header@
2+
"""
3+
Guess build_dependencies from sources
4+
"""
5+
6+
from copy import deepcopy
7+
from typing import Any, Iterator
8+
9+
from .source_strap_specs import SourceStrapSpecs
10+
11+
12+
class _BuilddepsGuess:
13+
def __init__(self, cfg: dict[str, Any]):
14+
self._ignore = set(cfg.get('ignore', []))
15+
self._remap = cfg.get('remap', {})
16+
17+
def _iter_guessed_used_builddeps(self, srcdir: str) -> Iterator[str]:
18+
raise NotImplementedError
19+
20+
def _get_mmpack_dep(self, used: str) -> str:
21+
raise NotImplementedError
22+
23+
def guess(self, srcdir: str) -> set[str]:
24+
"""Get the set of mmpack package guessed to be build dependencies."""
25+
used_deps = set(self._iter_guessed_used_builddeps(srcdir))
26+
used_deps.difference_update(self._ignore)
27+
return {self._remap.get(u, self._get_mmpack_dep(u))
28+
for u in used_deps}
29+
30+
31+
_GUESS_BACKENDS: dict[str, _BuilddepsGuess] = {
32+
}
33+
34+
35+
def guess_build_depends(specs: SourceStrapSpecs, srcdir: str) -> set[str]:
36+
"""
37+
Guess the build depends according to mmpack/sources-strap config
38+
39+
Arguments:
40+
specs: specs defined in sources-strap
41+
srcdir: path to sources
42+
"""
43+
cfg = deepcopy(specs.get('guess-build-depends', {}))
44+
from_builders = cfg.pop('from', None)
45+
if from_builders is None:
46+
from_builders = list(cfg.keys())
47+
elif from_builders == 'all':
48+
from_builders = list(_GUESS_BACKENDS.keys())
49+
elif isinstance(from_builders, str):
50+
from_builders = [from_builders]
51+
elif not isinstance(from_builders, list):
52+
raise ValueError('guess-build-depends/from key in mmpack/sources-strap'
53+
' must be a list or single string')
54+
55+
# Run builddeps guess for all listed backends
56+
guessed_deps = set()
57+
for builder in from_builders:
58+
backend_cls = _GUESS_BACKENDS[builder]
59+
backend = backend_cls(cfg.get(builder, {}))
60+
guessed_deps.update(backend.guess(srcdir))
61+
62+
return guessed_deps

src/mmpack_build/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mmpack_build_sources = files(
1919
'__main__.py',
2020
'base_hook.py',
2121
'binary_package.py',
22+
'builddeps_guess.py',
2223
'common.py',
2324
'decorators.py',
2425
'elf_utils.py',

src/mmpack_build/source_tarball.py

+20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .prefix import new_mmpack_prefix_context, prefix_install, run_build_script
2020
from .source_strap_specs import SourceStrapSpecs
2121
from .workspace import Workspace, cached_download, find_project_root_folder
22+
from .builddeps_guess import guess_build_depends
2223

2324

2425
class ProjectSource(NamedTuple):
@@ -291,6 +292,8 @@ def _process_source_strap(self, srcdir):
291292
self._run_build_script('source_strapped',
292293
specs.upstream_method or 'none', srcdir)
293294

295+
self._guess_build_depends(specs, srcdir)
296+
294297
def _run_build_script(self, name: str, method: str,
295298
execdir: str, env: Optional[Dict[str, str]] = None):
296299
if env is None:
@@ -558,3 +561,20 @@ def _patch_sources(self, patches: List[str], srcdir: str):
558561
run_cmd(['patch', '-d', srcdir, '-p1'], stdin=patchfile)
559562

560563
self.trace['patches'] = patches
564+
565+
@staticmethod
566+
def _guess_build_depends(specs: SourceStrapSpecs, srcdir: str):
567+
guessed_deps = guess_build_depends(specs, srcdir)
568+
569+
specs_path = join_path(srcdir, 'mmpack/specs')
570+
build_depends = specs_load(specs_path).get('build-depends', [])
571+
572+
guessed_deps.difference_update(set(build_depends))
573+
if not guessed_deps:
574+
return
575+
576+
# Add updated build dependencies at the end of specs.
577+
with open(specs_path, 'a', encoding='utf-8') as stream:
578+
stream.write('build-depends:\n')
579+
for dep in build_depends + list(guessed_deps):
580+
stream.write(f'- {dep}\n')

0 commit comments

Comments
 (0)