blob: 1e8e5987e8ed288b062c0f9fcabb0b1c1f6fe5c9 [file] [log] [blame]
Alexei Frolove19ebb82020-05-14 17:21:20 -07001# Copyright 2020 The Pigweed Authors
Alexei Frolov942adf02019-12-11 17:07:28 -08002#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7# https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
Armando Montanezfb3d3fb2020-06-09 18:12:12 -070015import("//build_overrides/pigweed.gni")
16
Alexei Frolovb499d3f2020-10-28 13:00:08 -070017import("$dir_pw_build/error.gni")
Alexei Frolov05d8ef22020-06-08 10:32:29 -070018import("$dir_pw_build/input_group.gni")
Wyatt Hepler752d7d32021-03-02 09:02:23 -080019import("$dir_pw_build/mirror_tree.gni")
Alexei Frolova4c0aee2020-12-01 13:48:48 -080020import("$dir_pw_build/python.gni")
Wyatt Hepler51ded742020-10-19 14:45:27 -070021import("$dir_pw_build/python_action.gni")
Alexei Frolovedd2f142020-06-09 19:11:27 -070022import("$dir_pw_build/target_types.gni")
Alexei Frolovdd6fa5c2020-08-11 10:04:01 -070023import("$dir_pw_third_party/nanopb/nanopb.gni")
Wyatt Heplerd49f8fe2020-10-15 10:13:47 -070024
Wyatt Heplerd9336a42020-11-10 09:47:30 -080025# Variables forwarded from the public pw_proto_library template to the final
26# pw_source_set.
Wyatt Heplere0c4fdc2020-05-29 17:26:19 -070027_forwarded_vars = [
28 "testonly",
29 "visibility",
30]
31
Wyatt Heplerd9336a42020-11-10 09:47:30 -080032# Internal template that invokes protoc with a pw_python_action. This should not
33# be used outside of this file; use pw_proto_library instead.
34#
35# This creates the internal GN target $target_name.$language._gen that compiles
36# proto files with protoc.
37template("_pw_invoke_protoc") {
Wyatt Hepler752d7d32021-03-02 09:02:23 -080038 if (defined(invoker.out_dir)) {
39 _out_dir = invoker.out_dir
40 } else {
41 _out_dir = "${invoker.base_out_dir}/${invoker.language}"
42 if (defined(invoker.module_as_package) && invoker.module_as_package != "") {
43 assert(invoker.language == "python")
44 _out_dir = "$_out_dir/${invoker.module_as_package}"
45 }
46 }
47
48 _includes =
49 rebase_path(get_target_outputs(":${invoker.base_target}._includes"))
Wyatt Heplerd9336a42020-11-10 09:47:30 -080050
51 pw_python_action("$target_name._gen") {
52 forward_variables_from(invoker, [ "metadata" ])
53 script =
54 "$dir_pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py"
55
Wyatt Hepler438caa02021-01-15 17:13:11 -080056 python_deps = [ "$dir_pw_protobuf_compiler/py" ]
57 if (defined(invoker.python_deps)) {
58 python_deps += invoker.python_deps
59 }
60
Wyatt Heplerd9336a42020-11-10 09:47:30 -080061 deps = [
Wyatt Hepler752d7d32021-03-02 09:02:23 -080062 ":${invoker.base_target}._includes",
63 ":${invoker.base_target}._sources",
64 ]
65
66 foreach(dep, invoker.deps) {
67 deps += [ get_label_info(dep, "label_no_toolchain") + "._gen" ]
68 }
69
70 if (defined(invoker.plugin_deps)) {
71 deps += invoker.plugin_deps
72 }
Wyatt Heplerd9336a42020-11-10 09:47:30 -080073
74 args = [
75 "--language",
76 invoker.language,
Wyatt Heplerd9336a42020-11-10 09:47:30 -080077 "--include-file",
Wyatt Hepler752d7d32021-03-02 09:02:23 -080078 _includes[0],
79 "--compile-dir",
80 rebase_path(invoker.compile_dir),
Wyatt Heplerd9336a42020-11-10 09:47:30 -080081 "--out-dir",
Wyatt Hepler752d7d32021-03-02 09:02:23 -080082 rebase_path(_out_dir),
83 "--sources",
Wyatt Heplerd9336a42020-11-10 09:47:30 -080084 ] + rebase_path(invoker.sources)
85
Wyatt Heplerd9336a42020-11-10 09:47:30 -080086 if (defined(invoker.plugin)) {
Wyatt Hepler752d7d32021-03-02 09:02:23 -080087 inputs = [ invoker.plugin ]
Wyatt Heplerd9336a42020-11-10 09:47:30 -080088 args += [ "--plugin-path=" + rebase_path(invoker.plugin) ]
89 }
90
Wyatt Hepler752d7d32021-03-02 09:02:23 -080091 if (defined(invoker.outputs)) {
92 outputs = invoker.outputs
93 } else {
Wyatt Heplerd9336a42020-11-10 09:47:30 -080094 stamp = true
95 }
Wyatt Heplerd9336a42020-11-10 09:47:30 -080096 }
97}
98
Alexei Frolovf39cd8b2020-04-13 17:59:20 -070099# Generates pw_protobuf C++ code for proto files, creating a source_set of the
100# generated files. This is internal and should not be used outside of this file.
101# Use pw_proto_library instead.
Alexei Frolovf39cd8b2020-04-13 17:59:20 -0700102template("_pw_pwpb_proto_library") {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800103 _pw_invoke_protoc(target_name) {
104 forward_variables_from(invoker, "*", _forwarded_vars)
105 language = "pwpb"
106 plugin = "$dir_pw_protobuf/py/pw_protobuf/plugin.py"
Wyatt Hepler438caa02021-01-15 17:13:11 -0800107 python_deps = [ "$dir_pw_protobuf/py" ]
Alexei Frolov942adf02019-12-11 17:07:28 -0800108 }
109
110 # Create a library with the generated source files.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800111 config("$target_name._include_path") {
112 include_dirs = [ "${invoker.base_out_dir}/pwpb" ]
113 visibility = [ ":*" ]
114 }
115
Alexei Frolovedd2f142020-06-09 19:11:27 -0700116 pw_source_set(target_name) {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800117 forward_variables_from(invoker, _forwarded_vars)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800118 public_configs = [ ":$target_name._include_path" ]
119 deps = [ ":$target_name._gen($default_toolchain)" ]
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800120 public_deps = [ dir_pw_protobuf ] + invoker.deps
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800121 sources = invoker.outputs
Alexei Frolovf39cd8b2020-04-13 17:59:20 -0700122 public = filter_include(sources, [ "*.pwpb.h" ])
123 }
124}
125
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700126# Generates nanopb RPC code for proto files, creating a source_set of the
127# generated files. This is internal and should not be used outside of this file.
128# Use pw_proto_library instead.
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700129template("_pw_nanopb_rpc_proto_library") {
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700130 # Create a target which runs protoc configured with the nanopb_rpc plugin to
131 # generate the C++ proto RPC headers.
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800132 _pw_invoke_protoc(target_name) {
133 forward_variables_from(invoker, "*", _forwarded_vars)
134 language = "nanopb_rpc"
135 plugin = "$dir_pw_rpc/py/pw_rpc/plugin_nanopb.py"
Wyatt Hepler438caa02021-01-15 17:13:11 -0800136 python_deps = [ "$dir_pw_rpc/py" ]
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700137 }
138
139 # Create a library with the generated source files.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800140 config("$target_name._include_path") {
141 include_dirs = [ "${invoker.base_out_dir}/nanopb_rpc" ]
142 visibility = [ ":*" ]
143 }
144
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700145 pw_source_set(target_name) {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800146 forward_variables_from(invoker, _forwarded_vars)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800147 public_configs = [ ":$target_name._include_path" ]
148 deps = [ ":$target_name._gen($default_toolchain)" ]
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700149 public_deps = [
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800150 ":${invoker.base_target}.nanopb",
Wyatt Heplercbd09c22020-09-15 11:17:24 -0700151 "$dir_pw_rpc:server",
Alexei Frolova4d71502020-10-14 12:43:14 -0700152 "$dir_pw_rpc/nanopb:method_union",
Alexei Frolovdd6fa5c2020-08-11 10:04:01 -0700153 "$dir_pw_third_party/nanopb",
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800154 ] + invoker.deps
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800155 public = invoker.outputs
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700156 }
157}
158
Alexei Frolovf39cd8b2020-04-13 17:59:20 -0700159# Generates nanopb code for proto files, creating a source_set of the generated
160# files. This is internal and should not be used outside of this file. Use
161# pw_proto_library instead.
Alexei Frolovf39cd8b2020-04-13 17:59:20 -0700162template("_pw_nanopb_proto_library") {
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800163 # When compiling with the Nanopb plugin, the nanopb.proto file is already
164 # compiled internally, so skip recompiling it with protoc.
165 if (rebase_path(invoker.sources, invoker.compile_dir) == [ "nanopb.proto" ]) {
166 group("$target_name._gen") {
167 deps = [ ":${invoker.base_target}._sources" ]
168 }
Alexei Frolovf39cd8b2020-04-13 17:59:20 -0700169
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800170 group("$target_name") {
171 deps = invoker.deps + [ ":$target_name._gen($default_toolchain)" ]
172 }
173 } else {
174 # Create a target which runs protoc configured with the nanopb plugin to
175 # generate the C proto sources.
176 _pw_invoke_protoc(target_name) {
177 forward_variables_from(invoker, "*", _forwarded_vars)
178 language = "nanopb"
179 plugin = "$dir_pw_third_party_nanopb/generator/protoc-gen-nanopb"
180 }
181
182 # Create a library with the generated source files.
183 config("$target_name._include_path") {
184 include_dirs = [ "${invoker.base_out_dir}/nanopb" ]
185 visibility = [ ":*" ]
186 }
187
188 pw_source_set(target_name) {
189 forward_variables_from(invoker, _forwarded_vars)
190 public_configs = [ ":$target_name._include_path" ]
191 deps = [ ":$target_name._gen($default_toolchain)" ]
192 public_deps = [ "$dir_pw_third_party/nanopb" ] + invoker.deps
193 sources = invoker.outputs
194 public = filter_include(sources, [ "*.pb.h" ])
195 }
Alexei Frolov942adf02019-12-11 17:07:28 -0800196 }
197}
198
Alexei Frolovc912ea72020-10-26 08:43:27 -0700199# Generates raw RPC code for proto files, creating a source_set of the generated
200# files. This is internal and should not be used outside of this file. Use
201# pw_proto_library instead.
Alexei Frolovc912ea72020-10-26 08:43:27 -0700202template("_pw_raw_rpc_proto_library") {
Alexei Frolovc912ea72020-10-26 08:43:27 -0700203 # Create a target which runs protoc configured with the nanopb_rpc plugin to
204 # generate the C++ proto RPC headers.
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800205 _pw_invoke_protoc(target_name) {
206 forward_variables_from(invoker, "*", _forwarded_vars)
207 language = "raw_rpc"
208 plugin = "$dir_pw_rpc/py/pw_rpc/plugin_raw.py"
Wyatt Hepler438caa02021-01-15 17:13:11 -0800209 python_deps = [ "$dir_pw_rpc/py" ]
Alexei Frolovc912ea72020-10-26 08:43:27 -0700210 }
211
212 # Create a library with the generated source files.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800213 config("$target_name._include_path") {
214 include_dirs = [ "${invoker.base_out_dir}/raw_rpc" ]
215 visibility = [ ":*" ]
216 }
217
Alexei Frolovc912ea72020-10-26 08:43:27 -0700218 pw_source_set(target_name) {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800219 forward_variables_from(invoker, _forwarded_vars)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800220 public_configs = [ ":$target_name._include_path" ]
221 deps = [ ":$target_name._gen($default_toolchain)" ]
Alexei Frolovc912ea72020-10-26 08:43:27 -0700222 public_deps = [
223 "$dir_pw_rpc:server",
224 "$dir_pw_rpc/raw:method_union",
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800225 ] + invoker.deps
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800226 public = invoker.outputs
Alexei Frolovc912ea72020-10-26 08:43:27 -0700227 }
228}
229
Alexei Frolovdef14712019-12-23 13:03:32 -0800230# Generates Go code for proto files, listing the proto output directory in the
231# metadata variable GOPATH. Internal use only.
Alexei Frolovdef14712019-12-23 13:03:32 -0800232template("_pw_go_proto_library") {
233 _proto_gopath = "$root_gen_dir/go"
Alexei Frolovdef14712019-12-23 13:03:32 -0800234
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800235 _pw_invoke_protoc(target_name) {
236 forward_variables_from(invoker, "*")
237 language = "go"
Alexei Frolovdef14712019-12-23 13:03:32 -0800238 metadata = {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800239 gopath = [ "GOPATH+=" + rebase_path(_proto_gopath) ]
Alexei Frolovc15a9882019-12-23 14:29:02 -0800240 external_deps = [
241 "github.com/golang/protobuf/proto",
242 "google.golang.org/grpc",
243 ]
Alexei Frolovdef14712019-12-23 13:03:32 -0800244 }
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800245
246 # Override the default "$base_out_dir/$language" output path.
247 out_dir = "$_proto_gopath/src"
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800248 }
249
250 group(target_name) {
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800251 deps = invoker.deps + [ ":$target_name._gen($default_toolchain)" ]
Alexei Frolovdef14712019-12-23 13:03:32 -0800252 }
253}
254
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800255# Generates Python code for proto files, creating a pw_python_package containing
256# the generated files. This is internal and should not be used outside of this
257# file. Use pw_proto_library instead.
258template("_pw_python_proto_library") {
259 _target = target_name
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800260
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800261 _pw_invoke_protoc(target_name) {
262 forward_variables_from(invoker, "*", _forwarded_vars)
263 language = "python"
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800264 plugin_deps = [ "$dir_pw_protobuf_compiler:protobuf_requirements.install" ]
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800265 }
266
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800267 _setup_py = "${invoker.base_out_dir}/python/setup.py"
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800268
269 # Create the setup and init files for the Python package.
Wyatt Hepler91741472021-02-03 08:45:10 -0800270 action(target_name + "._package_gen") {
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800271 script = "$dir_pw_protobuf_compiler/py/pw_protobuf_compiler/generate_python_package.py"
272 args = [
273 "--setup",
274 rebase_path(_setup_py),
275 "--package",
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800276 invoker._package_dir,
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800277 ] + rebase_path(invoker.outputs, "${invoker.base_out_dir}/python")
Wyatt Hepler32edf122020-12-11 17:21:34 -0800278
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800279 if (invoker.module_as_package != "") {
280 args += [ "--module-as-package" ]
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800281 }
282
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800283 public_deps = [ ":$_target._gen($default_toolchain)" ]
Wyatt Hepler91741472021-02-03 08:45:10 -0800284 outputs = [ _setup_py ]
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800285 }
286
287 # Create a Python package with the generated source files.
288 pw_python_package(target_name) {
289 forward_variables_from(invoker, _forwarded_vars)
290 setup = [ _setup_py ]
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800291 sources = invoker.outputs
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800292 python_deps = invoker.deps
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800293 other_deps = [ ":$_target._package_gen($default_toolchain)" ]
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800294 _pw_generated = true
295 }
296}
297
Alexei Frolov942adf02019-12-11 17:07:28 -0800298# Generates protobuf code from .proto definitions for various languages.
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700299# For each supported generator, creates a sub-target named:
Alexei Frolov942adf02019-12-11 17:07:28 -0800300#
Alexei Frolov8e30d462020-10-22 13:54:36 -0700301# <target_name>.<generator>
Alexei Frolov942adf02019-12-11 17:07:28 -0800302#
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800303# pw_protobuf_library targets generate Python packages. As such, they must have
304# globally unique package names. The first directory of the prefix or the first
305# common directory of the sources is used as the Python package.
306#
Alexei Frolov942adf02019-12-11 17:07:28 -0800307# Args:
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800308# sources: List of input .proto files.
309# deps: List of other pw_proto_library dependencies.
310# inputs: Other files on which the protos depend (e.g. nanopb .options files).
311# prefix: A prefix to add to the source protos prior to compilation. For
312# example, a source called "foo.proto" with prefix = "nested" will be
313# compiled with protoc as "nested/foo.proto".
314# strip_prefix: Remove this prefix from the source protos. All source and
315# input files must be nested under this path.
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700316#
Alexei Frolov942adf02019-12-11 17:07:28 -0800317template("pw_proto_library") {
318 assert(defined(invoker.sources) && invoker.sources != [],
Wyatt Heplerb4b73a62020-05-27 15:17:27 -0700319 "pw_proto_library requires .proto source files")
Alexei Frolov942adf02019-12-11 17:07:28 -0800320
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800321 if (defined(invoker.python_module_as_package)) {
322 _module_as_package = invoker.python_module_as_package
323
324 _must_be_one_source = invoker.sources
325 assert([ _must_be_one_source[0] ] == _must_be_one_source,
326 "'python_module_as_package' requires exactly one source file")
327 assert(_module_as_package != "",
328 "'python_module_as_package' cannot be be empty")
329 assert(string_split(_module_as_package, "/") == [ _module_as_package ],
330 "'python_module_as_package' cannot contain slashes")
331 assert(!defined(invoker.prefix),
332 "'prefix' cannot be provided with 'python_module_as_package'")
333 } else {
334 _module_as_package = ""
335 }
336
337 if (defined(invoker.strip_prefix)) {
338 _source_root = get_path_info(invoker.strip_prefix, "abspath")
339 } else {
340 _source_root = get_path_info(".", "abspath")
341 }
342
343 if (defined(invoker.prefix)) {
344 _prefix = invoker.prefix
345 } else {
346 _prefix = ""
347 }
348
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800349 _common = {
350 base_target = target_name
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800351
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800352 # This is the output directory for all files related to this proto library.
353 # Sources are mirrored to "$base_out_dir/sources" and protoc puts outputs in
354 # "$base_out_dir/$language" by default.
355 base_out_dir = get_label_info(":$target_name($default_toolchain)",
356 "target_gen_dir") + "/$target_name"
357
358 compile_dir = "$base_out_dir/sources"
359
360 # Refer to the source files as the are mirrored to the output directory.
361 sources = []
362 foreach(file, rebase_path(invoker.sources, _source_root)) {
363 sources += [ "$compile_dir/$_prefix/$file" ]
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800364 }
365 }
366
Wyatt Hepler91741472021-02-03 08:45:10 -0800367 _package_dir = ""
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800368 _source_names = []
Wyatt Hepler91741472021-02-03 08:45:10 -0800369
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800370 # Determine the Python package name to use for these protos. If there is no
371 # prefix, the first directory the sources are nested under is used.
372 foreach(source, rebase_path(invoker.sources, _source_root)) {
Wyatt Hepler91741472021-02-03 08:45:10 -0800373 _path_components = []
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800374 _path_components = string_split(source, "/")
Wyatt Hepler91741472021-02-03 08:45:10 -0800375
376 if (_package_dir == "") {
377 _package_dir = _path_components[0]
378 } else {
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800379 assert(_prefix != "" || _path_components[0] == _package_dir,
380 "Unless 'prefix' is supplied, all .proto sources in a " +
381 "pw_proto_library must be in the same directory tree")
Wyatt Hepler91741472021-02-03 08:45:10 -0800382 }
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800383
384 _source_names +=
385 [ get_path_info(source, "dir") + "/" + get_path_info(source, "name") ]
Wyatt Hepler91741472021-02-03 08:45:10 -0800386 }
387
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800388 # If the 'prefix' was supplied, use that for the package directory.
389 if (_prefix != "") {
390 _prefix_path_components = string_split(_prefix, "/")
391 _package_dir = _prefix_path_components[0]
392 }
393
394 assert(_package_dir != "" && _package_dir != "." && _package_dir != "..",
395 "Either a 'prefix' must be specified or all sources must be nested " +
396 "under a common directory")
397
398 # Define an action that is never executed to prevent duplicate proto packages
399 # from being declared. The target name and the output file include only the
400 # package directory, so different targets that use the same proto package name
401 # will conflict.
402 action("pw_proto_library.$_package_dir") {
403 script = "$dir_pw_build/py/pw_build/nop.py"
Wyatt Hepler91741472021-02-03 08:45:10 -0800404 visibility = []
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800405
406 # Place an error message in the output path (which is never created). If the
407 # package name conflicts occur in different BUILD.gn files, this results in
408 # an otherwise cryptic Ninja error, rather than a GN error.
409 outputs = [ "$root_out_dir/ " +
410 "ERROR - Multiple pw_proto_library targets create the " +
411 "'$_package_dir' package. Change the package name by setting " +
412 "the \"prefix\" arg or move the protos to a different " +
413 "directory, then re-run gn gen." ]
Wyatt Hepler91741472021-02-03 08:45:10 -0800414 }
415
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800416 if (defined(invoker.deps)) {
417 _deps = invoker.deps
418 } else {
419 _deps = []
420 }
421
Alexei Frolove19ebb82020-05-14 17:21:20 -0700422 # For each proto target, create a file which collects the base directories of
423 # all of its dependencies to list as include paths to protoc.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800424 generated_file("$target_name._includes") {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800425 # Collect metadata from the include path files of each dependency.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800426 deps = process_file_template(_deps, "{{source}}._includes")
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800427
Alexei Frolove19ebb82020-05-14 17:21:20 -0700428 data_keys = [ "protoc_includes" ]
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800429 outputs = [ "$target_gen_dir/${_common.base_target}/includes.txt" ]
Alexei Frolove19ebb82020-05-14 17:21:20 -0700430
431 # Indicate this library's base directory for its dependents.
432 metadata = {
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800433 protoc_includes = [ rebase_path(_common.compile_dir) ]
Alexei Frolove19ebb82020-05-14 17:21:20 -0700434 }
435 }
436
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800437 # Mirror the proto sources to the output directory with the prefix added.
438 pw_mirror_tree("$target_name._sources") {
439 source_root = _source_root
440 sources = invoker.sources
Alexei Frolov05d8ef22020-06-08 10:32:29 -0700441
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800442 if (defined(invoker.inputs)) {
443 sources += invoker.inputs
444 }
445
446 directory = "${_common.compile_dir}/$_prefix"
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700447 }
448
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700449 # Enumerate all of the protobuf generator targets.
Alexei Frolovc4b62ec2020-07-13 08:35:10 -0700450
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800451 _pw_pwpb_proto_library("$target_name.pwpb") {
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700452 forward_variables_from(invoker, _forwarded_vars)
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800453 forward_variables_from(_common, "*")
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800454
455 deps = []
456 foreach(dep, _deps) {
457 _base = get_label_info(dep, "label_no_toolchain")
458 deps += [ "$_base.pwpb(" + get_label_info(dep, "toolchain") + ")" ]
459 }
460
461 outputs = []
462 foreach(name, _source_names) {
463 outputs += [ "$base_out_dir/pwpb/$_prefix/${name}.pwpb.h" ]
464 }
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700465 }
466
467 if (dir_pw_third_party_nanopb != "") {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800468 _pw_nanopb_rpc_proto_library("$target_name.nanopb_rpc") {
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700469 forward_variables_from(invoker, _forwarded_vars)
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800470 forward_variables_from(_common, "*")
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800471
472 deps = []
473 foreach(dep, _deps) {
474 _lbl = get_label_info(dep, "label_no_toolchain")
475 deps += [ "$_lbl.nanopb_rpc(" + get_label_info(dep, "toolchain") + ")" ]
476 }
477
478 outputs = []
479 foreach(name, _source_names) {
480 outputs += [ "$base_out_dir/nanopb_rpc/$_prefix/${name}.rpc.pb.h" ]
481 }
Alexei Frolovc4b62ec2020-07-13 08:35:10 -0700482 }
483
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800484 _pw_nanopb_proto_library("$target_name.nanopb") {
485 forward_variables_from(invoker, _forwarded_vars)
486 forward_variables_from(_common, "*")
487
488 deps = []
489 foreach(dep, _deps) {
490 _base = get_label_info(dep, "label_no_toolchain")
491 deps += [ "$_base.nanopb(" + get_label_info(dep, "toolchain") + ")" ]
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800492 }
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800493
494 outputs = []
495 foreach(name, _source_names) {
496 outputs += [
497 "$base_out_dir/nanopb/$_prefix/${name}.pb.h",
498 "$base_out_dir/nanopb/$_prefix/${name}.pb.c",
499 ]
Wyatt Heplerd517afc2021-02-03 19:40:08 -0800500 }
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700501 }
502 } else {
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800503 pw_error("$target_name.nanopb_rpc") {
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700504 message =
505 "\$dir_pw_third_party_nanopb must be set to generate nanopb RPC code."
Alexei Frolov8185c822020-06-12 10:45:04 -0700506 }
Alexei Frolov942adf02019-12-11 17:07:28 -0800507
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800508 pw_error("$target_name.nanopb") {
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700509 message =
510 "\$dir_pw_third_party_nanopb must be set to compile nanopb protobufs."
Alexei Frolov942adf02019-12-11 17:07:28 -0800511 }
512 }
513
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800514 _pw_raw_rpc_proto_library("$target_name.raw_rpc") {
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700515 forward_variables_from(invoker, _forwarded_vars)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800516 forward_variables_from(_common, "*")
517
518 deps = []
519 foreach(dep, _deps) {
520 _base = get_label_info(dep, "label_no_toolchain")
521 deps += [ "$_base.raw_rpc(" + get_label_info(dep, "toolchain") + ")" ]
522 }
523
524 outputs = []
525 foreach(name, _source_names) {
526 outputs += [ "$base_out_dir/raw_rpc/$_prefix/${name}.raw_rpc.pb.h" ]
527 }
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700528 }
529
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800530 _pw_go_proto_library("$target_name.go") {
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800531 sources = _common.sources
532
533 deps = []
534 foreach(dep, _deps) {
535 _base = get_label_info(dep, "label_no_toolchain")
536 deps += [ "$_base.go(" + get_label_info(dep, "toolchain") + ")" ]
537 }
538
539 forward_variables_from(_common, "*")
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700540 }
541
Alexei Frolov38cad0c2020-12-03 12:36:24 -0800542 _pw_python_proto_library("$target_name.python") {
Alexei Frolov38cad0c2020-12-03 12:36:24 -0800543 forward_variables_from(_common, "*")
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800544 module_as_package = _module_as_package
545
546 deps = []
547 foreach(dep, _deps) {
548 _base = get_label_info(dep, "label_no_toolchain")
549 deps += [ "$_base.python(" + get_label_info(dep, "toolchain") + ")" ]
550 }
551
552 if (module_as_package == "") {
553 _python_prefix = "$base_out_dir/python/$_prefix"
554 } else {
555 _python_prefix = "$base_out_dir/python/$module_as_package"
556 }
557
558 outputs = []
559 foreach(name, _source_names) {
560 outputs += [
561 "$_python_prefix/${name}_pb2.py",
562 "$_python_prefix/${name}_pb2.pyi",
563 ]
564 }
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800565 }
566
Wyatt Heplerb4b73a62020-05-27 15:17:27 -0700567 # All supported pw_protobuf generators.
568 _protobuf_generators = [
569 "pwpb",
570 "nanopb",
Alexei Frolov79b7cb02020-07-06 13:51:43 -0700571 "nanopb_rpc",
Alexei Frolovc912ea72020-10-26 08:43:27 -0700572 "raw_rpc",
Wyatt Heplerb4b73a62020-05-27 15:17:27 -0700573 "go",
Alexei Frolova4c0aee2020-12-01 13:48:48 -0800574 "python",
Wyatt Heplerb4b73a62020-05-27 15:17:27 -0700575 ]
576
Alexei Frolov942adf02019-12-11 17:07:28 -0800577 # If the user attempts to use the target directly instead of one of the
Alexei Frolovf39cd8b2020-04-13 17:59:20 -0700578 # generator targets, run a script which prints a nice error message.
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700579 pw_python_action(target_name) {
Alexei Frolov942adf02019-12-11 17:07:28 -0800580 script = string_join("/",
581 [
582 dir_pw_protobuf_compiler,
583 "py",
584 "pw_protobuf_compiler",
585 "proto_target_invalid.py",
586 ])
587 args = [
588 "--target",
589 target_name,
590 "--dir",
591 get_path_info(".", "abspath"),
592 "--root",
593 "//",
Alexei Frolovb499d3f2020-10-28 13:00:08 -0700594 ] + _protobuf_generators
Alexei Frolov942adf02019-12-11 17:07:28 -0800595 stamp = true
596 }
597}