Commit 769719f1 authored by Mark Brand's avatar Mark Brand Committed by Commit Bot

Adding mojolpm fuzzer generators.

This adds code that generates libprotobuf-mutator based
structure-aware fuzzers as part of the mojom compilation process.
(changes in //mojo).

This is a cherrypick/split from
https://chromium-review.googlesource.com/c/chromium/src/+/2108507

Pragmatic fixes for the remaining missing dependencies.

Change-Id: I0e0d34a4b99b31f99ee872fb95be993043aef402
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2170830
Commit-Queue: Mark Brand <markbrand@google.com>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#771513}
parent a9af8d92
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{%- set header_guard = "%s_MOJOLPM_H_"|format(
module.path|upper|replace("/","_")|replace(".","_")|
replace("-", "_")) %}
{%- macro namespace_begin() %}
namespace mojolpm {
{%- for namespace in namespaces_as_array %}
namespace {{namespace}} {
{%- endfor %}
{%- endmacro %}
{%- macro namespace_end() %}
{%- for namespace in namespaces_as_array|reverse %}
} // namespace {{namespace}}
{%- endfor %}
} // namespace mojolpm
{%- endmacro %}
#ifndef {{header_guard}}
#define {{header_guard}}
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/tools/fuzzers/mojolpm.h"
{% for extra_public_header in extra_public_headers %}
#include "{{extra_public_header}}"
{%- endfor %}
{% for import in imports %}
#include "{{import.path}}-mojolpm.h"
#include "{{import.path}}.h"
{%- endfor %}
#include "{{module.path}}.mojolpm.pb.h"
#include "{{module.path}}.h"
{%- import "mojolpm_macros.tmpl" as util %}
{%- import "mojolpm_from_proto_macros.tmpl" as from_proto %}
{%- import "mojolpm_to_proto_macros.tmpl" as to_proto %}
namespace mojolpm {
{%- for enum in all_enums %}
{%- set mojom_type = enum|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- set proto_type = "::mojolpm" ~ (enum|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
// enum {{enum.name}}
bool FromProto(
const {{proto_type}}& input,
{{mojom_type}}& output);
bool ToProto(
const {{mojom_type}}& input,
{{proto_type}}& output);
{% endfor %}
{%- for struct in structs %}
{%- set mojom_in_type = struct|cpp_wrapper_param_type(add_same_module_namespaces=true) %}
{%- set mojom_out_type = struct|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
{%- set maybe_const = "const " if not struct|contains_handles_or_interfaces else "" %}
{%- set proto_type = "::mojolpm" ~ (struct|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set struct_type = proto_type ~ "_ProtoStruct" %}
// struct {{struct.name}}
bool FromProto(
const {{proto_type}}& input,
{{mojom_out_type}}& output);
bool ToProto(
{{mojom_in_type}} input,
{{proto_type}}& output);{{"\n"-}}
{%- for field in struct.fields %}
{%- set name = field.name %}
{%- set kind = field.kind %}
{%- if kind|is_array_kind or kind|is_map_kind %}
{{- from_proto.declare(struct_type, kind, name) }}
{{- to_proto.declare(struct_type, kind, name) }}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- for union in unions %}
{%- set mojom_in_type = union|cpp_wrapper_param_type(add_same_module_namespaces=true) %}
{%- set mojom_out_type = union|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
{%- set maybe_const = "const " if not union|contains_handles_or_interfaces else "" %}
{%- set proto_type = "::mojolpm" ~ (union|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set union_type = proto_type ~ "_ProtoUnion" %}
{%- if union|is_native_only_kind %}
#error "Mojo native-only union {{union.name}} - don't think this is possible"
{%- else %}
// union {{union.name}}
bool FromProto(
const {{proto_type}}& input,
{{mojom_out_type}}& output);
bool ToProto(
{{mojom_in_type}} input,
{{proto_type}}& output);{{"\n"-}}
{%- endif %}
{%- for field in union.fields %}
{%- set name = field.name %}
{%- set kind = field.kind %}
{%- if kind|is_array_kind or kind|is_map_kind %}
{{- from_proto.declare(union_type, kind, name) }}
{{- to_proto.declare(union_type, kind, name) }}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- for interface in interfaces %}
{%- set mojom_type = interface|get_qualified_name_for_kind(flatten_nested_kind=True) %}
{%- set proto_type = "::mojolpm" ~ (interface|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
// interface {{interface.name}}
bool FromProto(
const {{proto_type}}::Ptr& input,
{{mojom_type}}PtrInfo& output);
bool ToProto(
{{mojom_type}}Ptr&& input,
{{proto_type}}::Ptr& output);
bool ToProto(
{{mojom_type}}PtrInfo&& input,
{{proto_type}}::Ptr& output);
bool FromProto(
const {{proto_type}}::AssociatedPtr& input,
{{mojom_type}}AssociatedPtrInfo& output);
bool ToProto(
{{mojom_type}}AssociatedPtrInfo&& input,
{{proto_type}}::AssociatedPtr& output);
bool FromProto(
const {{proto_type}}::Request& input,
{{mojom_type}}Request& output);
bool ToProto(
{{mojom_type}}Request&& input,
{{proto_type}}::Request& output);
bool FromProto(
const {{proto_type}}::AssociatedRequest& input,
{{mojom_type}}AssociatedRequest& output);
bool ToProto(
{{mojom_type}}AssociatedRequest&& input,
{{proto_type}}::AssociatedRequest& output);
bool FromProto(
const {{proto_type}}::PendingRemote& input,
::mojo::PendingRemote<{{mojom_type}}>& output);
bool ToProto(
::mojo::PendingRemote<{{mojom_type}}>&& input,
{{proto_type}}::PendingRemote& output);
bool FromProto(
const {{proto_type}}::PendingReceiver& input,
::mojo::PendingReceiver<{{mojom_type}}>& output);
bool ToProto(
::mojo::PendingReceiver<{{mojom_type}}>&& input,
{{proto_type}}::PendingReceiver& output);
bool FromProto(
const {{proto_type}}::PendingAssociatedRemote& input,
::mojo::PendingAssociatedRemote<{{mojom_type}}>& output);
bool ToProto(
::mojo::PendingAssociatedRemote<{{mojom_type}}>&& input,
{{proto_type}}::PendingAssociatedRemote& output);
bool FromProto(
const {{proto_type}}::PendingAssociatedReceiver& input,
::mojo::PendingAssociatedReceiver<{{mojom_type}}>& output);
bool ToProto(
::mojo::PendingAssociatedReceiver<{{mojom_type}}>&& input,
{{proto_type}}::PendingAssociatedReceiver& output);{{"\n"-}}
{%- for method in interface.methods %}
{%- set method_type = proto_type ~ "::" ~ interface.name ~ "_" ~ method.name %}
{%- for param in method.parameters %}
{%- set name = param.name %}
{%- set kind = param.kind %}
{%- if kind|is_array_kind or kind|is_map_kind -%}
{{- from_proto.declare(method_type, kind, name)}}
{{- to_proto.declare(method_type, kind, name)}}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- endfor %}
{%- for interface in interfaces %}
{%- set mojom_type = interface|get_qualified_name_for_kind(flatten_nested_kind=True) %}
{%- set proto_type = "::mojolpm" ~ (interface|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- if interface.methods %}
bool HandleMethodCall(
const {{proto_type}}::MethodCall& input);
bool HandleMethodCallA(
const {{proto_type}}::MethodCallA& input);
bool HandleRemoteMethodCall(
const {{proto_type}}::RemoteMethodCall& input);
bool HandleAssociatedRemoteMethodCall(
const {{proto_type}}::AssociatedRemoteMethodCall& input);{{"\n"-}}
{%- for method in interface.methods %}
bool HandleMethodCall(
{{mojom_type}}Ptr& instance,
const {{proto_type}}::{{interface.name}}_{{method.name}}& input);
bool HandleMethodCallA(
{{mojom_type}}AssociatedPtr& instance,
const {{proto_type}}::{{interface.name}}_{{method.name}}& input);
bool HandleRemoteMethodCall(
::mojo::Remote<{{mojom_type}}>& instance,
const {{proto_type}}::{{interface.name}}_{{method.name}}& input);
bool HandleAssociatedRemoteMethodCall(
::mojo::AssociatedRemote<{{mojom_type}}>& instance,
const {{proto_type}}::{{interface.name}}_{{method.name}}& input);{{"\n"-}}
{%- endfor %}
{%- endif %}
{%- endfor -%}
} // namespace mojolpm
#endif // {{header_guard}}
{%- macro not_null(kind, name) %}
{%- if kind|is_typemapped_kind and kind|is_struct_kind and kind|nullable_is_same_kind %}
{%- set data_view = kind|get_qualified_name_for_kind ~ "DataView" %}
{%- set data_type = kind|cpp_wrapper_type(ignore_nullable=True) %}
{%- if data_type|truncate(16, true, '', 0) == '::scoped_refptr<' %}
{{name}}
{%- else %}
!::mojo::internal::CallIsNullIfExists<::mojo::StructTraits<{{data_view}}, {{data_type}}>>({{name}})
{%- endif %}
{%- else -%}{{name}}
{%- endif %}
{%- endmacro -%}
{%- macro value(kind, name) %}
{%- if kind|is_nullable_kind and (not kind|nullable_is_same_kind) -%}*{{name}}
{%- else -%}{{name}}
{%- endif %}
{%- endmacro -%}
{%- macro add_instance(kind, name, nested) %}
{%- if kind|is_array_kind %}
for (auto& {{name}}_iter : {{ value(kind, name) }}) {
{{ add_instance(kind.kind, name ~ '_iter', True)|indent(2, True) }}
}
{%- elif kind|is_map_kind %}
for (auto& {{name}}_iter : {{ value(kind, name) }}) {
auto& {{name}}_key = {{name}}_iter.first;
auto& {{name}}_value = {{name}}_iter.second;
{{ add_instance(kind.key_kind, name ~ "_key", True)|indent(2, True) }}
{{ add_instance(kind.value_kind, name ~ "_value", True)|indent(2, True) }}
}
{%- elif kind|is_interface_kind %}
{%- set mojom_type = kind|get_qualified_name_for_kind(flatten_nested_kind=True) %}
if ({{name}}) {
{{mojom_type}}Ptr tmp_{{name}}(std::move({{name}}));
mojolpm::GetContext()->AddInstance(std::move(tmp_{{name}}));
}
{%- elif kind|is_associated_interface_kind %}
{%- set mojom_type = kind.kind|get_qualified_name_for_kind(flatten_nested_kind=True) %}
if ({{name}}) {
{{mojom_type}}AssociatedPtr tmp_{{name}}(std::move({{name}}));
mojolpm::GetContext()->AddInstance(std::move(tmp_{{name}}));
}
{%- elif kind|is_pending_remote_kind %}
{%- set mojom_type = kind.kind|get_qualified_name_for_kind(flatten_nested_kind=True) %}
if ({{name}}) {
::mojo::Remote<{{mojom_type}}> tmp_{{name}}(std::move({{name}}));
mojolpm::GetContext()->AddInstance(std::move(tmp_{{name}}));
}
{%- elif kind|is_pending_associated_remote_kind %}
{%- set mojom_type = kind.kind|get_qualified_name_for_kind(flatten_nested_kind=True) %}
if ({{name}}) {
::mojo::AssociatedRemote<{{mojom_type}}> tmp_{{name}}(std::move({{name}}));
mojolpm::GetContext()->AddInstance(std::move(tmp_{{name}}));
}
{%- else %}
{%- if kind|is_nullable_kind %}
{%- set proto_type = kind|cpp_wrapper_proto_type(add_same_module_namespaces=true) %}
{{proto_type}} tmp_{{name}};
if ({{ not_null(kind, name) }}) {
{%- if kind|is_move_only_kind %}
if (ToProto(std::move({{ value(kind, name) }}), tmp_{{name}})) {
{%- else %}
if (ToProto({{ value(kind, name) }}, tmp_{{name}})) {
{%- endif %}
mojolpm::GetContext()->AddInstance(tmp_{{name}});
}
}
{%- else %}
{%- set proto_type = kind|cpp_wrapper_proto_type(add_same_module_namespaces=true) %}
{{proto_type}} tmp_{{name}};
{%- if kind|is_move_only_kind %}
if (ToProto(std::move({{name}}), tmp_{{name}})) {
{%- else %}
if (ToProto({{name}}, tmp_{{name}})) {
{%- endif %}
mojolpm::GetContext()->AddInstance(tmp_{{name}});
}
{%- endif %}
{%- endif %}
{%- endmacro %}
\ No newline at end of file
{% import "mojolpm_macros.tmpl" as util %}
{%- macro define_struct(struct) %}
{%- set mojom_type = struct|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- set proto_type = "::mojolpm" ~ (struct|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set struct_type = proto_type ~ "_ProtoStruct" %}
{%- set dataview_type = (struct|get_qualified_name_for_kind(flatten_nested_kind=True)) ~ "DataView" %}
template <>
struct StructTraits<{{dataview_type}}, {{struct_type}}> {
{%- for field in struct.fields %}
{%- set name = field.name|camel_to_under %}
{%- set kind = field.kind %}
{%- if field.kind|is_nullable_kind and not field.kind|nullable_is_same_kind %}
{%- set field_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- set field_maybe_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true, ignore_nullable=true) %}
static {{field_mojom_type}} {{field.name}}(
const {{struct_type}}& input) {
{{field_mojom_type}} maybe_local_{{name}};
{{field_maybe_mojom_type}} local_{{name}};
if (mojolpm::FromProto(
input.m_{{name}}(),
local_{{name}})) {
maybe_local_{{name}} = std::move(local_{{name}});
}
return maybe_local_{{name}};
}{{ "\n" }}
{%- else %}
{%- set field_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
static {{field_mojom_type}} {{field.name}}(
const {{struct_type}}& input) {
{{field_mojom_type}} local_{{name}};
(void) mojolpm::FromProto(
input.m_{{name}}(),
local_{{name}});
return local_{{name}};
}{{ "\n" }}
{%- endif %}
{%- endfor -%}
};
{% endmacro -%}
{%- macro define_union(union) -%}
{%- set mojom_type = union|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- set proto_type = "::mojolpm" ~ (union|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set union_type = proto_type ~ "_ProtoUnion" %}
{%- if union|is_typemapped_kind %}
{%- set dataview_type = (union|get_qualified_name_for_kind(flatten_nested_kind=True)) ~ "DataView" %}
template<>
struct UnionTraits<{{dataview_type}}, {{union_type}}> {
static {{dataview_type}}::Tag GetTag(
const {{union_type}}& input) {
switch (input.union_member_case()) {
{%- for field in union.fields %}
{%- set name = field.name|camel_to_under %}
{%- set kind = field.kind %}
{%- set field_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
case {{union_type}}::k{{("m_" ~ name)|under_to_camel}}:
return {{dataview_type}}::Tag::{{name|upper}};
{%- endfor %}
default:
NOTREACHED();
return static_cast<{{dataview_type}}::Tag>(0);
}
}{{"\n"}}
{%- for field in union.fields %}
{%- set name = field.name|camel_to_under %}
{%- set kind = field.kind %}
{%- if field.kind|is_nullable_kind and not field.kind|nullable_is_same_kind %}
{%- set field_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- set field_maybe_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true, ignore_nullable=true) %}
static {{field_mojom_type}} {{field.name}}(
const {{union_type}}& input) {
{{field_mojom_type}} maybe_local_{{name}};
{{field_maybe_mojom_type}} local_{{name}};
if (mojolpm::FromProto(
input.m_{{name}}(),
local_{{name}})) {
maybe_local_{{name}} = std::move(local_{{name}});
}
return maybe_local_{{name}};
}{{ "\n" }}
{%- else %}
{%- set field_mojom_type = kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
static {{field_mojom_type}} {{field.name}}(
const {{union_type}}& input) {
{{field_mojom_type}} local_{{name}};
(void) mojolpm::FromProto(
input.m_{{name}}(),
local_{{name}});
return local_{{name}};
}{{ "\n" }}
{%- endif %}
{%- endfor -%}
};
{% endif %}
{% endmacro -%}
\ No newline at end of file
......@@ -33,6 +33,8 @@ _kind_to_cpp_literal_suffix = {
}
class _NameFormatter(object):
"""A formatter for the names of kinds or values."""
......@@ -558,12 +560,20 @@ class Generator(generator.Generator):
for cpp_template_path in self.extra_cpp_template_paths:
path_to_template, filename = os.path.split(cpp_template_path)
filename_without_tmpl_suffix = filename.rstrip(".tmpl")
self.WriteWithComment(self._GenerateModuleFromImportedTemplate(path_to_template, filename),
"%s%s-%s" % (self.module.path, suffix, filename_without_tmpl_suffix))
self.WriteWithComment(
self._GenerateModuleFromImportedTemplate(path_to_template,
filename), "%s%s-%s" %
(self.module.path, suffix, filename_without_tmpl_suffix))
def _ConstantValue(self, constant):
return self._ExpressionToText(constant.value, kind=constant.kind)
def _UnderToCamel(self, value, digits_split=False):
# There are some mojom files that don't use snake_cased names, so we try to
# fix that to get more consistent output.
return generator.ToCamel(generator.ToLowerSnakeCase(value),
digits_split=digits_split)
def _DefaultValue(self, field):
if not field.default:
return ""
......@@ -658,8 +668,13 @@ class Generator(generator.Generator):
GetCppPodType(constant.kind), constant.name,
self._ConstantValue(constant))
def _GetCppWrapperType(self, kind, add_same_module_namespaces=False):
def _GetCppWrapperType(self,
kind,
add_same_module_namespaces=False,
ignore_nullable=False):
def _AddOptional(type_name):
if ignore_nullable:
return type_name
return "base::Optional<%s>" % type_name
if self._IsTypemappedKind(kind):
......@@ -700,16 +715,16 @@ class Generator(generator.Generator):
return "%sRequest" % self._GetNameForKind(
kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsPendingRemoteKind(kind):
return "mojo::PendingRemote<%s>" % self._GetNameForKind(
return "::mojo::PendingRemote<%s>" % self._GetNameForKind(
kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsPendingReceiverKind(kind):
return "mojo::PendingReceiver<%s>" % self._GetNameForKind(
return "::mojo::PendingReceiver<%s>" % self._GetNameForKind(
kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsPendingAssociatedRemoteKind(kind):
return "mojo::PendingAssociatedRemote<%s>" % self._GetNameForKind(
return "::mojo::PendingAssociatedRemote<%s>" % self._GetNameForKind(
kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsPendingAssociatedReceiverKind(kind):
return "mojo::PendingAssociatedReceiver<%s>" % self._GetNameForKind(
return "::mojo::PendingAssociatedReceiver<%s>" % self._GetNameForKind(
kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsAssociatedInterfaceKind(kind):
return "%sAssociatedPtrInfo" % self._GetNameForKind(
......@@ -724,17 +739,17 @@ class Generator(generator.Generator):
return (_AddOptional(type_name) if mojom.IsNullableKind(kind)
else type_name)
if mojom.IsGenericHandleKind(kind):
return "mojo::ScopedHandle"
return "::mojo::ScopedHandle"
if mojom.IsDataPipeConsumerKind(kind):
return "mojo::ScopedDataPipeConsumerHandle"
return "::mojo::ScopedDataPipeConsumerHandle"
if mojom.IsDataPipeProducerKind(kind):
return "mojo::ScopedDataPipeProducerHandle"
return "::mojo::ScopedDataPipeProducerHandle"
if mojom.IsMessagePipeKind(kind):
return "mojo::ScopedMessagePipeHandle"
return "::mojo::ScopedMessagePipeHandle"
if mojom.IsSharedBufferKind(kind):
return "mojo::ScopedSharedBufferHandle"
return "::mojo::ScopedSharedBufferHandle"
if mojom.IsPlatformHandleKind(kind):
return "mojo::PlatformHandle"
return "::mojo::PlatformHandle"
if not kind in _kind_to_cpp_type:
raise Exception("Unrecognized kind %s" % kind.spec)
return _kind_to_cpp_type[kind]
......@@ -769,19 +784,23 @@ class Generator(generator.Generator):
return ((not mojom.IsReferenceKind(kind)) or self._IsMoveOnlyKind(kind) or
self._IsCopyablePassByValue(kind))
def _GetCppWrapperCallType(self, kind):
def _GetCppWrapperCallType(self, kind, add_same_module_namespaces=False):
# TODO: Remove this once interfaces are always passed as PtrInfo.
if mojom.IsInterfaceKind(kind):
return "%sPtr" % self._GetNameForKind(kind)
return self._GetCppWrapperType(kind)
return "%sPtr" % self._GetNameForKind(
kind, add_same_module_namespaces=add_same_module_namespaces)
return self._GetCppWrapperType(
kind, add_same_module_namespaces=add_same_module_namespaces)
def _GetCppWrapperParamType(self, kind):
def _GetCppWrapperParamType(self, kind, add_same_module_namespaces=False):
# TODO: Remove all usage of this method in favor of
# _GetCppWrapperParamTypeNew. This requires all generated code which passes
# interface handles to use PtrInfo instead of Ptr.
if mojom.IsInterfaceKind(kind):
return "%sPtr" % self._GetNameForKind(kind)
cpp_wrapper_type = self._GetCppWrapperType(kind)
return "%sPtr" % self._GetNameForKind(
kind, add_same_module_namespaces=add_same_module_namespaces)
cpp_wrapper_type = self._GetCppWrapperType(
kind, add_same_module_namespaces=add_same_module_namespaces)
return (cpp_wrapper_type if self._ShouldPassParamByValue(kind)
else "const %s&" % cpp_wrapper_type)
......
......@@ -5,6 +5,7 @@
import("//build/config/jumbo.gni")
import("//third_party/closure_compiler/closure_args.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("//third_party/protobuf/proto_library.gni")
import("//ui/webui/webui_features.gni")
# TODO(rockot): Maybe we can factor these dependencies out of //mojo. They're
......@@ -904,6 +905,83 @@ template("mojom") {
}
}
if (generate_fuzzing) {
# This block generates the proto files used for the MojoLPM fuzzer,
# and the corresponding proto targets that will be linked in the fuzzer
# targets. These are independent of the typemappings, and can be done
# separately here.
generator_mojolpm_proto_target_name =
"${target_name}_mojolpm_proto_generator"
action(generator_mojolpm_proto_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = invoker.sources
deps = [
":$parser_target_name",
"//mojo/public/tools/bindings:precompile_templates",
]
outputs = []
args = common_generator_args
filelist = []
foreach(source, invoker.sources) {
filelist += [ rebase_path("$source", root_build_dir) ]
outputs += [ "$target_gen_dir/$source.mojolpm.proto" ]
}
response_file_contents = filelist
args += [
"--filelist={{response_file_name}}",
"--generate_non_variant_code",
"-g",
"mojolpm",
]
}
mojolpm_proto_target_name = "${target_name}_mojolpm_proto"
if (defined(invoker.sources)) {
proto_library(mojolpm_proto_target_name) {
testonly = true
generate_python = false
sources = process_file_template(
invoker.sources,
[ "{{source_gen_dir}}/{{source_file_part}}.mojolpm.proto" ])
import_dirs = [ "${root_gen_dir}" ]
proto_in_dir = "${root_gen_dir}"
proto_out_dir = "."
proto_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto_copy" ]
proto_deps += [ ":$generator_mojolpm_proto_target_name" ]
link_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ]
foreach(d, all_deps) {
# Resolve the name, so that a target //mojo/something becomes
# //mojo/something:something and we can append mojolpm_proto_suffix
# to get the proto dependency name.
full_name = get_label_info("$d", "label_no_toolchain")
proto_deps += [ "${full_name}_mojolpm_proto" ]
link_deps += [ "${full_name}_mojolpm_proto" ]
}
}
} else {
group(mojolpm_proto_target_name) {
testonly = true
public_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ]
if (defined(generator_shared_target_name)) {
public_deps += [ ":$generator_shared_target_name" ]
}
foreach(d, all_deps) {
# Resolve the name, so that a target //mojo/something becomes
# //mojo/something:something and we can append #mojolpm_proto_suffix
# to get the proto dependency name.
full_name = get_label_info("$d", "label_no_toolchain")
public_deps += [ "${full_name}_mojolpm_proto" ]
}
}
}
}
# Generate code for variants.
if (!defined(invoker.disable_variants) || !invoker.disable_variants) {
enabled_configurations = _bindings_configurations
......@@ -1081,6 +1159,12 @@ template("mojom") {
"$root_gen_dir/${base_path}${variant_dash_suffix}.cc",
"$root_gen_dir/${base_path}${variant_dash_suffix}.h",
]
if (generate_fuzzing && !defined(bindings_configuration.variant)) {
outputs += [
"$root_gen_dir/${base_path}${variant_dash_suffix}-mojolpm.cc",
"$root_gen_dir/${base_path}${variant_dash_suffix}-mojolpm.h",
]
}
}
response_file_contents = filelist
......@@ -1088,9 +1172,14 @@ template("mojom") {
args += [
"--filelist={{response_file_name}}",
"-g",
"c++",
]
if (generate_fuzzing && !defined(bindings_configuration.variant)) {
args += [ "c++,mojolpm" ]
} else {
args += [ "c++" ]
}
if (defined(bindings_configuration.variant)) {
args += [
"--variant",
......@@ -1141,6 +1230,79 @@ template("mojom") {
}
}
if (generate_fuzzing && !defined(variant)) {
# This block contains the C++ targets for the MojoLPM fuzzer, we need to
# do this here so that we can use the typemap configuration for the
# empty-variant Mojo target.
mojolpm_target_name = "${target_name}_mojolpm"
mojolpm_generator_target_name = "${target_name}__generator"
source_set(mojolpm_target_name) {
# There are still a few missing header dependencies between mojo targets
# with typemaps and the dependencies of their typemap headers. It would
# be good to enable include checking for these in the future though.
check_includes = false
testonly = true
if (defined(invoker.sources)) {
sources = process_file_template(
invoker.sources,
[
"{{source_gen_dir}}/{{source_file_part}}-mojolpm.cc",
"{{source_gen_dir}}/{{source_file_part}}-mojolpm.h",
])
deps = []
} else {
sources = []
deps = []
}
public_deps = [
":$generator_shared_target_name",
# NB: hardcoded dependency on the no-variant variant generator, since
# mojolpm only uses the no-variant type.
":$mojolpm_generator_target_name",
":$mojolpm_proto_target_name",
"//mojo/public/tools/fuzzers:mojolpm",
]
foreach(d, all_deps) {
# Resolve the name, so that a target //mojo/something becomes
# //mojo/something:something and we can append variant_suffix to
# get the cpp dependency name.
full_name = get_label_info("$d", "label_no_toolchain")
public_deps += [ "${full_name}_mojolpm" ]
}
foreach(typemap, active_typemaps) {
_typemap_config = {
}
_typemap_config = typemap.config
if (defined(_typemap_config.sources)) {
sources += _typemap_config.sources
}
if (defined(_typemap_config.deps)) {
deps += _typemap_config.deps
}
if (defined(_typemap_config.public_deps)) {
public_deps += _typemap_config.public_deps
}
}
foreach(config, cpp_typemap_configs) {
if (defined(config.traits_sources)) {
sources += config.traits_sources
}
if (defined(config.traits_deps)) {
deps += config.traits_deps
}
if (defined(config.traits_public_deps)) {
public_deps += config.traits_public_deps
}
}
}
}
# Write the typemapping configuration for this target out to a file to be
# validated by a Python script. This helps catch mistakes that can't
# be caught by logic in GN.
......
......@@ -50,10 +50,11 @@ import crbug_1001171
_BUILTIN_GENERATORS = {
"c++": "mojom_cpp_generator",
"javascript": "mojom_js_generator",
"java": "mojom_java_generator",
"typescript": "mojom_ts_generator",
"c++": "mojom_cpp_generator",
"javascript": "mojom_js_generator",
"java": "mojom_java_generator",
"mojolpm": "mojom_mojolpm_generator",
"typescript": "mojom_ts_generator",
}
......@@ -163,6 +164,8 @@ class MojomProcessor(object):
language_map = self._typemap.get(language, {})
language_map.update(typemap)
self._typemap[language] = language_map
if 'c++' in self._typemap:
self._typemap['mojolpm'] = self._typemap['c++']
def _GenerateModule(self, args, remaining_args, generator_modules,
rel_filename, imported_filename_stack):
......@@ -276,10 +279,11 @@ def main():
generate_parser.add_argument("--filelist", help="mojom input file list")
generate_parser.add_argument("-d", "--depth", dest="depth", default=".",
help="depth from source root")
generate_parser.add_argument("-g", "--generators",
generate_parser.add_argument("-g",
"--generators",
dest="generators_string",
metavar="GENERATORS",
default="c++,javascript,java",
default="c++,javascript,java,mojolpm",
help="comma-separated list of generators")
generate_parser.add_argument(
"--gen_dir", dest="gen_directories", action="append", metavar="directory",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment