File: proto_extras.gni

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (228 lines) | stat: -rw-r--r-- 8,553 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Generate extra functionality for protobuf messages, including:
# - Serialization to base::DictValue.
# - Stream operator support for C++ printing.
# - (future) equality operator support
# - (future) gtest matchers.
# This does not directly generate the protobuf bindings for any language, so
# callers must include the build target for C++ bindings in the deps.
#
# This is a wrapper around proto_library that adds the proto_extras plugin. It
# is intended to be used in conjunction with proto_library, not on its own.
#
# Conversion to base::Value support:
# - The generated method is `Serialize(const ProtoMessage& message)`, and
#   resides in the namespace of the proto message.
# - Include via <name>.to_value.h.
# - Disable via `omit_to_value_serialization` (default is false).
#
# Stream operator support:
# - The generated operator resides in the namespace of the proto message.
# - Include via <name>.ostream.h.
# - Disable via `omit_stream_operators` (default is false).
#
# Equality operator support:
# - The generated operator resides in the namespace of the proto message.
# - Include via <name>.equal.h.
# - Disable via `omit_equality` (default is false).
#
# The proto_extras template supports the following other properties:
# - extras_deps: These are the proto_extras targets for any proto dependencies.
# - sources: The .proto files to generate from.
# - deps: These should be proto_library targets.
# - defines: This is forwarded to all generated targets.
# - visibility: This is forwarded to all generated targets.
#
# The functionality is split up per-file (instead of everything in a 'utils' or
# 'extras' file) as per go/no-utils guidance. This:
# - Helps prevent scope creep of lots of functionality in one file, and
#   provides the infrastructure to easily make more functionality in a dedicated file.
# - Reduces header includes and build size.
# - Minimizes the build graph if users only need one piece of functionality.
#
# For cases where the message uses the full google::protobuf::Message type,
# the protobuf_full_support option can be used to ensure the generated code
# with the full protobuf library. Due to android build complications, this also
# requires the `use_fuzzing_engine_with_lpm` build flag to be set.
# This option is relevant for base::Value serialization and equality.
#
# Caveats:
# - Integer types in the proto that are not compatible with base::Value are
#   serialized as strings (e.g. uint64_t).
#
# Example:
#   proto_extras("foo_extras") {
#     sources = [
#       "foo.proto",
#     ]
#
#     deps = [
#       ":foo",                    # The target generating foo.pb.h
#       ":foo_dependency",         # The target generating foo_dependency.pb.h
#     ]
#     extras_deps = [
#       ":foo_dependency_extras",  # The proto_extras target for foo_dependency.
#     ]
#     omit_to_value_serialization = true   # default is false
#     omit_stream_operators = true         # default is false
#     protobuf_full_support = true         # default is false
#     # Note: This target fails as there is no functionality being generated!
#   }
#
#  Consumers would then depend on ":foo_extras",

import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/protobuf/proto_library.gni")

template("proto_extras") {
  _generate_to_value = true
  if (defined(invoker.omit_to_value_serialization) &&
      invoker.omit_to_value_serialization) {
    _generate_to_value = false
  }
  _generate_ostream = true
  if (defined(invoker.omit_stream_operators) &&
      !invoker.omit_stream_operators) {
    _generate_ostream = false
  }
  _generate_equality = true
  if (defined(invoker.omit_equality) && invoker.omit_equality) {
    _generate_equality = false
  }
  _protobuf_full_support = false
  if (defined(invoker.protobuf_full_support) && invoker.protobuf_full_support &&
      use_fuzzing_engine_with_lpm) {
    _protobuf_full_support = true
  }

  assert(
      !_generate_ostream || _generate_to_value,
      "Stream operator generation currently depends on ToValue " +
          "serialization. Cannot set omit_to_value_serialization = true if " +
          "omit_stream_operators = false. Target: ${target_name}")

  assert(_generate_to_value || _generate_ostream || _generate_equality,
         "There must be one generation type enabled. Target: ${target_name}")

  _extras_deps = []
  if (defined(invoker.extras_deps)) {
    _extras_deps += invoker.extras_deps
  }

  _all_targets = []
  _to_value_target_name = "${target_name}_to_value"
  if (_generate_to_value) {
    _all_targets += [ _to_value_target_name ]
    proto_library(_to_value_target_name) {
      proto_in_dir = "//"
      sources = invoker.sources
      forward_variables_from(invoker,
                             [
                               "deps",
                               "defines",
                               "visibility",
                             ])
      link_deps = [ "//components/proto_extras:proto_extras_lib" ]
      if (_protobuf_full_support) {
        link_deps += [ "//components/proto_extras:protobuf_full_support" ]
      }

      # Link the *_to_value targets for all extras_deps.
      _extras_deps_to_value = []
      foreach(_dep, _extras_deps) {
        _extras_deps_to_value += [ "${_dep}_to_value" ]
      }
      link_deps += _extras_deps_to_value

      generator_plugin_label = "//components/proto_extras:proto_extras_plugin"
      generator_plugin_suffix = ".to_value"
      generate_cc = false
      generate_python = false
      link_public_deps = [ "//base" ]
      _to_value_options_list = [ "generate_to_value_serialization" ]
      if (_protobuf_full_support) {
        _to_value_options_list += [ "protobuf_full_support" ]
      }
      generator_plugin_options = string_join(",", _to_value_options_list)
    }
  }

  if (_generate_ostream) {
    _ostream_target_name = "${target_name}_ostream"
    _all_targets += [ _ostream_target_name ]
    proto_library(_ostream_target_name) {
      proto_in_dir = "//"
      sources = invoker.sources
      forward_variables_from(invoker,
                             [
                               "defines",
                               "visibility",
                             ])

      deps = [ ":$_to_value_target_name" ]
      if (defined(invoker.deps)) {
        deps += invoker.deps
      }
      link_deps = [ "//base" ]

      generator_plugin_label = "//components/proto_extras:proto_extras_plugin"
      generator_plugin_suffix = ".ostream"
      generate_cc = false
      generate_python = false
      generator_plugin_options = "generate_stream_operator"
    }
  }

  if (_generate_equality) {
    _equality_target_name = "${target_name}_equal"
    _all_targets += [ _equality_target_name ]
    proto_library(_equality_target_name) {
      proto_in_dir = "//"
      sources = invoker.sources
      forward_variables_from(invoker,
                             [
                               "deps",
                               "defines",
                               "visibility",
                             ])

      # Link the *_to_value targets for all extras_deps.
      _extras_deps_equality = []
      foreach(_dep, _extras_deps) {
        _extras_deps_equality += [ "${_dep}_equal" ]
      }
      link_deps = _extras_deps_equality
      _equality_options_list = [ "generate_equality" ]
      if (_protobuf_full_support) {
        _equality_options_list += [ "protobuf_full_support" ]
        link_deps += [ "//components/proto_extras:protobuf_full_support" ]
      }

      generator_plugin_label = "//components/proto_extras:proto_extras_plugin"
      generator_plugin_suffix = ".equal"
      generate_cc = false
      generate_python = false
      generator_plugin_options = string_join(",", _equality_options_list)
    }
  }

  # Group all generated targets into one group for the target_name.
  # Users can techncally depend on the generated target names for a more
  # optimized build graph, but it is uncommon in the codebase to not depend on a
  # target that is specifically named, so this ensures that the normal behavior
  # works.
  group(target_name) {
    forward_variables_from(invoker,
                           [
                             "defines",
                             "visibility",
                           ])
    public_deps = []
    foreach(_target, _all_targets) {
      public_deps += [ ":$_target" ]
    }
  }
}