aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/cmake/traceparser.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/cmake/traceparser.py')
-rw-r--r--mesonbuild/cmake/traceparser.py84
1 files changed, 62 insertions, 22 deletions
diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py
index 7b29c86..8eb8605 100644
--- a/mesonbuild/cmake/traceparser.py
+++ b/mesonbuild/cmake/traceparser.py
@@ -47,6 +47,8 @@ class CMakeTarget:
self.imported = imported
self.tline = tline
self.depends = []
+ self.current_bin_dir = None
+ self.current_src_dir = None
def __repr__(self):
s = 'CMake TARGET:\n -- name: {}\n -- type: {}\n -- imported: {}\n -- properties: {{\n{} }}\n -- tline: {}'
@@ -83,6 +85,36 @@ class CMakeTraceParser:
self.trace_file_path = Path(build_dir) / self.trace_file
self.trace_format = 'json-v1' if version_compare(cmake_version, '>=3.17') else 'human'
+ # State for delayed command execution. Delayed command execution is realised
+ # with a custom CMake file that overrides some functions and adds some
+ # introspection information to the trace.
+ self.delayed_commands = [] # type: T.List[str]
+ self.stored_commands = [] # type: T.List[CMakeTraceLine]
+
+ # All supported functions
+ self.functions = {
+ 'set': self._cmake_set,
+ 'unset': self._cmake_unset,
+ 'add_executable': self._cmake_add_executable,
+ 'add_library': self._cmake_add_library,
+ 'add_custom_command': self._cmake_add_custom_command,
+ 'add_custom_target': self._cmake_add_custom_target,
+ 'set_property': self._cmake_set_property,
+ 'set_target_properties': self._cmake_set_target_properties,
+ 'target_compile_definitions': self._cmake_target_compile_definitions,
+ 'target_compile_options': self._cmake_target_compile_options,
+ 'target_include_directories': self._cmake_target_include_directories,
+ 'target_link_libraries': self._cmake_target_link_libraries,
+ 'target_link_options': self._cmake_target_link_options,
+ 'add_dependencies': self._cmake_add_dependencies,
+
+ # Special functions defined in the preload script.
+ # These functions do nothing in the CMake code, but have special
+ # meaning here in the trace parser.
+ 'meson_ps_execute_delayed_calls': self._meson_ps_execute_delayed_calls,
+ 'meson_ps_reload_vars': self._meson_ps_reload_vars,
+ }
+
def trace_args(self) -> T.List[str]:
arg_map = {
'human': ['--trace', '--trace-expand'],
@@ -116,28 +148,15 @@ class CMakeTraceParser:
else:
raise CMakeException('CMake: Internal error: Invalid trace format {}. Expected [human, json-v1]'.format(self.trace_format))
- # All supported functions
- functions = {
- 'set': self._cmake_set,
- 'unset': self._cmake_unset,
- 'add_executable': self._cmake_add_executable,
- 'add_library': self._cmake_add_library,
- 'add_custom_command': self._cmake_add_custom_command,
- 'add_custom_target': self._cmake_add_custom_target,
- 'set_property': self._cmake_set_property,
- 'set_target_properties': self._cmake_set_target_properties,
- 'target_compile_definitions': self._cmake_target_compile_definitions,
- 'target_compile_options': self._cmake_target_compile_options,
- 'target_include_directories': self._cmake_target_include_directories,
- 'target_link_libraries': self._cmake_target_link_libraries,
- 'target_link_options': self._cmake_target_link_options,
- 'add_dependencies': self._cmake_add_dependencies,
- }
-
# Primary pass -- parse everything
for l in lexer1:
+ # store the function if its execution should be delayed
+ if l.func in self.delayed_commands:
+ self.stored_commands += [l]
+ continue
+
# "Execute" the CMake function if supported
- fn = functions.get(l.func, None)
+ fn = self.functions.get(l.func, None)
if(fn):
fn(l)
@@ -160,6 +179,12 @@ class CMakeTraceParser:
return []
+ def var_to_str(self, var: str) -> T.Optional[str]:
+ if var in self.vars and self.vars[var]:
+ return self.vars[var][0]
+
+ return None
+
def var_to_bool(self, var):
if var not in self.vars:
return False
@@ -300,7 +325,7 @@ class CMakeTraceParser:
target = CMakeGeneratorTarget(name)
def handle_output(key: str, target: CMakeGeneratorTarget) -> None:
- target.outputs += [key]
+ target.outputs += key.split(';')
def handle_command(key: str, target: CMakeGeneratorTarget) -> None:
if key == 'ARGS':
@@ -308,7 +333,7 @@ class CMakeTraceParser:
target.command[-1] += key.split(';')
def handle_depends(key: str, target: CMakeGeneratorTarget) -> None:
- target.depends += [key]
+ target.depends += key.split(';')
def handle_working_dir(key: str, target: CMakeGeneratorTarget) -> None:
if target.working_dir is None:
@@ -337,6 +362,8 @@ class CMakeTraceParser:
if fn is not None:
fn(i, target)
+ target.current_bin_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_BINARY_DIR')
+ target.current_src_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR')
target.outputs = self._guess_files(target.outputs)
target.depends = self._guess_files(target.depends)
target.command = [self._guess_files(x) for x in target.command]
@@ -465,7 +492,8 @@ class CMakeTraceParser:
if not target:
return self._gen_exception('add_dependencies', 'target not found', tline)
- target.depends += args[1:]
+ for i in args[1:]:
+ target.depends += i.split(';')
def _cmake_target_compile_definitions(self, tline: CMakeTraceLine) -> None:
# DOC: https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
@@ -531,6 +559,18 @@ class CMakeTraceParser:
self.targets[target].properties[i[0]] += i[1]
+ def _meson_ps_execute_delayed_calls(self, tline: CMakeTraceLine) -> None:
+ for l in self.stored_commands:
+ fn = self.functions.get(l.func, None)
+ if(fn):
+ fn(l)
+
+ # clear the stored commands
+ self.stored_commands = []
+
+ def _meson_ps_reload_vars(self, tline: CMakeTraceLine) -> None:
+ self.delayed_commands = self.get_cmake_var('MESON_PS_DELAYED_CALLS')
+
def _lex_trace_human(self, trace):
# The trace format is: '<file>(<line>): <func>(<args -- can contain \n> )\n'
reg_tline = re.compile(r'\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(([\s\S]*?) ?\)\s*\n', re.MULTILINE)