aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2019-01-31 13:55:20 +0100
committerDaniel Mensinger <daniel@mensinger-ka.de>2019-01-31 15:43:04 +0100
commitbe3c58d6388c845fdde4374258dbb4ffbe18c5ca (patch)
tree6cd2ecb97433bb644db64e1e222c90c59dcdc3e2
parent8224ecfbe6e1811680113740341a277407904eb9 (diff)
downloadmeson-be3c58d6388c845fdde4374258dbb4ffbe18c5ca.zip
meson-be3c58d6388c845fdde4374258dbb4ffbe18c5ca.tar.gz
meson-be3c58d6388c845fdde4374258dbb4ffbe18c5ca.tar.bz2
Modify kwargs in rewriter
-rw-r--r--mesonbuild/rewriter.py271
1 files changed, 271 insertions, 0 deletions
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py
index 3426896..de39f63 100644
--- a/mesonbuild/rewriter.py
+++ b/mesonbuild/rewriter.py
@@ -71,7 +71,184 @@ class RequiredKeys:
return wrapped
+class MesonBaseType:
+ def __init__(self, node: mparser.BaseNode):
+ if node is None:
+ self.node = self._new_node()
+ else:
+ self.node = node
+ self.node_type = None
+ for i in self.supported_nodes():
+ if isinstance(self.node, i):
+ self.node_type = i
+
+ def _new_node(self):
+ # Overwrite in derived class
+ return mparser.BaseNode()
+
+ def can_modify(self):
+ return self.node_type is not None
+
+ def get_node(self):
+ return self.node
+
+ def supported_nodes(self):
+ # Overwrite in derived class
+ return []
+
+ def set_value(self, value):
+ # Overwrite in derived class
+ mlog.warning('Cannot set the value of type', mlog.bold(type(self).__name__), '--> skipping')
+
+ def add_value(self, value):
+ # Overwrite in derived class
+ mlog.warning('Cannot add a value of type', mlog.bold(type(self).__name__), '--> skipping')
+
+ def remove_value(self, value):
+ # Overwrite in derived class
+ mlog.warning('Cannot remove a value of type', mlog.bold(type(self).__name__), '--> skipping')
+
+class MesonStr(MesonBaseType):
+ def __init__(self, node: mparser.BaseNode):
+ super().__init__(node)
+
+ def _new_node(self):
+ return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, ''))
+
+ def supported_nodes(self):
+ return [mparser.StringNode]
+
+ def set_value(self, value):
+ self.node.value = str(value)
+
+class MesonBool(MesonBaseType):
+ def __init__(self, node: mparser.BaseNode):
+ super().__init__(node)
+
+ def _new_node(self):
+ return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, False))
+
+ def supported_nodes(self):
+ return [mparser.BooleanNode]
+
+ def set_value(self, value):
+ self.node.value = bool(value)
+
+class MesonID(MesonBaseType):
+ def __init__(self, node: mparser.BaseNode):
+ super().__init__(node)
+
+ def _new_node(self):
+ return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, ''))
+
+ def supported_nodes(self):
+ return [mparser.IdNode]
+
+ def set_value(self, value):
+ self.node.value = str(value)
+
+class MesonList(MesonBaseType):
+ def __init__(self, node: mparser.BaseNode):
+ super().__init__(node)
+
+ def _new_node(self):
+ return mparser.ArrayNode(mparser.ArgumentNode(mparser.Token('', '', 0, 0, 0, None, '')), 0, 0)
+
+ def _new_element_node(self, value):
+ # Overwrite in derived class
+ return mparser.BaseNode()
+
+ def _ensure_array_node(self):
+ if not isinstance(self.node, mparser.ArrayNode):
+ tmp = self.node
+ self.node = self._new_node()
+ self.node.args.arguments += [tmp]
+
+ def _check_is_equal(self, node, value):
+ # Overwrite in derived class
+ return False
+
+ def get_node(self):
+ if isinstance(self.node, mparser.ArrayNode):
+ if len(self.node.args.arguments) == 1:
+ return self.node.args.arguments[0]
+ return self.node
+
+ def supported_element_nodes(self):
+ # Overwrite in derived class
+ return []
+
+ def supported_nodes(self):
+ return [mparser.ArrayNode] + self.supported_element_nodes()
+
+ def set_value(self, value):
+ if not isinstance(value, list):
+ value = [value]
+ self._ensure_array_node()
+ self.node.args.arguments = [] # Remove all current nodes
+ for i in value:
+ self.node.args.arguments += [self._new_element_node(i)]
+
+ def add_value(self, value):
+ if not isinstance(value, list):
+ value = [value]
+ self._ensure_array_node()
+ for i in value:
+ self.node.args.arguments += [self._new_element_node(i)]
+
+ def remove_value(self, value):
+ def check_remove_node(node):
+ for j in value:
+ if self._check_is_equal(i, j):
+ return True
+ return False
+
+ if not isinstance(value, list):
+ value = [value]
+ self._ensure_array_node()
+ removed_list = []
+ for i in self.node.args.arguments:
+ if not check_remove_node(i):
+ removed_list += [i]
+ self.node.args.arguments = removed_list
+
+class MesonStrList(MesonList):
+ def __init__(self, node: mparser.BaseNode):
+ super().__init__(node)
+
+ def _new_element_node(self, value):
+ return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, str(value)))
+
+ def _check_is_equal(self, node, value):
+ if isinstance(node, mparser.StringNode):
+ return node.value == value
+ return False
+
+ def supported_element_nodes(self):
+ return [mparser.StringNode]
+
+class MesonIDList(MesonList):
+ def __init__(self, node: mparser.BaseNode):
+ super().__init__(node)
+
+ def _new_element_node(self, value):
+ return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, str(value)))
+
+ def _check_is_equal(self, node, value):
+ if isinstance(node, mparser.IdNode):
+ return node.value == value
+ return False
+
+ def supported_element_nodes(self):
+ return [mparser.IdNode]
+
rewriter_keys = {
+ 'kwargs': {
+ 'function': (str, None, None),
+ 'id': (str, None, None),
+ 'operation': (str, None, ['set', 'delete', 'add', 'remove']),
+ 'kwargs': (dict, {}, None)
+ },
'target': {
'target': (str, None, None),
'operation': (str, None, ['src_add', 'src_rm', 'test']),
@@ -80,6 +257,38 @@ rewriter_keys = {
}
}
+rewriter_func_kwargs = {
+ 'dependency': {
+ 'language': MesonStr,
+ 'method': MesonStr,
+ 'native': MesonBool,
+ 'not_found_message': MesonStr,
+ 'required': MesonBool,
+ 'static': MesonBool,
+ 'version': MesonStrList,
+ 'modules': MesonStrList
+ },
+ 'target': {
+ 'build_by_default': MesonBool,
+ 'build_rpath': MesonStr,
+ 'dependencies': MesonIDList,
+ 'gui_app': MesonBool,
+ 'link_with': MesonIDList,
+ 'export_dynamic': MesonBool,
+ 'implib': MesonBool,
+ 'install': MesonBool,
+ 'install_dir': MesonStr,
+ 'install_rpath': MesonStr,
+ 'pie': MesonBool
+ },
+ 'project': {
+ 'meson_version': MesonStr,
+ 'license': MesonStrList,
+ 'subproject_dir': MesonStr,
+ 'version': MesonStr
+ }
+}
+
class Rewriter:
def __init__(self, sourcedir: str, generator: str = 'ninja'):
self.sourcedir = sourcedir
@@ -87,6 +296,7 @@ class Rewriter:
self.id_generator = AstIDGenerator()
self.modefied_nodes = []
self.functions = {
+ 'kwargs': self.process_kwargs,
'target': self.process_target,
}
@@ -120,6 +330,67 @@ class Rewriter:
return tgt
+ @RequiredKeys(rewriter_keys['kwargs'])
+ def process_kwargs(self, cmd):
+ mlog.log('Processing function type', mlog.bold(cmd['function']), 'with id', mlog.cyan("'" + cmd['id'] + "'"))
+ if cmd['function'] not in rewriter_func_kwargs:
+ mlog.error('Unknown function type {} --> skipping'.format(cmd['function']))
+ return
+ kwargs_def = rewriter_func_kwargs[cmd['function']]
+
+ # Find the function node to modify
+ node = None
+ if cmd['function'] == 'project':
+ node = self.interpreter.project_node
+ elif cmd['function'] == 'target':
+ tmp = self.find_target(cmd['id'])
+ if tmp:
+ node = tmp['node']
+ if not node:
+ mlog.error('Unable to find the function node')
+ assert(isinstance(node, mparser.FunctionNode))
+
+ num_changed = 0
+ for key, val in cmd['kwargs'].items():
+ if key not in kwargs_def:
+ mlog.error('Cannot modify unknown kwarg --> skipping', mlog.bold(key))
+ continue
+
+ # Remove the key from the kwargs
+ if cmd['operation'] == 'delete':
+ if key in node.args.kwargs:
+ mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs')
+ del node.args.kwargs[key]
+ num_changed += 1
+ else:
+ mlog.log(' -- Key', mlog.bold(key), 'is already deleted')
+ continue
+
+ if key not in node.args.kwargs:
+ node.args.kwargs[key] = None
+ modifyer = kwargs_def[key](node.args.kwargs[key])
+ if not modifyer.can_modify():
+ mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify')
+
+ # Apply the operation
+ val_str = str(val)
+ if cmd['operation'] == 'set':
+ mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str))
+ modifyer.set_value(val)
+ elif cmd['operation'] == 'add':
+ mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key))
+ modifyer.add_value(val)
+ elif cmd['operation'] == 'remove':
+ mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key))
+ modifyer.remove_value(val)
+
+ # Write back the result
+ node.args.kwargs[key] = modifyer.get_node()
+ num_changed += 1
+
+ if num_changed > 0 and node not in self.modefied_nodes:
+ self.modefied_nodes += [node]
+
@RequiredKeys(rewriter_keys['target'])
def process_target(self, cmd):
mlog.log('Processing target', mlog.bold(cmd['target']), 'operation', mlog.cyan(cmd['operation']))