aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2021-01-21 12:33:27 +0100
committerXavier Claessens <xclaesse@gmail.com>2021-01-21 08:54:35 -0500
commitadb1b2f3f6ad54b346348ec6e5b8d96f2f7ba0a6 (patch)
treee18fe1b3cfb0f32b76ecaa456fdd3b0a2599b53d
parent021068a8b7461a62ed4ce68ab558bc94786e0550 (diff)
downloadmeson-adb1b2f3f6ad54b346348ec6e5b8d96f2f7ba0a6.zip
meson-adb1b2f3f6ad54b346348ec6e5b8d96f2f7ba0a6.tar.gz
meson-adb1b2f3f6ad54b346348ec6e5b8d96f2f7ba0a6.tar.bz2
interpreter: accept external programs and dependencies for summary
-rw-r--r--docs/markdown/Reference-manual.md6
-rw-r--r--docs/markdown/snippets/summary_prog_dep.md4
-rw-r--r--mesonbuild/dependencies/base.py17
-rw-r--r--mesonbuild/interpreter.py18
-rw-r--r--mesonbuild/mlog.py12
-rwxr-xr-xrun_unittests.py6
-rw-r--r--test cases/unit/73 summary/meson.build5
7 files changed, 60 insertions, 8 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 802002b..cb8347a 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1313,7 +1313,11 @@ The content is a series of key/value pairs grouped into sections. If the section
keyword argument is omitted, those key/value pairs are implicitly grouped into a section
with no title. key/value pairs can optionally be grouped into a dictionary,
but keep in mind that dictionaries does not guarantee ordering. `key` must be string,
-`value` can only be integer, boolean, string, or a list of those.
+`value` can be:
+
+- an integer, boolean or string
+- *since 0.57.0* an external program or a dependency
+- a list of those.
`summary()` can be called multiple times as long as the same section/key
pair doesn't appear twice. All sections will be collected and printed at
diff --git a/docs/markdown/snippets/summary_prog_dep.md b/docs/markdown/snippets/summary_prog_dep.md
new file mode 100644
index 0000000..6f0262f
--- /dev/null
+++ b/docs/markdown/snippets/summary_prog_dep.md
@@ -0,0 +1,4 @@
+## `summary()` accepts external programs or dependencies
+
+External program objects and dependency objects can be passed to
+`summary()` as the value to be printed.
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index e72f346..cd77b4b 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -134,6 +134,13 @@ class Dependency:
def is_built(self) -> bool:
return False
+ def summary_value(self) -> T.Union[str, mlog.AnsiDecorator, mlog.AnsiText]:
+ if not self.found():
+ return mlog.red('NO')
+ if not self.version:
+ return mlog.green('YES')
+ return mlog.AnsiText(mlog.green('YES'), ' ', mlog.cyan(self.version))
+
def get_compile_args(self) -> T.List[str]:
if self.include_type == 'system':
converted = []
@@ -263,6 +270,11 @@ class InternalDependency(Dependency):
setattr(result, k, copy.deepcopy(v, memo))
return result
+ def summary_value(self) -> mlog.AnsiDecorator:
+ # Omit the version. Most of the time it will be just the project
+ # version, which is uninteresting in the summary.
+ return mlog.green('YES')
+
def is_built(self) -> bool:
if self.sources or self.libraries or self.whole_libraries:
return True
@@ -1888,6 +1900,11 @@ class ExternalProgram:
else:
mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO'))
+ def summary_value(self) -> T.Union[str, mlog.AnsiDecorator]:
+ if not self.found():
+ return mlog.red('NO')
+ return self.path
+
def __repr__(self) -> str:
r = '<{} {!r} -> {!r}>'
return r.format(self.__class__.__name__, self.name, self.command)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 817204f..a3fa050 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1854,7 +1854,7 @@ class Summary:
self.sections = collections.defaultdict(dict)
self.max_key_len = 0
- def add_section(self, section, values, kwargs):
+ def add_section(self, section, values, kwargs, subproject):
bool_yn = kwargs.get('bool_yn', False)
if not isinstance(bool_yn, bool):
raise InterpreterException('bool_yn keyword argument must be boolean')
@@ -1866,13 +1866,17 @@ class Summary:
raise InterpreterException('Summary section {!r} already have key {!r}'.format(section, k))
formatted_values = []
for i in listify(v):
- if not isinstance(i, (str, int)):
- m = 'Summary value in section {!r}, key {!r}, must be string, integer or boolean'
- raise InterpreterException(m.format(section, k))
- if bool_yn and isinstance(i, bool):
+ i = unholder(i)
+ if isinstance(i, bool) and bool_yn:
formatted_values.append(mlog.green('YES') if i else mlog.red('NO'))
- else:
+ elif isinstance(i, (str, int, bool)):
formatted_values.append(str(i))
+ elif isinstance(i, (ExternalProgram, Dependency)):
+ FeatureNew.single_use('dependency or external program in summary', '0.57.0', subproject)
+ formatted_values.append(i.summary_value())
+ else:
+ m = 'Summary value in section {!r}, key {!r}, must be string, integer, boolean, dependency or external program'
+ raise InterpreterException(m.format(section, k))
self.sections[section][k] = (formatted_values, list_sep)
self.max_key_len = max(self.max_key_len, len(k))
@@ -3284,7 +3288,7 @@ external dependencies (including libraries) must go to "dependencies".''')
def summary_impl(self, section, values, kwargs):
if self.subproject not in self.summary:
self.summary[self.subproject] = Summary(self.active_projectname, self.project_version)
- self.summary[self.subproject].add_section(section, values, kwargs)
+ self.summary[self.subproject].add_section(section, values, kwargs, self.subproject)
def _print_summary(self):
# Add automatic 'Supbrojects' section in main project.
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index a6aa2b5..20794df 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -136,6 +136,18 @@ class AnsiDecorator:
def __str__(self) -> str:
return self.get_text(colorize_console())
+
+class AnsiText:
+ def __init__(self, *args: T.List[T.Union[str, AnsiDecorator]]):
+ self.args = args
+
+ def __len__(self) -> int:
+ return sum((len(x) for x in self.args))
+
+ def __str__(self) -> str:
+ return ''.join((str(x) for x in self.args))
+
+
def bold(text: str, quoted: bool = False) -> AnsiDecorator:
return AnsiDecorator(text, "\033[1m", quoted=quoted)
diff --git a/run_unittests.py b/run_unittests.py
index da6d329..b244a07 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4707,6 +4707,12 @@ class AllPlatformTests(BasePlatformTests):
no : NO
coma list : a, b, c
+ Stuff
+ missing prog : NO
+ existing prog : ''' + sys.executable + '''
+ missing dep : NO
+ internal dep : YES
+
Plugins
long coma list : alpha, alphacolor, apetag, audiofx, audioparsers, auparse,
autodetect, avi
diff --git a/test cases/unit/73 summary/meson.build b/test cases/unit/73 summary/meson.build
index 1bc05ca..50383b4 100644
--- a/test cases/unit/73 summary/meson.build
+++ b/test cases/unit/73 summary/meson.build
@@ -9,6 +9,11 @@ summary({'Some boolean': false,
'A list': ['string', 1, true],
'empty list': [],
}, section: 'Configuration')
+summary({'missing prog': find_program('xyzzy', required: false),
+ 'existing prog': import('python').find_installation(),
+ 'missing dep': dependency('', required: false),
+ 'internal dep': declare_dependency(),
+ }, section: 'Stuff')
summary('A number', 1, section: 'Configuration')
summary('yes', true, bool_yn : true, section: 'Configuration')
summary('no', false, bool_yn : true, section: 'Configuration')