From 3c1ccb923fc110fa86893b3e7cbbfa0b75c9a4dc Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 22 Jul 2020 09:16:55 -0400 Subject: [PATCH 1/5] logs: Prepend current subproject name to all messages Meson used to prepend '|' for each nested subproject to distinguish in the logs where a subproject start and ends. It is more useful to print the current subproject name. Also print the call stack when starting a new subproject to better see which subproject chain leads to to. --- mesonbuild/interpreter.py | 13 +++++++------ mesonbuild/mlog.py | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 5cf3dde9a..2e4444ccd 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2912,8 +2912,9 @@ external dependencies (including libraries) must go to "dependencies".''') self.global_args_frozen = True mlog.log() - with mlog.nested(): - mlog.log('Executing subproject', mlog.bold(subp_name), 'method', mlog.bold(method), '\n') + with mlog.nested(subp_name): + stack = ':'.join(self.subproject_stack + [subp_name]) + mlog.log('Executing subproject', mlog.bold(stack), 'method', mlog.bold(method), '\n') try: if method == 'meson': return self._do_subproject_meson(subp_name, subdir, default_options, kwargs) @@ -2926,7 +2927,7 @@ external dependencies (including libraries) must go to "dependencies".''') raise except Exception as e: if not required: - with mlog.nested(): + with mlog.nested(subp_name): # Suppress the 'ERROR:' prefix because this exception is not # fatal and VS CI treat any logs with "ERROR:" as fatal. mlog.exception(e, prefix=mlog.yellow('Exception:')) @@ -2938,7 +2939,7 @@ external dependencies (including libraries) must go to "dependencies".''') ast: T.Optional[mparser.CodeBlockNode] = None, build_def_files: T.Optional[T.List[str]] = None, is_translated: bool = False) -> SubprojectHolder: - with mlog.nested(): + with mlog.nested(subp_name): new_build = self.build.copy() subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir, self.modules, default_options, ast=ast, is_translated=is_translated) @@ -2975,7 +2976,7 @@ external dependencies (including libraries) must go to "dependencies".''') return self.subprojects[subp_name] def _do_subproject_cmake(self, subp_name, subdir, subdir_abs, default_options, kwargs): - with mlog.nested(): + with mlog.nested(subp_name): new_build = self.build.copy() prefix = self.coredata.options[OptionKey('prefix')].value @@ -2995,7 +2996,7 @@ external dependencies (including libraries) must go to "dependencies".''') ast = cm_int.pretend_to_be_meson(options.target_options) mlog.log() - with mlog.nested(): + with mlog.nested('cmake-ast'): mlog.log('Processing generated meson AST') # Debug print the generated meson file diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index 15fdb8d14..c1c323ba7 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -69,7 +69,7 @@ def setup_console() -> None: log_dir = None # type: T.Optional[str] log_file = None # type: T.Optional[T.TextIO] log_fname = 'meson-log.txt' # type: str -log_depth = 0 # type: int +log_depth = [] # type: T.List[str] log_timestamp_start = None # type: T.Optional[float] log_fatal_warnings = False # type: bool log_disable_stdout = False # type: bool @@ -209,8 +209,8 @@ def force_print(*args: str, **kwargs: T.Any) -> None: print(*args, **kwargs) raw = iostr.getvalue() - if log_depth > 0: - prepend = '|' * log_depth + if log_depth: + prepend = log_depth[-1] + '|' raw = prepend + raw.replace('\n', '\n' + prepend, raw.count('\n') - 1) # _Something_ is going to get printed. @@ -370,10 +370,10 @@ def format_list(input_list: T.List[str]) -> str: return '' @contextmanager -def nested() -> T.Generator[None, None, None]: +def nested(name: str = '') -> T.Generator[None, None, None]: global log_depth - log_depth += 1 + log_depth.append(name) try: yield finally: - log_depth -= 1 + log_depth.pop() From b33e7bca73007aeec92ecada5642ce6fd08d6f58 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 10 Mar 2021 14:08:52 -0500 Subject: [PATCH 2/5] mlog: Add a space after 'subproject|' --- mesonbuild/mlog.py | 2 +- run_unittests.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index c1c323ba7..c7d586500 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -210,7 +210,7 @@ def force_print(*args: str, **kwargs: T.Any) -> None: raw = iostr.getvalue() if log_depth: - prepend = log_depth[-1] + '|' + prepend = log_depth[-1] + '| ' raw = prepend + raw.replace('\n', '\n' + prepend, raw.count('\n') - 1) # _Something_ is going to get printed. diff --git a/run_unittests.py b/run_unittests.py index c22f884b0..28ef486d4 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -4180,12 +4180,12 @@ class AllPlatformTests(BasePlatformTests): # Parent project warns correctly self.assertRegex(out, "WARNING: Project targeting '>=0.45'.*'0.47.0': dict") # Subprojects warn correctly - self.assertRegex(out, r"\|WARNING: Project targeting '>=0.40'.*'0.44.0': disabler") - self.assertRegex(out, r"\|WARNING: Project targeting '!=0.40'.*'0.44.0': disabler") + self.assertRegex(out, r"\| WARNING: Project targeting '>=0.40'.*'0.44.0': disabler") + self.assertRegex(out, r"\| WARNING: Project targeting '!=0.40'.*'0.44.0': disabler") # Subproject has a new-enough meson_version, no warning self.assertNotRegex(out, "WARNING: Project targeting.*Python") # Ensure a summary is printed in the subproject and the outer project - self.assertRegex(out, r"\|WARNING: Project specifies a minimum meson_version '>=0.40'") + self.assertRegex(out, r"\| WARNING: Project specifies a minimum meson_version '>=0.40'") self.assertRegex(out, r"\| \* 0.44.0: {'disabler'}") self.assertRegex(out, "WARNING: Project specifies a minimum meson_version '>=0.45'") self.assertRegex(out, " * 0.47.0: {'dict'}") From 60c2c25d5bb2378b2d8da9ba6b9693a3111f27f5 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 10 Mar 2021 14:11:24 -0500 Subject: [PATCH 3/5] mlog: Do not print 'subproject|' on empty lines --- mesonbuild/mlog.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index c7d586500..c51922aa7 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -211,7 +211,11 @@ def force_print(*args: str, **kwargs: T.Any) -> None: raw = iostr.getvalue() if log_depth: prepend = log_depth[-1] + '| ' - raw = prepend + raw.replace('\n', '\n' + prepend, raw.count('\n') - 1) + lines = [] + for l in raw.split('\n'): + l = l.strip() + lines.append(prepend + l if l else '') + raw = '\n'.join(lines) # _Something_ is going to get printed. try: From 7c3418204f824a613c67e7ccd06ef6983656e904 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 10 Mar 2021 14:17:11 -0500 Subject: [PATCH 4/5] interpreter: Do not print "method meson" --- mesonbuild/interpreter.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 2e4444ccd..8653b385e 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2914,7 +2914,11 @@ external dependencies (including libraries) must go to "dependencies".''') mlog.log() with mlog.nested(subp_name): stack = ':'.join(self.subproject_stack + [subp_name]) - mlog.log('Executing subproject', mlog.bold(stack), 'method', mlog.bold(method), '\n') + m = ['Executing subproject', mlog.bold(stack)] + if method != 'meson': + m += ['method', mlog.bold(method)] + mlog.log(*m,'\n') + try: if method == 'meson': return self._do_subproject_meson(subp_name, subdir, default_options, kwargs) From 8cd4d0b2832666f19660b9006040e5ff7e5d4576 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 10 Mar 2021 14:19:48 -0500 Subject: [PATCH 5/5] mlog: Do not print 'subproject|' for the message 'Executing subproject' It already contains the full callstack and it's more visible when it's standing on its own line. --- mesonbuild/interpreter.py | 12 +++++------- mesonbuild/mlog.py | 7 ++++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 8653b385e..4dcb48cbe 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2911,13 +2911,11 @@ external dependencies (including libraries) must go to "dependencies".''') os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.global_args_frozen = True - mlog.log() - with mlog.nested(subp_name): - stack = ':'.join(self.subproject_stack + [subp_name]) - m = ['Executing subproject', mlog.bold(stack)] - if method != 'meson': - m += ['method', mlog.bold(method)] - mlog.log(*m,'\n') + stack = ':'.join(self.subproject_stack + [subp_name]) + m = ['\nExecuting subproject', mlog.bold(stack)] + if method != 'meson': + m += ['method', mlog.bold(method)] + mlog.log(*m,'\n', nested=False) try: if method == 'meson': diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index c51922aa7..38a4805b3 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -201,7 +201,7 @@ def process_markup(args: T.Sequence[T.Union[AnsiDecorator, str]], keep: bool) -> arr.append(str(arg)) return arr -def force_print(*args: str, **kwargs: T.Any) -> None: +def force_print(*args: str, nested: str, **kwargs: T.Any) -> None: if log_disable_stdout: return iostr = io.StringIO() @@ -210,7 +210,7 @@ def force_print(*args: str, **kwargs: T.Any) -> None: raw = iostr.getvalue() if log_depth: - prepend = log_depth[-1] + '| ' + prepend = log_depth[-1] + '| ' if nested else '' lines = [] for l in raw.split('\n'): l = l.strip() @@ -250,6 +250,7 @@ def log(*args: T.Union[str, AnsiDecorator], is_error: bool = False, def _log(*args: T.Union[str, AnsiDecorator], is_error: bool = False, **kwargs: T.Any) -> None: + nested = kwargs.pop('nested', True) arr = process_markup(args, False) if log_file is not None: print(*arr, file=log_file, **kwargs) @@ -257,7 +258,7 @@ def _log(*args: T.Union[str, AnsiDecorator], is_error: bool = False, if colorize_console(): arr = process_markup(args, True) if not log_errors_only or is_error: - force_print(*arr, **kwargs) + force_print(*arr, nested=nested, **kwargs) def log_once(*args: T.Union[str, AnsiDecorator], is_error: bool = False, **kwargs: T.Any) -> None: