xref: /third_party/node/deps/v8/gni/proto_library.gni (revision 1cb0ef41)
1# Copyright 2019 the V8 project authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import("//build_overrides/build.gni")
6
7# This file should not be pulled in chromium builds.
8assert(!build_with_chromium)
9
10if (host_os == "win") {
11  _host_executable_suffix = ".exe"
12} else {
13  _host_executable_suffix = ""
14}
15
16template("proto_library") {
17  assert(defined(invoker.sources))
18  proto_sources = invoker.sources
19
20  # All the proto imports should be relative to the project root.
21  proto_in_dir = "//"
22  if (defined(invoker.proto_in_dir)) {
23    proto_in_dir = invoker.proto_in_dir
24  }
25  assert(defined(invoker.proto_out_dir),
26         "proto_out_dir must be explicitly defined")
27  proto_out_dir = invoker.proto_out_dir
28
29  # We don't support generate_python in the standalone build, but still must
30  # check that the caller sets this to false. This is because when building in
31  # the chromium tree, chromium's proto_library.gni in chrome (!= this) defaults
32  # generate_python = true.
33  assert(defined(invoker.generate_python) && !invoker.generate_python)
34
35  import_dirs = []
36  if (defined(invoker.import_dirs)) {
37    import_dirs = invoker.import_dirs
38  }
39
40  # If false will not generate the default .pb.{cc,h} files. Used for custom
41  # codegen plugins.
42  generate_cc = true
43  if (defined(invoker.generate_cc)) {
44    generate_cc = invoker.generate_cc
45  }
46
47  generate_descriptor = ""
48  if (defined(invoker.generate_descriptor)) {
49    generate_descriptor = invoker.generate_descriptor
50  }
51
52  if (defined(invoker.generator_plugin_label)) {
53    plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
54    plugin_path =
55        get_label_info(plugin_host_label, "root_out_dir") + "/" +
56        get_label_info(plugin_host_label, "name") + _host_executable_suffix
57    generate_with_plugin = true
58  } else if (defined(invoker.generator_plugin_script)) {
59    plugin_path = invoker.generator_plugin_script
60    generate_with_plugin = true
61  } else {
62    generate_with_plugin = false
63  }
64
65  if (generate_with_plugin) {
66    if (defined(invoker.generator_plugin_suffix)) {
67      generator_plugin_suffixes = [
68        "${invoker.generator_plugin_suffix}.h",
69        "${invoker.generator_plugin_suffix}.cc",
70      ]
71    } else {
72      generator_plugin_suffixes = invoker.generator_plugin_suffixes
73    }
74  }
75
76  out_dir = "$root_gen_dir/" + proto_out_dir
77  rel_out_dir = rebase_path(out_dir, root_build_dir)
78
79  # Prevent unused errors when generating descriptor only.
80  if (generate_descriptor != "") {
81    not_needed([ "rel_out_dir" ])
82  }
83
84  protos = rebase_path(proto_sources, proto_in_dir)
85  protogens = []
86
87  if (generate_descriptor != "") {
88    protogens += [ "$out_dir/${generate_descriptor}" ]
89  }
90
91  foreach(proto, protos) {
92    proto_dir = get_path_info(proto, "dir")
93    proto_name = get_path_info(proto, "name")
94    proto_path = proto_dir + "/" + proto_name
95
96    # Prevent unused errors when generating descriptor only.
97    if (generate_descriptor != "") {
98      not_needed([ "proto_path" ])
99    }
100
101    if (generate_cc) {
102      protogens += [
103        "$out_dir/$proto_path.pb.h",
104        "$out_dir/$proto_path.pb.cc",
105      ]
106    }
107    if (generate_with_plugin) {
108      foreach(suffix, generator_plugin_suffixes) {
109        protogens += [ "$out_dir/${proto_path}${suffix}" ]
110      }
111    }
112  }
113
114  config_name = "${target_name}_config"
115  if (generate_descriptor == "") {
116    action_name = "${target_name}_gen"
117    source_set_name = target_name
118  } else {
119    action_name = target_name
120  }
121
122  config(config_name) {
123    include_dirs = [ out_dir ]
124  }
125
126  # The XXX_gen action that generates the .pb.{cc,h} files.
127  action(action_name) {
128    if (generate_descriptor == "") {
129      visibility = [ ":$source_set_name" ]
130    }
131    sources = proto_sources
132    outputs = get_path_info(protogens, "abspath")
133
134    protoc_label = "//:protoc($host_toolchain)"
135    protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" +
136                  _host_executable_suffix
137    protoc_rebased_path = "./" + rebase_path(protoc_path, root_build_dir)
138    script = "//gni/protoc.py"
139    args = [
140      # Path should be rebased because |root_build_dir| for current toolchain
141      # may be different from |root_out_dir| of protoc built on host toolchain.
142      protoc_rebased_path,
143      "--proto_path",
144      rebase_path(proto_in_dir, root_build_dir),
145    ]
146
147    foreach(path, import_dirs) {
148      args += [
149        "--proto_path",
150        rebase_path(path, root_build_dir),
151      ]
152    }
153
154    if (generate_cc) {
155      cc_generator_options_ = ""
156      if (defined(invoker.cc_generator_options)) {
157        cc_generator_options_ = invoker.cc_generator_options
158      }
159      args += [
160        "--cpp_out",
161        cc_generator_options_ + rel_out_dir,
162      ]
163    }
164    if (generate_descriptor != "") {
165      depfile = "$out_dir/$generate_descriptor.d"
166      args += [
167        "--include_imports",
168        "--descriptor_set_out",
169        rebase_path("$out_dir/$generate_descriptor", root_build_dir),
170        "--dependency_out",
171        rebase_path(depfile, root_build_dir),
172      ]
173    }
174
175    if (generate_with_plugin) {
176      plugin_path_rebased = rebase_path(plugin_path, root_build_dir)
177      plugin_out_args = ""
178      if (defined(invoker.generator_plugin_options)) {
179        plugin_out_args += invoker.generator_plugin_options
180      }
181      plugin_out_args += ":$rel_out_dir"
182
183      args += [
184        "--plugin=protoc-gen-plugin=$plugin_path_rebased",
185        "--plugin_out=$plugin_out_args",
186      ]
187    }
188
189    args += rebase_path(proto_sources, root_build_dir)
190
191    inputs = [ protoc_path ]
192    deps = [ protoc_label ]
193
194    # TODO(hjd): Avoid adding to deps here this.
195    # When we generate BUILD files we need find the transitive proto,
196    # dependencies, so also add link_deps to actual deps so they show up
197    # in gn desc.
198    if (defined(invoker.link_deps)) {
199      deps += invoker.link_deps
200    }
201    if (generate_with_plugin) {
202      inputs += [ plugin_path ]
203      if (defined(plugin_host_label)) {
204        # Action depends on native generator plugin but for host toolchain only.
205        deps += [ plugin_host_label ]
206      }
207    }
208
209    if (defined(invoker.deps)) {
210      deps += invoker.deps
211    }
212  }  # action(action_name)
213
214  # The source_set that builds the generated .pb.cc files.
215  if (generate_descriptor == "") {
216    source_set(source_set_name) {
217      forward_variables_from(invoker,
218                             [
219                               "defines",
220                               "include_dirs",
221                               "public_configs",
222                               "testonly",
223                               "visibility",
224                             ])
225
226      sources = get_target_outputs(":$action_name")
227
228      if (defined(invoker.extra_configs)) {
229        configs += invoker.extra_configs
230      }
231
232      if (!defined(invoker.public_configs)) {
233        public_configs = []
234      }
235
236      public_configs += [
237        "//:protobuf_gen_config",
238        ":$config_name",
239      ]
240
241      # By default, propagate the config for |include_dirs| to dependent
242      # targets, so that public imports can be resolved to corresponding header
243      # files. In some cases, the embedder target handles include directory
244      # propagation itself, e.g. via a common config.
245      propagate_imports_configs = !defined(invoker.propagate_imports_configs) ||
246                                  invoker.propagate_imports_configs
247      if (propagate_imports_configs) {
248        public_configs += [ ":$config_name" ]
249      } else {
250        configs += [ ":$config_name" ]
251      }
252
253      # Use protobuf_full only for tests.
254      if (defined(invoker.use_protobuf_full) &&
255          invoker.use_protobuf_full == true) {
256        deps = [ "//:protobuf_full" ]
257      } else if (generate_cc) {
258        deps = [ "//:protobuf_lite" ]
259      } else {
260        deps = []
261      }
262
263      deps += [ ":$action_name" ]
264      if (defined(invoker.deps)) {
265        deps += invoker.deps
266      }
267    }  # source_set(source_set_name)
268  }
269}  # template
270