blob: 9ab1bada3e5077c74953586c1c7212c4a1ecb183 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generate mojo connectivity test code."""
import json
import os
from pathlib import Path
# pylint: disable=import-error, no-name-in-module
import jinja2
from generators import mojom_cpp_generator
from mojom.generate import generator as mojom_generator
from mojom.generate import module as mojom_module
# pylint: enable=import-error, no-name-in-module
from chromite.lib import commandline
TEMPLATES_PATH = Path(Path(os.path.realpath(__file__)).parent, 'templates')
class Generator:
"""Generates bindings code for c++."""
def __init__(self, mojom, mojo_root, output_dir, generator_overrides):
self._output_dir = output_dir
self._mojom = os.path.relpath(mojom, mojo_root)
self._generator_overrides = generator_overrides
self._module = None
self._LoadModule()
self._env = None
self._SetUpEnv()
def _LoadModule(self):
module_path = Path(self._output_dir, f'{self._mojom}-module')
with module_path.open('rb') as f:
self._module = mojom_module.Module.Load(f)
self._module.Stylize(mojom_generator.Stylizer())
def _GetFullMojomNameForKind(self, kind):
return self._env.filters['get_full_mojom_name_for_kind'](kind)
def _IsGeneratorOverrideKind(self, kind):
return (hasattr(kind, 'name') and self._GetFullMojomNameForKind(kind)
in self._generator_overrides)
def _GetGeneratorOverrideType(self, kind):
if not self._IsGeneratorOverrideKind(kind):
return None
return self._generator_overrides[self._GetFullMojomNameForKind(
kind)]['generator_typename']
def _SetUpEnv(self):
self._env = jinja2.Environment(
loader=jinja2.FileSystemLoader(TEMPLATES_PATH))
generator = mojom_cpp_generator.Generator(self._module)
self._env.filters.update(generator.GetFilters())
self._env.filters.update({
'generator_override_type': self._GetGeneratorOverrideType,
})
self._env.tests.update({
'PendingRemoteKind': mojom_module.IsPendingRemoteKind,
'PendingReceiverKind': mojom_module.IsPendingReceiverKind,
'StructKind': mojom_module.IsStructKind,
'UnionKind': mojom_module.IsUnionKind,
'EnumKind': mojom_module.IsEnumKind,
'ArrayKind': mojom_module.IsArrayKind,
'MapKind': mojom_module.IsMapKind,
'GenericHandleKind': mojom_module.IsGenericHandleKind,
'GeneratorOverrideKind': self._IsGeneratorOverrideKind,
})
def _GenerateFile(self, suffix, args):
data = self._env.get_template(f'{suffix}.j2').render(**args)
output_file = Path(self._output_dir, f'{self._mojom}-{suffix}')
output_file.write_text(data)
def Generate(self):
extra_headers = []
for override in self._generator_overrides.values():
extra_headers += override['generator_headers']
args = {
'module': self._module,
'namespaces_as_array': self._module.mojom_namespace.split('.'),
'extra_headers': extra_headers,
}
self._GenerateFile('connectivity-forward.h', args)
self._GenerateFile('connectivity.h', args)
self._GenerateFile('connectivity.cc', args)
def Generate(mojoms, mojo_root, output_dir, generator_overrides_files):
"""Parses arguments and generates bindings code for c++."""
generator_overrides = {}
for f in generator_overrides_files:
override = json.loads(Path(f).read_bytes())
generator_overrides.update(override.get('c++', {}))
for mojom in mojoms:
Generator(mojom, mojo_root, output_dir, generator_overrides).Generate()
def GetParser():
"""Returns an argument parser."""
parser = commandline.ArgumentParser(description=__doc__)
parser.add_argument(
'--mojo-root', required=True, help='Root of the mojo files.')
parser.add_argument(
'--output-dir',
required=True,
help='Path for mojo generated code. '
'Must be the same as the mojo bindings output dir.')
parser.add_argument(
'--mojom-file-list', help='Mojom filenames passed as a file.')
parser.add_argument(
'--mojoms', default=[], nargs='+', help='Mojom filenames.')
parser.add_argument(
'--generator-overrides',
default=[],
nargs='+',
help='The json config of the generator overrides.')
return parser
def main(argv):
parser = GetParser()
opts = parser.parse_args(argv)
if opts.mojom_file_list:
opts.mojoms.extend(
Path(opts.mojom_file_list).read_text(encoding='utf-8').split())
opts.Freeze()
if not opts.mojoms:
raise parser.error('Must list at least one mojom file via --mojoms or '
'--mojom-file-list')
Generate(opts.mojoms, opts.mojo_root, opts.output_dir,
opts.generator_overrides)
if __name__ == '__main__':
commandline.ScriptWrapperMain(lambda _: main)