xref: /aosp_15_r20/external/pigweed/pw_protobuf_compiler/proto.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker#
3*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker# the License at
6*61c4878aSAndroid Build Coastguard Worker#
7*61c4878aSAndroid Build Coastguard Worker#     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker#
9*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker# the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Workerimport("//build_overrides/pigweed.gni")
16*61c4878aSAndroid Build Coastguard Workerimport("//build_overrides/pigweed_environment.gni")
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/error.gni")
19*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/input_group.gni")
20*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/mirror_tree.gni")
21*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/python.gni")
22*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/python_action.gni")
23*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/python_gn_args.gni")
24*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/target_types.gni")
25*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_third_party/nanopb/nanopb.gni")
26*61c4878aSAndroid Build Coastguard Workerimport("toolchain.gni")
27*61c4878aSAndroid Build Coastguard Worker
28*61c4878aSAndroid Build Coastguard Worker# Variables forwarded from the public pw_proto_library template to the final
29*61c4878aSAndroid Build Coastguard Worker# pw_source_set.
30*61c4878aSAndroid Build Coastguard Worker_forwarded_vars = [
31*61c4878aSAndroid Build Coastguard Worker  "testonly",
32*61c4878aSAndroid Build Coastguard Worker  "visibility",
33*61c4878aSAndroid Build Coastguard Worker]
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Workerdeclare_args() {
36*61c4878aSAndroid Build Coastguard Worker  # To override the protobuf compiler used set this to the GN target that builds
37*61c4878aSAndroid Build Coastguard Worker  # the protobuf compiler.
38*61c4878aSAndroid Build Coastguard Worker  pw_protobuf_compiler_PROTOC_TARGET = ""
39*61c4878aSAndroid Build Coastguard Worker}
40*61c4878aSAndroid Build Coastguard Worker
41*61c4878aSAndroid Build Coastguard Workerif (pw_protobuf_compiler_PROTOC_TARGET == "" &&
42*61c4878aSAndroid Build Coastguard Worker    defined(pw_env_setup_CIPD_PIGWEED)) {
43*61c4878aSAndroid Build Coastguard Worker  _default_protc =
44*61c4878aSAndroid Build Coastguard Worker      rebase_path("$pw_env_setup_CIPD_PIGWEED/bin/protoc", root_build_dir)
45*61c4878aSAndroid Build Coastguard Worker  if (host_os == "win") {
46*61c4878aSAndroid Build Coastguard Worker    _default_protc += ".exe"
47*61c4878aSAndroid Build Coastguard Worker  }
48*61c4878aSAndroid Build Coastguard Worker} else {
49*61c4878aSAndroid Build Coastguard Worker  _default_protc = ""
50*61c4878aSAndroid Build Coastguard Worker}
51*61c4878aSAndroid Build Coastguard Worker
52*61c4878aSAndroid Build Coastguard Workerdeclare_args() {
53*61c4878aSAndroid Build Coastguard Worker  # To override the protobuf compiler used set this to the path, relative to the
54*61c4878aSAndroid Build Coastguard Worker  # root_build_dir, to the protoc binary.
55*61c4878aSAndroid Build Coastguard Worker  pw_protobuf_compiler_PROTOC_BINARY = _default_protc
56*61c4878aSAndroid Build Coastguard Worker}
57*61c4878aSAndroid Build Coastguard Worker
58*61c4878aSAndroid Build Coastguard Worker# Internal template that invokes protoc with a pw_python_action. This should not
59*61c4878aSAndroid Build Coastguard Worker# be used outside of this file; use pw_proto_library instead.
60*61c4878aSAndroid Build Coastguard Worker#
61*61c4878aSAndroid Build Coastguard Worker# This creates the internal GN target $target_name.$language._gen that compiles
62*61c4878aSAndroid Build Coastguard Worker# proto files with protoc.
63*61c4878aSAndroid Build Coastguard Workertemplate("_pw_invoke_protoc") {
64*61c4878aSAndroid Build Coastguard Worker  if (current_toolchain == pw_protobuf_compiler_TOOLCHAIN) {
65*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.out_dir)) {
66*61c4878aSAndroid Build Coastguard Worker      _out_dir = invoker.out_dir
67*61c4878aSAndroid Build Coastguard Worker    } else {
68*61c4878aSAndroid Build Coastguard Worker      _out_dir = "${invoker.base_out_dir}/${invoker.language}"
69*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.module_as_package) &&
70*61c4878aSAndroid Build Coastguard Worker          invoker.module_as_package != "") {
71*61c4878aSAndroid Build Coastguard Worker        assert(invoker.language == "python")
72*61c4878aSAndroid Build Coastguard Worker        _out_dir = "$_out_dir/${invoker.module_as_package}"
73*61c4878aSAndroid Build Coastguard Worker      }
74*61c4878aSAndroid Build Coastguard Worker    }
75*61c4878aSAndroid Build Coastguard Worker
76*61c4878aSAndroid Build Coastguard Worker    _includes =
77*61c4878aSAndroid Build Coastguard Worker        rebase_path(get_target_outputs(":${invoker.base_target}._includes"),
78*61c4878aSAndroid Build Coastguard Worker                    root_build_dir)
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker    pw_python_action("$target_name._gen") {
81*61c4878aSAndroid Build Coastguard Worker      script =
82*61c4878aSAndroid Build Coastguard Worker          "$dir_pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py"
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard Worker      # NOTE: A python_dep on "$dir_pw_protobuf_compiler/py" should not be
85*61c4878aSAndroid Build Coastguard Worker      # included building that Python package which requires the build venv to
86*61c4878aSAndroid Build Coastguard Worker      # be created. Instead, use python_metadata_deps to only add
87*61c4878aSAndroid Build Coastguard Worker      # pw_protobuf_compiler to the PYTHONPATH.
88*61c4878aSAndroid Build Coastguard Worker      python_deps = []
89*61c4878aSAndroid Build Coastguard Worker
90*61c4878aSAndroid Build Coastguard Worker      # Add pw_protobuf_compiler and its dependencies to the PYTHONPATH when
91*61c4878aSAndroid Build Coastguard Worker      # running this action.
92*61c4878aSAndroid Build Coastguard Worker      python_metadata_deps = [ "$dir_pw_protobuf_compiler/py" ]
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker      python_deps = []
95*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.python_deps)) {
96*61c4878aSAndroid Build Coastguard Worker        python_deps += invoker.python_deps
97*61c4878aSAndroid Build Coastguard Worker      }
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker      deps = [
100*61c4878aSAndroid Build Coastguard Worker        ":${invoker.base_target}._includes",
101*61c4878aSAndroid Build Coastguard Worker        ":${invoker.base_target}._sources",
102*61c4878aSAndroid Build Coastguard Worker      ]
103*61c4878aSAndroid Build Coastguard Worker
104*61c4878aSAndroid Build Coastguard Worker      foreach(dep, invoker.deps) {
105*61c4878aSAndroid Build Coastguard Worker        deps += [ get_label_info(dep, "label_no_toolchain") + "._gen" ]
106*61c4878aSAndroid Build Coastguard Worker      }
107*61c4878aSAndroid Build Coastguard Worker
108*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.other_deps)) {
109*61c4878aSAndroid Build Coastguard Worker        deps += invoker.other_deps
110*61c4878aSAndroid Build Coastguard Worker      }
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard Worker      args = []
113*61c4878aSAndroid Build Coastguard Worker      if (!pw_protobuf_compiler_GENERATE_LEGACY_ENUM_SNAKE_CASE_NAMES) {
114*61c4878aSAndroid Build Coastguard Worker        args += [ "--exclude-pwpb-legacy-snake-case-field-name-enums" ]
115*61c4878aSAndroid Build Coastguard Worker      }
116*61c4878aSAndroid Build Coastguard Worker      if (pw_protobuf_compiler_NO_GENERIC_OPTIONS_FILES) {
117*61c4878aSAndroid Build Coastguard Worker        args += [ "--pwpb-no-generic-options-files" ]
118*61c4878aSAndroid Build Coastguard Worker      }
119*61c4878aSAndroid Build Coastguard Worker      if (pw_protobuf_compiler_NO_ONEOF_CALLBACKS ||
120*61c4878aSAndroid Build Coastguard Worker          invoker.use_legacy_oneof_interfaces) {
121*61c4878aSAndroid Build Coastguard Worker        args += [ "--pwpb-no-oneof-callbacks" ]
122*61c4878aSAndroid Build Coastguard Worker      }
123*61c4878aSAndroid Build Coastguard Worker      if (pw_protobuf_compiler_PROTOC_TARGET != "") {
124*61c4878aSAndroid Build Coastguard Worker        assert(
125*61c4878aSAndroid Build Coastguard Worker            pw_protobuf_compiler_PROTOC_BINARY != "",
126*61c4878aSAndroid Build Coastguard Worker            "if pw_protobuf_compiler_PROTOC_TARGET is set then pw_protobuf_compiler_PROTOC_BINARY must be set to the path to protoc, relative to the root_build_dir.")
127*61c4878aSAndroid Build Coastguard Worker        _protoc_src_dir =
128*61c4878aSAndroid Build Coastguard Worker            get_label_info(pw_protobuf_compiler_PROTOC_TARGET, "dir") + "/src"
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker        args += [
131*61c4878aSAndroid Build Coastguard Worker          "--protoc",
132*61c4878aSAndroid Build Coastguard Worker          pw_protobuf_compiler_PROTOC_BINARY,
133*61c4878aSAndroid Build Coastguard Worker          "--proto-path",
134*61c4878aSAndroid Build Coastguard Worker          rebase_path(_protoc_src_dir, root_build_dir),
135*61c4878aSAndroid Build Coastguard Worker        ]
136*61c4878aSAndroid Build Coastguard Worker        deps += [ pw_protobuf_compiler_PROTOC_TARGET ]
137*61c4878aSAndroid Build Coastguard Worker      }
138*61c4878aSAndroid Build Coastguard Worker      args += [
139*61c4878aSAndroid Build Coastguard Worker                "--language",
140*61c4878aSAndroid Build Coastguard Worker                invoker.language,
141*61c4878aSAndroid Build Coastguard Worker                "--include-file",
142*61c4878aSAndroid Build Coastguard Worker                _includes[0],
143*61c4878aSAndroid Build Coastguard Worker                "--compile-dir",
144*61c4878aSAndroid Build Coastguard Worker                rebase_path(invoker.compile_dir, root_build_dir),
145*61c4878aSAndroid Build Coastguard Worker                "--out-dir",
146*61c4878aSAndroid Build Coastguard Worker                rebase_path(_out_dir, root_build_dir),
147*61c4878aSAndroid Build Coastguard Worker                "--sources",
148*61c4878aSAndroid Build Coastguard Worker              ] + rebase_path(invoker.sources, root_build_dir)
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.plugin)) {
151*61c4878aSAndroid Build Coastguard Worker        inputs = [ invoker.plugin ]
152*61c4878aSAndroid Build Coastguard Worker        args +=
153*61c4878aSAndroid Build Coastguard Worker            [ "--plugin-path=" + rebase_path(invoker.plugin, root_build_dir) ]
154*61c4878aSAndroid Build Coastguard Worker      }
155*61c4878aSAndroid Build Coastguard Worker
156*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.outputs)) {
157*61c4878aSAndroid Build Coastguard Worker        outputs = invoker.outputs
158*61c4878aSAndroid Build Coastguard Worker      } else {
159*61c4878aSAndroid Build Coastguard Worker        stamp = true
160*61c4878aSAndroid Build Coastguard Worker      }
161*61c4878aSAndroid Build Coastguard Worker
162*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.metadata)) {
163*61c4878aSAndroid Build Coastguard Worker        metadata = invoker.metadata
164*61c4878aSAndroid Build Coastguard Worker      }
165*61c4878aSAndroid Build Coastguard Worker    }
166*61c4878aSAndroid Build Coastguard Worker
167*61c4878aSAndroid Build Coastguard Worker    # Output a .json file with information about this proto library.
168*61c4878aSAndroid Build Coastguard Worker    _proto_info = {
169*61c4878aSAndroid Build Coastguard Worker      label = get_label_info(":${invoker.target_name}", "label_no_toolchain")
170*61c4878aSAndroid Build Coastguard Worker      protoc_outputs =
171*61c4878aSAndroid Build Coastguard Worker          rebase_path(get_target_outputs(":$target_name._gen"), root_build_dir)
172*61c4878aSAndroid Build Coastguard Worker      root = rebase_path(_out_dir, root_build_dir)
173*61c4878aSAndroid Build Coastguard Worker      package = invoker.package
174*61c4878aSAndroid Build Coastguard Worker
175*61c4878aSAndroid Build Coastguard Worker      nested_in_python_package = ""
176*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.python_package)) {
177*61c4878aSAndroid Build Coastguard Worker        nested_in_python_package =
178*61c4878aSAndroid Build Coastguard Worker            get_label_info(invoker.python_package, "label_no_toolchain")
179*61c4878aSAndroid Build Coastguard Worker      }
180*61c4878aSAndroid Build Coastguard Worker
181*61c4878aSAndroid Build Coastguard Worker      dependencies = []
182*61c4878aSAndroid Build Coastguard Worker      foreach(dep, invoker.deps) {
183*61c4878aSAndroid Build Coastguard Worker        dependencies +=
184*61c4878aSAndroid Build Coastguard Worker            rebase_path([ get_label_info(dep, "target_gen_dir") + "/" +
185*61c4878aSAndroid Build Coastguard Worker                              get_label_info(dep, "name") + ".json" ],
186*61c4878aSAndroid Build Coastguard Worker                        root_build_dir)
187*61c4878aSAndroid Build Coastguard Worker      }
188*61c4878aSAndroid Build Coastguard Worker    }
189*61c4878aSAndroid Build Coastguard Worker    write_file("$target_gen_dir/$target_name.json", _proto_info, "json")
190*61c4878aSAndroid Build Coastguard Worker  } else {
191*61c4878aSAndroid Build Coastguard Worker    # protoc is only ever invoked from pw_protobuf_compiler_TOOLCHAIN.
192*61c4878aSAndroid Build Coastguard Worker    not_needed([ "target_name" ])
193*61c4878aSAndroid Build Coastguard Worker    not_needed(invoker, "*")
194*61c4878aSAndroid Build Coastguard Worker  }
195*61c4878aSAndroid Build Coastguard Worker}
196*61c4878aSAndroid Build Coastguard Worker
197*61c4878aSAndroid Build Coastguard Worker# Generates pw_protobuf C++ code for proto files, creating a source_set of the
198*61c4878aSAndroid Build Coastguard Worker# generated files. This is internal and should not be used outside of this file.
199*61c4878aSAndroid Build Coastguard Worker# Use pw_proto_library instead.
200*61c4878aSAndroid Build Coastguard Workertemplate("_pw_pwpb_rpc_proto_library") {
201*61c4878aSAndroid Build Coastguard Worker  # Create a target which runs protoc configured with the pwpb_rpc plugin to
202*61c4878aSAndroid Build Coastguard Worker  # generate the C++ proto RPC headers.
203*61c4878aSAndroid Build Coastguard Worker  _pw_invoke_protoc(target_name) {
204*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", _forwarded_vars)
205*61c4878aSAndroid Build Coastguard Worker    language = "pwpb_rpc"
206*61c4878aSAndroid Build Coastguard Worker    plugin = "$dir_pw_rpc/py/pw_rpc/plugin_pwpb.py"
207*61c4878aSAndroid Build Coastguard Worker    python_deps = [ "$dir_pw_rpc/py" ]
208*61c4878aSAndroid Build Coastguard Worker  }
209*61c4878aSAndroid Build Coastguard Worker
210*61c4878aSAndroid Build Coastguard Worker  # Create a library with the generated source files.
211*61c4878aSAndroid Build Coastguard Worker  config("$target_name._include_path") {
212*61c4878aSAndroid Build Coastguard Worker    include_dirs = [ "${invoker.base_out_dir}/pwpb_rpc" ]
213*61c4878aSAndroid Build Coastguard Worker    visibility = [ ":*" ]
214*61c4878aSAndroid Build Coastguard Worker  }
215*61c4878aSAndroid Build Coastguard Worker
216*61c4878aSAndroid Build Coastguard Worker  pw_source_set(target_name) {
217*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
218*61c4878aSAndroid Build Coastguard Worker    public_configs = [ ":$target_name._include_path" ]
219*61c4878aSAndroid Build Coastguard Worker    deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
220*61c4878aSAndroid Build Coastguard Worker    public_deps = [
221*61c4878aSAndroid Build Coastguard Worker                    ":${invoker.base_target}.pwpb",
222*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_protobuf",
223*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc:server",
224*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc/pwpb:client_api",
225*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc/pwpb:server_api",
226*61c4878aSAndroid Build Coastguard Worker                  ] + invoker.deps
227*61c4878aSAndroid Build Coastguard Worker    public = invoker.outputs
228*61c4878aSAndroid Build Coastguard Worker    check_includes = false
229*61c4878aSAndroid Build Coastguard Worker  }
230*61c4878aSAndroid Build Coastguard Worker}
231*61c4878aSAndroid Build Coastguard Worker
232*61c4878aSAndroid Build Coastguard Workertemplate("_pw_pwpb_proto_library") {
233*61c4878aSAndroid Build Coastguard Worker  _pw_invoke_protoc(target_name) {
234*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", _forwarded_vars)
235*61c4878aSAndroid Build Coastguard Worker    language = "pwpb"
236*61c4878aSAndroid Build Coastguard Worker    plugin = "$dir_pw_protobuf/py/pw_protobuf/plugin.py"
237*61c4878aSAndroid Build Coastguard Worker    python_deps = [ "$dir_pw_protobuf/py" ]
238*61c4878aSAndroid Build Coastguard Worker  }
239*61c4878aSAndroid Build Coastguard Worker
240*61c4878aSAndroid Build Coastguard Worker  # Create a library with the generated source files.
241*61c4878aSAndroid Build Coastguard Worker  config("$target_name._include_path") {
242*61c4878aSAndroid Build Coastguard Worker    include_dirs = [ "${invoker.base_out_dir}/pwpb" ]
243*61c4878aSAndroid Build Coastguard Worker    visibility = [ ":*" ]
244*61c4878aSAndroid Build Coastguard Worker  }
245*61c4878aSAndroid Build Coastguard Worker
246*61c4878aSAndroid Build Coastguard Worker  pw_source_set(target_name) {
247*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
248*61c4878aSAndroid Build Coastguard Worker    public_configs = [ ":$target_name._include_path" ]
249*61c4878aSAndroid Build Coastguard Worker    deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
250*61c4878aSAndroid Build Coastguard Worker    public_deps = [
251*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_containers:vector",
252*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_string:string",
253*61c4878aSAndroid Build Coastguard Worker                    dir_pw_assert,
254*61c4878aSAndroid Build Coastguard Worker                    dir_pw_function,
255*61c4878aSAndroid Build Coastguard Worker                    dir_pw_preprocessor,
256*61c4878aSAndroid Build Coastguard Worker                    dir_pw_protobuf,
257*61c4878aSAndroid Build Coastguard Worker                    dir_pw_result,
258*61c4878aSAndroid Build Coastguard Worker                    dir_pw_status,
259*61c4878aSAndroid Build Coastguard Worker                  ] + invoker.deps
260*61c4878aSAndroid Build Coastguard Worker    sources = invoker.outputs
261*61c4878aSAndroid Build Coastguard Worker    public = filter_include(sources, [ "*.pwpb.h" ])
262*61c4878aSAndroid Build Coastguard Worker  }
263*61c4878aSAndroid Build Coastguard Worker}
264*61c4878aSAndroid Build Coastguard Worker
265*61c4878aSAndroid Build Coastguard Worker# Generates nanopb RPC code for proto files, creating a source_set of the
266*61c4878aSAndroid Build Coastguard Worker# generated files. This is internal and should not be used outside of this file.
267*61c4878aSAndroid Build Coastguard Worker# Use pw_proto_library instead.
268*61c4878aSAndroid Build Coastguard Workertemplate("_pw_nanopb_rpc_proto_library") {
269*61c4878aSAndroid Build Coastguard Worker  # Create a target which runs protoc configured with the nanopb_rpc plugin to
270*61c4878aSAndroid Build Coastguard Worker  # generate the C++ proto RPC headers.
271*61c4878aSAndroid Build Coastguard Worker  _pw_invoke_protoc(target_name) {
272*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", _forwarded_vars)
273*61c4878aSAndroid Build Coastguard Worker    language = "nanopb_rpc"
274*61c4878aSAndroid Build Coastguard Worker    plugin = "$dir_pw_rpc/py/pw_rpc/plugin_nanopb.py"
275*61c4878aSAndroid Build Coastguard Worker    python_deps = [ "$dir_pw_rpc/py" ]
276*61c4878aSAndroid Build Coastguard Worker  }
277*61c4878aSAndroid Build Coastguard Worker
278*61c4878aSAndroid Build Coastguard Worker  # Create a library with the generated source files.
279*61c4878aSAndroid Build Coastguard Worker  config("$target_name._include_path") {
280*61c4878aSAndroid Build Coastguard Worker    include_dirs = [ "${invoker.base_out_dir}/nanopb_rpc" ]
281*61c4878aSAndroid Build Coastguard Worker    visibility = [ ":*" ]
282*61c4878aSAndroid Build Coastguard Worker  }
283*61c4878aSAndroid Build Coastguard Worker
284*61c4878aSAndroid Build Coastguard Worker  pw_source_set(target_name) {
285*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
286*61c4878aSAndroid Build Coastguard Worker    public_configs = [ ":$target_name._include_path" ]
287*61c4878aSAndroid Build Coastguard Worker    deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
288*61c4878aSAndroid Build Coastguard Worker    public_deps = [
289*61c4878aSAndroid Build Coastguard Worker                    ":${invoker.base_target}.nanopb",
290*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc:server",
291*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc/nanopb:client_api",
292*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc/nanopb:server_api",
293*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_third_party/nanopb",
294*61c4878aSAndroid Build Coastguard Worker                  ] + invoker.deps
295*61c4878aSAndroid Build Coastguard Worker    public = invoker.outputs
296*61c4878aSAndroid Build Coastguard Worker    check_includes = false
297*61c4878aSAndroid Build Coastguard Worker  }
298*61c4878aSAndroid Build Coastguard Worker}
299*61c4878aSAndroid Build Coastguard Worker
300*61c4878aSAndroid Build Coastguard Worker# Generates nanopb code for proto files, creating a source_set of the generated
301*61c4878aSAndroid Build Coastguard Worker# files. This is internal and should not be used outside of this file. Use
302*61c4878aSAndroid Build Coastguard Worker# pw_proto_library instead.
303*61c4878aSAndroid Build Coastguard Workertemplate("_pw_nanopb_proto_library") {
304*61c4878aSAndroid Build Coastguard Worker  # When compiling with the Nanopb plugin, the nanopb.proto file is already
305*61c4878aSAndroid Build Coastguard Worker  # compiled internally, so skip recompiling it with protoc.
306*61c4878aSAndroid Build Coastguard Worker  if (rebase_path(invoker.sources, invoker.compile_dir) == [ "nanopb.proto" ]) {
307*61c4878aSAndroid Build Coastguard Worker    group("$target_name._gen") {
308*61c4878aSAndroid Build Coastguard Worker      deps = [
309*61c4878aSAndroid Build Coastguard Worker        ":${invoker.base_target}._sources($pw_protobuf_compiler_TOOLCHAIN)",
310*61c4878aSAndroid Build Coastguard Worker      ]
311*61c4878aSAndroid Build Coastguard Worker    }
312*61c4878aSAndroid Build Coastguard Worker
313*61c4878aSAndroid Build Coastguard Worker    group("$target_name") {
314*61c4878aSAndroid Build Coastguard Worker      deps = invoker.deps +
315*61c4878aSAndroid Build Coastguard Worker             [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
316*61c4878aSAndroid Build Coastguard Worker    }
317*61c4878aSAndroid Build Coastguard Worker  } else {
318*61c4878aSAndroid Build Coastguard Worker    # Create a target which runs protoc configured with the nanopb plugin to
319*61c4878aSAndroid Build Coastguard Worker    # generate the C proto sources.
320*61c4878aSAndroid Build Coastguard Worker    _pw_invoke_protoc(target_name) {
321*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(invoker, "*", _forwarded_vars)
322*61c4878aSAndroid Build Coastguard Worker      language = "nanopb"
323*61c4878aSAndroid Build Coastguard Worker      plugin = "$dir_pw_third_party_nanopb/generator/protoc-gen-nanopb"
324*61c4878aSAndroid Build Coastguard Worker      other_deps = [ "$dir_pw_third_party/nanopb:generate_nanopb_proto.action" ]
325*61c4878aSAndroid Build Coastguard Worker    }
326*61c4878aSAndroid Build Coastguard Worker
327*61c4878aSAndroid Build Coastguard Worker    # Create a library with the generated source files.
328*61c4878aSAndroid Build Coastguard Worker    config("$target_name._include_path") {
329*61c4878aSAndroid Build Coastguard Worker      include_dirs = [ "${invoker.base_out_dir}/nanopb" ]
330*61c4878aSAndroid Build Coastguard Worker      visibility = [ ":*" ]
331*61c4878aSAndroid Build Coastguard Worker    }
332*61c4878aSAndroid Build Coastguard Worker
333*61c4878aSAndroid Build Coastguard Worker    pw_source_set(target_name) {
334*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(invoker, _forwarded_vars)
335*61c4878aSAndroid Build Coastguard Worker      public_configs = [ ":$target_name._include_path" ]
336*61c4878aSAndroid Build Coastguard Worker      deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
337*61c4878aSAndroid Build Coastguard Worker      public_deps = [ "$dir_pw_third_party/nanopb" ] + invoker.deps
338*61c4878aSAndroid Build Coastguard Worker      sources = invoker.outputs
339*61c4878aSAndroid Build Coastguard Worker      public = filter_include(sources, [ "*.pb.h" ])
340*61c4878aSAndroid Build Coastguard Worker    }
341*61c4878aSAndroid Build Coastguard Worker  }
342*61c4878aSAndroid Build Coastguard Worker}
343*61c4878aSAndroid Build Coastguard Worker
344*61c4878aSAndroid Build Coastguard Worker# Generates raw RPC code for proto files, creating a source_set of the generated
345*61c4878aSAndroid Build Coastguard Worker# files. This is internal and should not be used outside of this file. Use
346*61c4878aSAndroid Build Coastguard Worker# pw_proto_library instead.
347*61c4878aSAndroid Build Coastguard Workertemplate("_pw_raw_rpc_proto_library") {
348*61c4878aSAndroid Build Coastguard Worker  # Create a target which runs protoc configured with the nanopb_rpc plugin to
349*61c4878aSAndroid Build Coastguard Worker  # generate the C++ proto RPC headers.
350*61c4878aSAndroid Build Coastguard Worker  _pw_invoke_protoc(target_name) {
351*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", _forwarded_vars)
352*61c4878aSAndroid Build Coastguard Worker    language = "raw_rpc"
353*61c4878aSAndroid Build Coastguard Worker    plugin = "$dir_pw_rpc/py/pw_rpc/plugin_raw.py"
354*61c4878aSAndroid Build Coastguard Worker    python_deps = [ "$dir_pw_rpc/py" ]
355*61c4878aSAndroid Build Coastguard Worker  }
356*61c4878aSAndroid Build Coastguard Worker
357*61c4878aSAndroid Build Coastguard Worker  # Create a library with the generated source files.
358*61c4878aSAndroid Build Coastguard Worker  config("$target_name._include_path") {
359*61c4878aSAndroid Build Coastguard Worker    include_dirs = [ "${invoker.base_out_dir}/raw_rpc" ]
360*61c4878aSAndroid Build Coastguard Worker    visibility = [ ":*" ]
361*61c4878aSAndroid Build Coastguard Worker  }
362*61c4878aSAndroid Build Coastguard Worker
363*61c4878aSAndroid Build Coastguard Worker  pw_source_set(target_name) {
364*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
365*61c4878aSAndroid Build Coastguard Worker    public_configs = [ ":$target_name._include_path" ]
366*61c4878aSAndroid Build Coastguard Worker    deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
367*61c4878aSAndroid Build Coastguard Worker    public_deps = [
368*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc:server",
369*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc/raw:client_api",
370*61c4878aSAndroid Build Coastguard Worker                    "$dir_pw_rpc/raw:server_api",
371*61c4878aSAndroid Build Coastguard Worker                  ] + invoker.deps
372*61c4878aSAndroid Build Coastguard Worker    public = invoker.outputs
373*61c4878aSAndroid Build Coastguard Worker    check_includes = false
374*61c4878aSAndroid Build Coastguard Worker  }
375*61c4878aSAndroid Build Coastguard Worker}
376*61c4878aSAndroid Build Coastguard Worker
377*61c4878aSAndroid Build Coastguard Worker# Generates Go code for proto files, listing the proto output directory in the
378*61c4878aSAndroid Build Coastguard Worker# metadata variable GOPATH. Internal use only.
379*61c4878aSAndroid Build Coastguard Workertemplate("_pw_go_proto_library") {
380*61c4878aSAndroid Build Coastguard Worker  _proto_gopath = "$root_gen_dir/go"
381*61c4878aSAndroid Build Coastguard Worker
382*61c4878aSAndroid Build Coastguard Worker  _pw_invoke_protoc(target_name) {
383*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*")
384*61c4878aSAndroid Build Coastguard Worker    language = "go"
385*61c4878aSAndroid Build Coastguard Worker    metadata = {
386*61c4878aSAndroid Build Coastguard Worker      gopath = [ "GOPATH+=" + rebase_path(_proto_gopath) ]
387*61c4878aSAndroid Build Coastguard Worker      external_deps = [
388*61c4878aSAndroid Build Coastguard Worker        "github.com/golang/protobuf/proto",
389*61c4878aSAndroid Build Coastguard Worker        "google.golang.org/grpc",
390*61c4878aSAndroid Build Coastguard Worker      ]
391*61c4878aSAndroid Build Coastguard Worker    }
392*61c4878aSAndroid Build Coastguard Worker
393*61c4878aSAndroid Build Coastguard Worker    # Override the default "$base_out_dir/$language" output path.
394*61c4878aSAndroid Build Coastguard Worker    out_dir = "$_proto_gopath/src"
395*61c4878aSAndroid Build Coastguard Worker  }
396*61c4878aSAndroid Build Coastguard Worker
397*61c4878aSAndroid Build Coastguard Worker  group(target_name) {
398*61c4878aSAndroid Build Coastguard Worker    deps =
399*61c4878aSAndroid Build Coastguard Worker        invoker.deps + [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
400*61c4878aSAndroid Build Coastguard Worker  }
401*61c4878aSAndroid Build Coastguard Worker}
402*61c4878aSAndroid Build Coastguard Worker
403*61c4878aSAndroid Build Coastguard Worker# Generates Python code for proto files, creating a pw_python_package containing
404*61c4878aSAndroid Build Coastguard Worker# the generated files. This is internal and should not be used outside of this
405*61c4878aSAndroid Build Coastguard Worker# file. Use pw_proto_library instead.
406*61c4878aSAndroid Build Coastguard Workertemplate("_pw_python_proto_library") {
407*61c4878aSAndroid Build Coastguard Worker  _pw_invoke_protoc(target_name) {
408*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, "*", _forwarded_vars + [ "python_package" ])
409*61c4878aSAndroid Build Coastguard Worker    language = "python"
410*61c4878aSAndroid Build Coastguard Worker
411*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.python_package)) {
412*61c4878aSAndroid Build Coastguard Worker      python_package = invoker.python_package
413*61c4878aSAndroid Build Coastguard Worker    }
414*61c4878aSAndroid Build Coastguard Worker  }
415*61c4878aSAndroid Build Coastguard Worker
416*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.python_package) && invoker.python_package != "") {
417*61c4878aSAndroid Build Coastguard Worker    # This package is nested in another Python package. Depending on this
418*61c4878aSAndroid Build Coastguard Worker    # its python subtarget is equivalent to depending on the Python package it
419*61c4878aSAndroid Build Coastguard Worker    # is nested in.
420*61c4878aSAndroid Build Coastguard Worker    pw_python_group(target_name) {
421*61c4878aSAndroid Build Coastguard Worker      python_deps = [ invoker.python_package ]
422*61c4878aSAndroid Build Coastguard Worker    }
423*61c4878aSAndroid Build Coastguard Worker
424*61c4878aSAndroid Build Coastguard Worker    # This proto library is merged into another package, but create a target to
425*61c4878aSAndroid Build Coastguard Worker    # collect its dependencies that the other package can depend on.
426*61c4878aSAndroid Build Coastguard Worker    pw_python_group(target_name + "._deps") {
427*61c4878aSAndroid Build Coastguard Worker      python_deps = invoker.deps
428*61c4878aSAndroid Build Coastguard Worker      other_deps =
429*61c4878aSAndroid Build Coastguard Worker          [ ":${invoker.target_name}._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
430*61c4878aSAndroid Build Coastguard Worker    }
431*61c4878aSAndroid Build Coastguard Worker  } else {
432*61c4878aSAndroid Build Coastguard Worker    # Create a Python package with the generated source files.
433*61c4878aSAndroid Build Coastguard Worker    pw_python_package(target_name) {
434*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(invoker, _forwarded_vars)
435*61c4878aSAndroid Build Coastguard Worker      _target_dir =
436*61c4878aSAndroid Build Coastguard Worker          get_path_info(get_label_info(":${invoker.base_target}", "dir"),
437*61c4878aSAndroid Build Coastguard Worker                        "abspath")
438*61c4878aSAndroid Build Coastguard Worker      generate_setup = {
439*61c4878aSAndroid Build Coastguard Worker        metadata = {
440*61c4878aSAndroid Build Coastguard Worker          # Default to a package name that include the full source path to avoid
441*61c4878aSAndroid Build Coastguard Worker          # conflicts with other packages when collecting all the .whl files
442*61c4878aSAndroid Build Coastguard Worker          # with pw_python_wheels().
443*61c4878aSAndroid Build Coastguard Worker          name =
444*61c4878aSAndroid Build Coastguard Worker              string_replace(string_replace(_target_dir, "//", ""), "/", "_") +
445*61c4878aSAndroid Build Coastguard Worker              "_" + invoker.base_target
446*61c4878aSAndroid Build Coastguard Worker
447*61c4878aSAndroid Build Coastguard Worker          # The package name should match where the __init__.py lives. If
448*61c4878aSAndroid Build Coastguard Worker          # module_as_package is specified use that for the Python package name.
449*61c4878aSAndroid Build Coastguard Worker          if (defined(invoker.module_as_package) &&
450*61c4878aSAndroid Build Coastguard Worker              invoker.module_as_package != "") {
451*61c4878aSAndroid Build Coastguard Worker            name = invoker.module_as_package
452*61c4878aSAndroid Build Coastguard Worker          }
453*61c4878aSAndroid Build Coastguard Worker          version =
454*61c4878aSAndroid Build Coastguard Worker              "0.0.1"  # TODO(hepler): Need to be able to set this verison.
455*61c4878aSAndroid Build Coastguard Worker        }
456*61c4878aSAndroid Build Coastguard Worker      }
457*61c4878aSAndroid Build Coastguard Worker      sources = invoker.outputs
458*61c4878aSAndroid Build Coastguard Worker      strip_prefix = "${invoker.base_out_dir}/python"
459*61c4878aSAndroid Build Coastguard Worker      python_deps = invoker.deps
460*61c4878aSAndroid Build Coastguard Worker      other_deps = [ ":$target_name._gen($pw_protobuf_compiler_TOOLCHAIN)" ]
461*61c4878aSAndroid Build Coastguard Worker      static_analysis = []
462*61c4878aSAndroid Build Coastguard Worker
463*61c4878aSAndroid Build Coastguard Worker      _pw_module_as_package = invoker.module_as_package != ""
464*61c4878aSAndroid Build Coastguard Worker    }
465*61c4878aSAndroid Build Coastguard Worker  }
466*61c4878aSAndroid Build Coastguard Worker}
467*61c4878aSAndroid Build Coastguard Worker
468*61c4878aSAndroid Build Coastguard Worker# Generates protobuf code from .proto definitions for various languages.
469*61c4878aSAndroid Build Coastguard Worker# For each supported generator, creates a sub-target named:
470*61c4878aSAndroid Build Coastguard Worker#
471*61c4878aSAndroid Build Coastguard Worker#   <target_name>.<generator>
472*61c4878aSAndroid Build Coastguard Worker#
473*61c4878aSAndroid Build Coastguard Worker# GN permits using abbreviated labels when the target name matches the directory
474*61c4878aSAndroid Build Coastguard Worker# name (e.g. //foo for //foo:foo). For consistency with this, the sub-targets
475*61c4878aSAndroid Build Coastguard Worker# for each generator are aliased to the directory when the target name is the
476*61c4878aSAndroid Build Coastguard Worker# same. For example, these two labels are equivalent:
477*61c4878aSAndroid Build Coastguard Worker#
478*61c4878aSAndroid Build Coastguard Worker#   //path/to/my_protos:my_protos.pwpb
479*61c4878aSAndroid Build Coastguard Worker#   //path/to/my_protos:pwpb
480*61c4878aSAndroid Build Coastguard Worker#
481*61c4878aSAndroid Build Coastguard Worker# pw_protobuf_library targets generate Python packages. As such, they must have
482*61c4878aSAndroid Build Coastguard Worker# globally unique package names. The first directory of the prefix or the first
483*61c4878aSAndroid Build Coastguard Worker# common directory of the sources is used as the Python package.
484*61c4878aSAndroid Build Coastguard Worker#
485*61c4878aSAndroid Build Coastguard Worker# Args:
486*61c4878aSAndroid Build Coastguard Worker#   sources: List of input .proto files.
487*61c4878aSAndroid Build Coastguard Worker#   deps: List of other pw_proto_library dependencies.
488*61c4878aSAndroid Build Coastguard Worker#   other_deps: List of other non-proto dependencies.
489*61c4878aSAndroid Build Coastguard Worker#   inputs: Other files on which the protos depend (e.g. nanopb .options files).
490*61c4878aSAndroid Build Coastguard Worker#   prefix: A prefix to add to the source protos prior to compilation. For
491*61c4878aSAndroid Build Coastguard Worker#       example, a source called "foo.proto" with prefix = "nested" will be
492*61c4878aSAndroid Build Coastguard Worker#       compiled with protoc as "nested/foo.proto".
493*61c4878aSAndroid Build Coastguard Worker#   strip_prefix: Remove this prefix from the source protos. All source and
494*61c4878aSAndroid Build Coastguard Worker#       input files must be nested under this path.
495*61c4878aSAndroid Build Coastguard Worker#   python_package: Label of Python package to which to add the proto modules.
496*61c4878aSAndroid Build Coastguard Worker#       The .python subtarget will redirect to this package.
497*61c4878aSAndroid Build Coastguard Worker#
498*61c4878aSAndroid Build Coastguard Workertemplate("pw_proto_library") {
499*61c4878aSAndroid Build Coastguard Worker  assert(defined(invoker.sources) && invoker.sources != [],
500*61c4878aSAndroid Build Coastguard Worker         "pw_proto_library requires .proto source files")
501*61c4878aSAndroid Build Coastguard Worker
502*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.python_module_as_package)) {
503*61c4878aSAndroid Build Coastguard Worker    _module_as_package = invoker.python_module_as_package
504*61c4878aSAndroid Build Coastguard Worker
505*61c4878aSAndroid Build Coastguard Worker    _must_be_one_source = invoker.sources
506*61c4878aSAndroid Build Coastguard Worker    assert([ _must_be_one_source[0] ] == _must_be_one_source,
507*61c4878aSAndroid Build Coastguard Worker           "'python_module_as_package' requires exactly one source file")
508*61c4878aSAndroid Build Coastguard Worker    assert(_module_as_package != "",
509*61c4878aSAndroid Build Coastguard Worker           "'python_module_as_package' cannot be be empty")
510*61c4878aSAndroid Build Coastguard Worker    assert(string_split(_module_as_package, "/") == [ _module_as_package ],
511*61c4878aSAndroid Build Coastguard Worker           "'python_module_as_package' cannot contain slashes")
512*61c4878aSAndroid Build Coastguard Worker    assert(!defined(invoker.prefix),
513*61c4878aSAndroid Build Coastguard Worker           "'prefix' cannot be provided with 'python_module_as_package'")
514*61c4878aSAndroid Build Coastguard Worker  } else {
515*61c4878aSAndroid Build Coastguard Worker    _module_as_package = ""
516*61c4878aSAndroid Build Coastguard Worker  }
517*61c4878aSAndroid Build Coastguard Worker
518*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.strip_prefix)) {
519*61c4878aSAndroid Build Coastguard Worker    _source_root = get_path_info(invoker.strip_prefix, "abspath")
520*61c4878aSAndroid Build Coastguard Worker  } else {
521*61c4878aSAndroid Build Coastguard Worker    _source_root = get_path_info(".", "abspath")
522*61c4878aSAndroid Build Coastguard Worker  }
523*61c4878aSAndroid Build Coastguard Worker
524*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.prefix)) {
525*61c4878aSAndroid Build Coastguard Worker    _prefix = invoker.prefix
526*61c4878aSAndroid Build Coastguard Worker  } else {
527*61c4878aSAndroid Build Coastguard Worker    _prefix = ""
528*61c4878aSAndroid Build Coastguard Worker  }
529*61c4878aSAndroid Build Coastguard Worker
530*61c4878aSAndroid Build Coastguard Worker  _root_dir_name = ""
531*61c4878aSAndroid Build Coastguard Worker  _source_names = []
532*61c4878aSAndroid Build Coastguard Worker
533*61c4878aSAndroid Build Coastguard Worker  # Determine the Python package name to use for these protos. If there is no
534*61c4878aSAndroid Build Coastguard Worker  # prefix, the first directory the sources are nested under is used.
535*61c4878aSAndroid Build Coastguard Worker  foreach(source, rebase_path(invoker.sources, _source_root)) {
536*61c4878aSAndroid Build Coastguard Worker    _path_components = []
537*61c4878aSAndroid Build Coastguard Worker    _path_components = string_split(source, "/")
538*61c4878aSAndroid Build Coastguard Worker
539*61c4878aSAndroid Build Coastguard Worker    if (_root_dir_name == "") {
540*61c4878aSAndroid Build Coastguard Worker      _root_dir_name = _path_components[0]
541*61c4878aSAndroid Build Coastguard Worker    } else {
542*61c4878aSAndroid Build Coastguard Worker      assert(_prefix != "" || _path_components[0] == _root_dir_name,
543*61c4878aSAndroid Build Coastguard Worker             "Unless 'prefix' is supplied, all .proto sources in a " +
544*61c4878aSAndroid Build Coastguard Worker                 "pw_proto_library must be in the same directory tree")
545*61c4878aSAndroid Build Coastguard Worker    }
546*61c4878aSAndroid Build Coastguard Worker
547*61c4878aSAndroid Build Coastguard Worker    _source_names +=
548*61c4878aSAndroid Build Coastguard Worker        [ get_path_info(source, "dir") + "/" + get_path_info(source, "name") ]
549*61c4878aSAndroid Build Coastguard Worker  }
550*61c4878aSAndroid Build Coastguard Worker
551*61c4878aSAndroid Build Coastguard Worker  # If the 'prefix' was supplied, use that for the package directory.
552*61c4878aSAndroid Build Coastguard Worker  if (_prefix != "") {
553*61c4878aSAndroid Build Coastguard Worker    _prefix_path_components = string_split(_prefix, "/")
554*61c4878aSAndroid Build Coastguard Worker    _root_dir_name = _prefix_path_components[0]
555*61c4878aSAndroid Build Coastguard Worker  }
556*61c4878aSAndroid Build Coastguard Worker
557*61c4878aSAndroid Build Coastguard Worker  assert(
558*61c4878aSAndroid Build Coastguard Worker      _root_dir_name != "" && _root_dir_name != "." && _root_dir_name != "..",
559*61c4878aSAndroid Build Coastguard Worker      "Either a 'prefix' must be specified or all sources must be nested " +
560*61c4878aSAndroid Build Coastguard Worker          "under a common directory")
561*61c4878aSAndroid Build Coastguard Worker
562*61c4878aSAndroid Build Coastguard Worker  if (defined(invoker.deps)) {
563*61c4878aSAndroid Build Coastguard Worker    _deps = invoker.deps
564*61c4878aSAndroid Build Coastguard Worker  } else {
565*61c4878aSAndroid Build Coastguard Worker    _deps = []
566*61c4878aSAndroid Build Coastguard Worker  }
567*61c4878aSAndroid Build Coastguard Worker
568*61c4878aSAndroid Build Coastguard Worker  _common = {
569*61c4878aSAndroid Build Coastguard Worker    base_target = target_name
570*61c4878aSAndroid Build Coastguard Worker
571*61c4878aSAndroid Build Coastguard Worker    # This is the output directory for all files related to this proto library.
572*61c4878aSAndroid Build Coastguard Worker    # Sources are mirrored to "$base_out_dir/sources" and protoc puts outputs in
573*61c4878aSAndroid Build Coastguard Worker    # "$base_out_dir/$language" by default.
574*61c4878aSAndroid Build Coastguard Worker    base_out_dir =
575*61c4878aSAndroid Build Coastguard Worker        get_label_info(":$target_name($pw_protobuf_compiler_TOOLCHAIN)",
576*61c4878aSAndroid Build Coastguard Worker                       "target_gen_dir") + "/$target_name.proto_library"
577*61c4878aSAndroid Build Coastguard Worker
578*61c4878aSAndroid Build Coastguard Worker    compile_dir = "$base_out_dir/sources"
579*61c4878aSAndroid Build Coastguard Worker
580*61c4878aSAndroid Build Coastguard Worker    # Refer to the source files as the are mirrored to the output directory.
581*61c4878aSAndroid Build Coastguard Worker    sources = []
582*61c4878aSAndroid Build Coastguard Worker    foreach(file, rebase_path(invoker.sources, _source_root)) {
583*61c4878aSAndroid Build Coastguard Worker      sources += [ "$compile_dir/$_prefix/$file" ]
584*61c4878aSAndroid Build Coastguard Worker    }
585*61c4878aSAndroid Build Coastguard Worker
586*61c4878aSAndroid Build Coastguard Worker    package = _root_dir_name
587*61c4878aSAndroid Build Coastguard Worker
588*61c4878aSAndroid Build Coastguard Worker    use_legacy_oneof_interfaces = false
589*61c4878aSAndroid Build Coastguard Worker    if (defined(invoker.use_legacy_oneof_interfaces)) {
590*61c4878aSAndroid Build Coastguard Worker      use_legacy_oneof_interfaces = invoker.use_legacy_oneof_interfaces
591*61c4878aSAndroid Build Coastguard Worker    }
592*61c4878aSAndroid Build Coastguard Worker  }
593*61c4878aSAndroid Build Coastguard Worker
594*61c4878aSAndroid Build Coastguard Worker  # For each proto target, create a file which collects the base directories of
595*61c4878aSAndroid Build Coastguard Worker  # all of its dependencies to list as include paths to protoc.
596*61c4878aSAndroid Build Coastguard Worker  generated_file("$target_name._includes") {
597*61c4878aSAndroid Build Coastguard Worker    # Collect metadata from the include path files of each dependency.
598*61c4878aSAndroid Build Coastguard Worker
599*61c4878aSAndroid Build Coastguard Worker    deps = []
600*61c4878aSAndroid Build Coastguard Worker    foreach(dep, _deps) {
601*61c4878aSAndroid Build Coastguard Worker      _base = get_label_info(dep, "label_no_toolchain")
602*61c4878aSAndroid Build Coastguard Worker      deps += [ "$_base._includes(" + get_label_info(dep, "toolchain") + ")" ]
603*61c4878aSAndroid Build Coastguard Worker    }
604*61c4878aSAndroid Build Coastguard Worker
605*61c4878aSAndroid Build Coastguard Worker    data_keys = [ "protoc_includes" ]
606*61c4878aSAndroid Build Coastguard Worker    outputs = [ "${_common.base_out_dir}/includes.txt" ]
607*61c4878aSAndroid Build Coastguard Worker
608*61c4878aSAndroid Build Coastguard Worker    # Indicate this library's base directory for its dependents.
609*61c4878aSAndroid Build Coastguard Worker    metadata = {
610*61c4878aSAndroid Build Coastguard Worker      protoc_includes = [ rebase_path(_common.compile_dir, root_build_dir) ]
611*61c4878aSAndroid Build Coastguard Worker    }
612*61c4878aSAndroid Build Coastguard Worker  }
613*61c4878aSAndroid Build Coastguard Worker
614*61c4878aSAndroid Build Coastguard Worker  # Mirror the proto sources to the output directory with the prefix added.
615*61c4878aSAndroid Build Coastguard Worker  if (current_toolchain == pw_protobuf_compiler_TOOLCHAIN) {
616*61c4878aSAndroid Build Coastguard Worker    pw_mirror_tree("$target_name._sources") {
617*61c4878aSAndroid Build Coastguard Worker      source_root = _source_root
618*61c4878aSAndroid Build Coastguard Worker      sources = invoker.sources
619*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.other_deps)) {
620*61c4878aSAndroid Build Coastguard Worker        deps = invoker.other_deps
621*61c4878aSAndroid Build Coastguard Worker      }
622*61c4878aSAndroid Build Coastguard Worker
623*61c4878aSAndroid Build Coastguard Worker      if (defined(invoker.inputs)) {
624*61c4878aSAndroid Build Coastguard Worker        sources += invoker.inputs
625*61c4878aSAndroid Build Coastguard Worker      }
626*61c4878aSAndroid Build Coastguard Worker
627*61c4878aSAndroid Build Coastguard Worker      directory = "${_common.compile_dir}/$_prefix"
628*61c4878aSAndroid Build Coastguard Worker    }
629*61c4878aSAndroid Build Coastguard Worker  } else {
630*61c4878aSAndroid Build Coastguard Worker    not_needed(invoker,
631*61c4878aSAndroid Build Coastguard Worker               [
632*61c4878aSAndroid Build Coastguard Worker                 "inputs",
633*61c4878aSAndroid Build Coastguard Worker                 "other_deps",
634*61c4878aSAndroid Build Coastguard Worker               ])
635*61c4878aSAndroid Build Coastguard Worker  }
636*61c4878aSAndroid Build Coastguard Worker
637*61c4878aSAndroid Build Coastguard Worker  # Enumerate all of the protobuf generator targets.
638*61c4878aSAndroid Build Coastguard Worker
639*61c4878aSAndroid Build Coastguard Worker  _pw_pwpb_rpc_proto_library("$target_name.pwpb_rpc") {
640*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
641*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(_common, "*")
642*61c4878aSAndroid Build Coastguard Worker
643*61c4878aSAndroid Build Coastguard Worker    deps = []
644*61c4878aSAndroid Build Coastguard Worker    foreach(dep, _deps) {
645*61c4878aSAndroid Build Coastguard Worker      _base = get_label_info(dep, "label_no_toolchain")
646*61c4878aSAndroid Build Coastguard Worker      deps += [ "$_base.pwpb_rpc(" + get_label_info(dep, "toolchain") + ")" ]
647*61c4878aSAndroid Build Coastguard Worker    }
648*61c4878aSAndroid Build Coastguard Worker
649*61c4878aSAndroid Build Coastguard Worker    outputs = []
650*61c4878aSAndroid Build Coastguard Worker    foreach(name, _source_names) {
651*61c4878aSAndroid Build Coastguard Worker      outputs += [ "$base_out_dir/pwpb_rpc/$_prefix/${name}.rpc.pwpb.h" ]
652*61c4878aSAndroid Build Coastguard Worker    }
653*61c4878aSAndroid Build Coastguard Worker  }
654*61c4878aSAndroid Build Coastguard Worker
655*61c4878aSAndroid Build Coastguard Worker  _pw_pwpb_proto_library("$target_name.pwpb") {
656*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
657*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(_common, "*")
658*61c4878aSAndroid Build Coastguard Worker
659*61c4878aSAndroid Build Coastguard Worker    deps = []
660*61c4878aSAndroid Build Coastguard Worker    foreach(dep, _deps) {
661*61c4878aSAndroid Build Coastguard Worker      _base = get_label_info(dep, "label_no_toolchain")
662*61c4878aSAndroid Build Coastguard Worker      deps += [ "$_base.pwpb(" + get_label_info(dep, "toolchain") + ")" ]
663*61c4878aSAndroid Build Coastguard Worker    }
664*61c4878aSAndroid Build Coastguard Worker
665*61c4878aSAndroid Build Coastguard Worker    outputs = []
666*61c4878aSAndroid Build Coastguard Worker    foreach(name, _source_names) {
667*61c4878aSAndroid Build Coastguard Worker      outputs += [ "$base_out_dir/pwpb/$_prefix/${name}.pwpb.h" ]
668*61c4878aSAndroid Build Coastguard Worker    }
669*61c4878aSAndroid Build Coastguard Worker  }
670*61c4878aSAndroid Build Coastguard Worker
671*61c4878aSAndroid Build Coastguard Worker  if (dir_pw_third_party_nanopb != "") {
672*61c4878aSAndroid Build Coastguard Worker    _pw_nanopb_rpc_proto_library("$target_name.nanopb_rpc") {
673*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(invoker, _forwarded_vars)
674*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(_common, "*")
675*61c4878aSAndroid Build Coastguard Worker
676*61c4878aSAndroid Build Coastguard Worker      deps = []
677*61c4878aSAndroid Build Coastguard Worker      foreach(dep, _deps) {
678*61c4878aSAndroid Build Coastguard Worker        _lbl = get_label_info(dep, "label_no_toolchain")
679*61c4878aSAndroid Build Coastguard Worker        deps += [ "$_lbl.nanopb_rpc(" + get_label_info(dep, "toolchain") + ")" ]
680*61c4878aSAndroid Build Coastguard Worker      }
681*61c4878aSAndroid Build Coastguard Worker
682*61c4878aSAndroid Build Coastguard Worker      outputs = []
683*61c4878aSAndroid Build Coastguard Worker      foreach(name, _source_names) {
684*61c4878aSAndroid Build Coastguard Worker        outputs += [ "$base_out_dir/nanopb_rpc/$_prefix/${name}.rpc.pb.h" ]
685*61c4878aSAndroid Build Coastguard Worker      }
686*61c4878aSAndroid Build Coastguard Worker    }
687*61c4878aSAndroid Build Coastguard Worker
688*61c4878aSAndroid Build Coastguard Worker    _pw_nanopb_proto_library("$target_name.nanopb") {
689*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(invoker, _forwarded_vars)
690*61c4878aSAndroid Build Coastguard Worker      forward_variables_from(_common, "*")
691*61c4878aSAndroid Build Coastguard Worker
692*61c4878aSAndroid Build Coastguard Worker      deps = []
693*61c4878aSAndroid Build Coastguard Worker      foreach(dep, _deps) {
694*61c4878aSAndroid Build Coastguard Worker        _base = get_label_info(dep, "label_no_toolchain")
695*61c4878aSAndroid Build Coastguard Worker        deps += [ "$_base.nanopb(" + get_label_info(dep, "toolchain") + ")" ]
696*61c4878aSAndroid Build Coastguard Worker      }
697*61c4878aSAndroid Build Coastguard Worker
698*61c4878aSAndroid Build Coastguard Worker      outputs = []
699*61c4878aSAndroid Build Coastguard Worker      foreach(name, _source_names) {
700*61c4878aSAndroid Build Coastguard Worker        outputs += [
701*61c4878aSAndroid Build Coastguard Worker          "$base_out_dir/nanopb/$_prefix/${name}.pb.h",
702*61c4878aSAndroid Build Coastguard Worker          "$base_out_dir/nanopb/$_prefix/${name}.pb.c",
703*61c4878aSAndroid Build Coastguard Worker        ]
704*61c4878aSAndroid Build Coastguard Worker      }
705*61c4878aSAndroid Build Coastguard Worker    }
706*61c4878aSAndroid Build Coastguard Worker  } else {
707*61c4878aSAndroid Build Coastguard Worker    pw_error("$target_name.nanopb_rpc") {
708*61c4878aSAndroid Build Coastguard Worker      message =
709*61c4878aSAndroid Build Coastguard Worker          "\$dir_pw_third_party_nanopb must be set to generate nanopb RPC code."
710*61c4878aSAndroid Build Coastguard Worker    }
711*61c4878aSAndroid Build Coastguard Worker
712*61c4878aSAndroid Build Coastguard Worker    pw_error("$target_name.nanopb") {
713*61c4878aSAndroid Build Coastguard Worker      message =
714*61c4878aSAndroid Build Coastguard Worker          "\$dir_pw_third_party_nanopb must be set to compile nanopb protobufs."
715*61c4878aSAndroid Build Coastguard Worker    }
716*61c4878aSAndroid Build Coastguard Worker  }
717*61c4878aSAndroid Build Coastguard Worker
718*61c4878aSAndroid Build Coastguard Worker  _pw_raw_rpc_proto_library("$target_name.raw_rpc") {
719*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, _forwarded_vars)
720*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(_common, "*")
721*61c4878aSAndroid Build Coastguard Worker
722*61c4878aSAndroid Build Coastguard Worker    deps = []
723*61c4878aSAndroid Build Coastguard Worker    foreach(dep, _deps) {
724*61c4878aSAndroid Build Coastguard Worker      _base = get_label_info(dep, "label_no_toolchain")
725*61c4878aSAndroid Build Coastguard Worker      deps += [ "$_base.raw_rpc(" + get_label_info(dep, "toolchain") + ")" ]
726*61c4878aSAndroid Build Coastguard Worker    }
727*61c4878aSAndroid Build Coastguard Worker
728*61c4878aSAndroid Build Coastguard Worker    outputs = []
729*61c4878aSAndroid Build Coastguard Worker    foreach(name, _source_names) {
730*61c4878aSAndroid Build Coastguard Worker      outputs += [ "$base_out_dir/raw_rpc/$_prefix/${name}.raw_rpc.pb.h" ]
731*61c4878aSAndroid Build Coastguard Worker    }
732*61c4878aSAndroid Build Coastguard Worker  }
733*61c4878aSAndroid Build Coastguard Worker
734*61c4878aSAndroid Build Coastguard Worker  _pw_go_proto_library("$target_name.go") {
735*61c4878aSAndroid Build Coastguard Worker    sources = _common.sources
736*61c4878aSAndroid Build Coastguard Worker
737*61c4878aSAndroid Build Coastguard Worker    deps = []
738*61c4878aSAndroid Build Coastguard Worker    foreach(dep, _deps) {
739*61c4878aSAndroid Build Coastguard Worker      _base = get_label_info(dep, "label_no_toolchain")
740*61c4878aSAndroid Build Coastguard Worker      deps += [ "$_base.go(" + get_label_info(dep, "toolchain") + ")" ]
741*61c4878aSAndroid Build Coastguard Worker    }
742*61c4878aSAndroid Build Coastguard Worker
743*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(_common, "*")
744*61c4878aSAndroid Build Coastguard Worker  }
745*61c4878aSAndroid Build Coastguard Worker
746*61c4878aSAndroid Build Coastguard Worker  _pw_python_proto_library("$target_name.python") {
747*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(_common, "*")
748*61c4878aSAndroid Build Coastguard Worker    forward_variables_from(invoker, [ "python_package" ])
749*61c4878aSAndroid Build Coastguard Worker    module_as_package = _module_as_package
750*61c4878aSAndroid Build Coastguard Worker
751*61c4878aSAndroid Build Coastguard Worker    deps = []
752*61c4878aSAndroid Build Coastguard Worker    foreach(dep, _deps) {
753*61c4878aSAndroid Build Coastguard Worker      _base = get_label_info(dep, "label_no_toolchain")
754*61c4878aSAndroid Build Coastguard Worker      deps += [ "$_base.python(" + get_label_info(dep, "toolchain") + ")" ]
755*61c4878aSAndroid Build Coastguard Worker    }
756*61c4878aSAndroid Build Coastguard Worker
757*61c4878aSAndroid Build Coastguard Worker    if (module_as_package == "") {
758*61c4878aSAndroid Build Coastguard Worker      _python_prefix = "$base_out_dir/python/$_prefix"
759*61c4878aSAndroid Build Coastguard Worker    } else {
760*61c4878aSAndroid Build Coastguard Worker      _python_prefix = "$base_out_dir/python/$module_as_package"
761*61c4878aSAndroid Build Coastguard Worker    }
762*61c4878aSAndroid Build Coastguard Worker
763*61c4878aSAndroid Build Coastguard Worker    outputs = []
764*61c4878aSAndroid Build Coastguard Worker    foreach(name, _source_names) {
765*61c4878aSAndroid Build Coastguard Worker      outputs += [
766*61c4878aSAndroid Build Coastguard Worker        "$_python_prefix/${name}_pb2.py",
767*61c4878aSAndroid Build Coastguard Worker        "$_python_prefix/${name}_pb2.pyi",
768*61c4878aSAndroid Build Coastguard Worker      ]
769*61c4878aSAndroid Build Coastguard Worker    }
770*61c4878aSAndroid Build Coastguard Worker  }
771*61c4878aSAndroid Build Coastguard Worker
772*61c4878aSAndroid Build Coastguard Worker  # All supported pw_protobuf generators.
773*61c4878aSAndroid Build Coastguard Worker  _protobuf_generators = [
774*61c4878aSAndroid Build Coastguard Worker    "pwpb",
775*61c4878aSAndroid Build Coastguard Worker    "pwpb_rpc",
776*61c4878aSAndroid Build Coastguard Worker    "nanopb",
777*61c4878aSAndroid Build Coastguard Worker    "nanopb_rpc",
778*61c4878aSAndroid Build Coastguard Worker    "raw_rpc",
779*61c4878aSAndroid Build Coastguard Worker    "go",
780*61c4878aSAndroid Build Coastguard Worker    "python",
781*61c4878aSAndroid Build Coastguard Worker  ]
782*61c4878aSAndroid Build Coastguard Worker
783*61c4878aSAndroid Build Coastguard Worker  # If the label matches the directory name, alias the subtargets to the
784*61c4878aSAndroid Build Coastguard Worker  # directory (e.g. //foo:nanopb is an alias for //foo:foo.nanopb).
785*61c4878aSAndroid Build Coastguard Worker  if (get_label_info(":$target_name", "name") ==
786*61c4878aSAndroid Build Coastguard Worker      get_path_info(get_label_info(":$target_name", "dir"), "name")) {
787*61c4878aSAndroid Build Coastguard Worker    foreach(_generator, _protobuf_generators - [ "python" ]) {
788*61c4878aSAndroid Build Coastguard Worker      group(_generator) {
789*61c4878aSAndroid Build Coastguard Worker        public_deps = [ ":${invoker.target_name}.$_generator" ]
790*61c4878aSAndroid Build Coastguard Worker      }
791*61c4878aSAndroid Build Coastguard Worker    }
792*61c4878aSAndroid Build Coastguard Worker
793*61c4878aSAndroid Build Coastguard Worker    pw_python_group("python") {
794*61c4878aSAndroid Build Coastguard Worker      python_deps = [ ":${invoker.target_name}.python" ]
795*61c4878aSAndroid Build Coastguard Worker    }
796*61c4878aSAndroid Build Coastguard Worker  }
797*61c4878aSAndroid Build Coastguard Worker
798*61c4878aSAndroid Build Coastguard Worker  # If the user attempts to use the target directly instead of one of the
799*61c4878aSAndroid Build Coastguard Worker  # generator targets, run a script which prints a nice error message.
800*61c4878aSAndroid Build Coastguard Worker  pw_python_action(target_name) {
801*61c4878aSAndroid Build Coastguard Worker    script = string_join("/",
802*61c4878aSAndroid Build Coastguard Worker                         [
803*61c4878aSAndroid Build Coastguard Worker                           dir_pw_protobuf_compiler,
804*61c4878aSAndroid Build Coastguard Worker                           "py",
805*61c4878aSAndroid Build Coastguard Worker                           "pw_protobuf_compiler",
806*61c4878aSAndroid Build Coastguard Worker                           "proto_target_invalid.py",
807*61c4878aSAndroid Build Coastguard Worker                         ])
808*61c4878aSAndroid Build Coastguard Worker    args = [
809*61c4878aSAndroid Build Coastguard Worker             "--target",
810*61c4878aSAndroid Build Coastguard Worker             target_name,
811*61c4878aSAndroid Build Coastguard Worker             "--dir",
812*61c4878aSAndroid Build Coastguard Worker             get_path_info(".", "abspath"),
813*61c4878aSAndroid Build Coastguard Worker             "--root",
814*61c4878aSAndroid Build Coastguard Worker             "//",
815*61c4878aSAndroid Build Coastguard Worker           ] + _protobuf_generators
816*61c4878aSAndroid Build Coastguard Worker    stamp = true
817*61c4878aSAndroid Build Coastguard Worker  }
818*61c4878aSAndroid Build Coastguard Worker}
819