aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/cmake
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2021-05-28 23:35:19 +0200
committerDaniel Mensinger <daniel@mensinger-ka.de>2021-05-29 13:20:25 +0200
commit0e777e7c90d5ac89b457621aa96a513dce0d3e2f (patch)
tree3203b4666ad0e76ad72dfd84988d080b0269028a /mesonbuild/cmake
parent25fa2d4f7ba0978d8a224cf2cba3d697a3bbfb3d (diff)
downloadmeson-0e777e7c90d5ac89b457621aa96a513dce0d3e2f.zip
meson-0e777e7c90d5ac89b457621aa96a513dce0d3e2f.tar.gz
meson-0e777e7c90d5ac89b457621aa96a513dce0d3e2f.tar.bz2
cmake: CMakeTraceParser improvements
- handle cached CMake variables differently - associate variables with source files - better performance (str to Path and generator expressions)
Diffstat (limited to 'mesonbuild/cmake')
-rw-r--r--mesonbuild/cmake/generator.py4
-rw-r--r--mesonbuild/cmake/traceparser.py54
2 files changed, 45 insertions, 13 deletions
diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py
index 02d56cc..848fdf9 100644
--- a/mesonbuild/cmake/generator.py
+++ b/mesonbuild/cmake/generator.py
@@ -23,6 +23,10 @@ def parse_generator_expressions(raw: str) -> str:
use cases.
'''
+ # Early abort if no generator expression present
+ if '$<' not in raw:
+ return raw
+
out = '' # type: str
i = 0 # type: int
diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py
index 6294fa1..23a1852 100644
--- a/mesonbuild/cmake/traceparser.py
+++ b/mesonbuild/cmake/traceparser.py
@@ -22,21 +22,31 @@ from ..mesonlib import version_compare
import typing as T
from pathlib import Path
+from functools import lru_cache
import re
import json
import textwrap
class CMakeTraceLine:
- def __init__(self, file: Path, line: int, func: str, args: T.List[str]) -> None:
- self.file = file
+ def __init__(self, file_str: str, line: int, func: str, args: T.List[str]) -> None:
+ self.file = CMakeTraceLine._to_path(file_str)
self.line = line
self.func = func.lower()
self.args = args
+ @staticmethod
+ @lru_cache(maxsize=None)
+ def _to_path(file_str: str) -> Path:
+ return Path(file_str)
+
def __repr__(self) -> str:
s = 'CMake TRACE: {0}:{1} {2}({3})'
return s.format(self.file, self.line, self.func, self.args)
+class CMakeCacheEntry(T.NamedTuple):
+ value: T.List[str]
+ type: str
+
class CMakeTarget:
def __init__(
self,
@@ -81,8 +91,10 @@ class CMakeGeneratorTarget(CMakeTarget):
class CMakeTraceParser:
def __init__(self, cmake_version: str, build_dir: Path, permissive: bool = True) -> None:
- self.vars = {} # type: T.Dict[str, T.List[str]]
- self.targets = {} # type: T.Dict[str, CMakeTarget]
+ self.vars: T.Dict[str, T.List[str]] = {}
+ self.vars_by_file: T.Dict[Path, T.Dict[str, T.List[str]]] = {}
+ self.targets: T.Dict[str, CMakeTarget] = {}
+ self.cache: T.Dict[str, CMakeCacheEntry] = {}
self.explicit_headers = set() # type: T.Set[Path]
@@ -234,6 +246,14 @@ class CMakeTraceParser:
"""
# DOC: https://cmake.org/cmake/help/latest/command/set.html
+ cache_type = None
+ cache_force = 'FORCE' in tline.args
+ try:
+ cache_idx = tline.args.index('CACHE')
+ cache_type = tline.args[cache_idx + 1]
+ except (ValueError, IndexError):
+ pass
+
# 1st remove PARENT_SCOPE and CACHE from args
args = []
for i in tline.args:
@@ -256,12 +276,19 @@ class CMakeTraceParser:
identifier = args.pop(0)
value = ' '.join(args)
+ # Write to the CMake cache instead
+ if cache_type:
+ # Honor how the CMake FORCE parameter works
+ if identifier not in self.cache or cache_force:
+ self.cache[identifier] = CMakeCacheEntry(value.split(';'), cache_type)
+
if not value:
# Same as unset
if identifier in self.vars:
del self.vars[identifier]
else:
self.vars[identifier] = value.split(';')
+ self.vars_by_file.setdefault(tline.file, {})[identifier] = value.split(';')
def _cmake_unset(self, tline: CMakeTraceLine) -> None:
# DOC: https://cmake.org/cmake/help/latest/command/unset.html
@@ -437,17 +464,18 @@ class CMakeTraceParser:
if not value:
return
- def do_target(tgt: str) -> None:
- if i not in self.targets:
- return self._gen_exception('set_property', f'TARGET {i} not found', tline)
+ def do_target(t: str) -> None:
+ if t not in self.targets:
+ return self._gen_exception('set_property', f'TARGET {t} not found', tline)
- if identifier not in self.targets[i].properties:
- self.targets[i].properties[identifier] = []
+ tgt = self.targets[t]
+ if identifier not in tgt.properties:
+ tgt.properties[identifier] = []
if append:
- self.targets[i].properties[identifier] += value
+ tgt.properties[identifier] += value
else:
- self.targets[i].properties[identifier] = value
+ tgt.properties[identifier] = value
def do_source(src: str) -> None:
if identifier != 'HEADER_FILE_ONLY' or not self._str_to_bool(value):
@@ -652,7 +680,7 @@ class CMakeTraceParser:
argl = args.split(' ')
argl = list(map(lambda x: x.strip(), argl))
- yield CMakeTraceLine(Path(file), int(line), func, argl)
+ yield CMakeTraceLine(file, int(line), func, argl)
def _lex_trace_json(self, trace: str) -> T.Generator[CMakeTraceLine, None, None]:
lines = trace.splitlines(keepends=False)
@@ -667,7 +695,7 @@ class CMakeTraceParser:
for j in args:
assert isinstance(j, str)
args = [parse_generator_expressions(x) for x in args]
- yield CMakeTraceLine(Path(data['file']), data['line'], data['cmd'], args)
+ yield CMakeTraceLine(data['file'], data['line'], data['cmd'], args)
def _flatten_args(self, args: T.List[str]) -> T.List[str]:
# Split lists in arguments