• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2017 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://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,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15template("proto_library") {
16  assert(defined(invoker.sources))
17  proto_sources = invoker.sources
18
19  # All the proto imports should be relative to the project root.
20  proto_in_dir = "//"
21  if (defined(invoker.proto_in_dir)) {
22    proto_in_dir = invoker.proto_in_dir
23  }
24  assert(defined(invoker.proto_out_dir),
25         "proto_out_dir must be explicitly defined")
26  proto_out_dir = invoker.proto_out_dir
27
28  # We don't support generate_python in the standalone build, but still must
29  # check that the caller sets this to false. This is because when building in
30  # the chromium tree, chromium's proto_library.gni in chrome (!= this) defaults
31  # generate_python = true.
32  assert(defined(invoker.generate_python) && !invoker.generate_python)
33
34  # If false will not generate the default .pb.{cc,h} files. Used for custom
35  # codegen plugins.
36  generate_cc = true
37  if (defined(invoker.generate_cc)) {
38    generate_cc = invoker.generate_cc
39  }
40
41  generate_descriptor = ""
42  if (defined(invoker.generate_descriptor)) {
43    generate_descriptor = invoker.generate_descriptor
44  }
45
46  if (defined(invoker.generator_plugin_label)) {
47    plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
48    plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" +
49                  get_label_info(plugin_host_label, "name")
50    generate_with_plugin = true
51  } else if (defined(invoker.generator_plugin_script)) {
52    plugin_path = invoker.generator_plugin_script
53    generate_with_plugin = true
54  } else {
55    generate_with_plugin = false
56  }
57
58  if (generate_with_plugin) {
59    if (defined(invoker.generator_plugin_suffix)) {
60      generator_plugin_suffixes = [
61        "${invoker.generator_plugin_suffix}.h",
62        "${invoker.generator_plugin_suffix}.cc",
63      ]
64    } else {
65      generator_plugin_suffixes = invoker.generator_plugin_suffixes
66    }
67  }
68
69  cc_out_dir = "$root_gen_dir/" + proto_out_dir
70  rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir)
71
72  protos = rebase_path(proto_sources, proto_in_dir)
73  protogens = []
74
75  if (generate_descriptor != "") {
76    protogens += [ "$root_gen_dir/" + generate_descriptor ]
77  }
78
79  foreach(proto, protos) {
80    proto_dir = get_path_info(proto, "dir")
81    proto_name = get_path_info(proto, "name")
82    proto_path = proto_dir + "/" + proto_name
83
84    if (generate_cc) {
85      protogens += [
86        "$cc_out_dir/$proto_path.pb.h",
87        "$cc_out_dir/$proto_path.pb.cc",
88      ]
89    }
90    if (generate_with_plugin) {
91      foreach(suffix, generator_plugin_suffixes) {
92        protogens += [ "$cc_out_dir/${proto_path}${suffix}" ]
93      }
94    }
95  }
96
97  config_name = "${target_name}_config"
98  action_name = "${target_name}_gen"
99  source_set_name = target_name
100
101  config(config_name) {
102    include_dirs = [ cc_out_dir ]
103  }
104
105  # The XXX_gen action that generates the .pb.{cc,h} files.
106  action(action_name) {
107    visibility = [ ":$source_set_name" ]
108    script = "//gn/standalone/build_tool_wrapper.py"
109    sources = proto_sources
110    outputs = get_path_info(protogens, "abspath")
111
112    protoc_label = "//buildtools:protoc($host_toolchain)"
113    protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc"
114    args = [
115      # Path should be rebased because |root_build_dir| for current toolchain
116      # may be different from |root_out_dir| of protoc built on host toolchain.
117      "./" + rebase_path(protoc_path, root_build_dir),
118      "--proto_path",
119      rebase_path(proto_in_dir, root_build_dir),
120    ]
121    if (generate_cc) {
122      args += [
123        "--cpp_out",
124        rel_cc_out_dir,
125      ]
126    }
127    if (generate_descriptor != "") {
128      args += [
129        "--include_imports",
130        "--descriptor_set_out",
131        rebase_path("$root_gen_dir/" + generate_descriptor, root_build_dir),
132      ]
133    }
134
135    if (generate_with_plugin) {
136      plugin_path_rebased = rebase_path(plugin_path, root_build_dir)
137      plugin_out_args = ""
138      if (defined(invoker.generator_plugin_options)) {
139        plugin_out_args += invoker.generator_plugin_options
140      }
141      plugin_out_args += ":$rel_cc_out_dir"
142
143      args += [
144        "--plugin=protoc-gen-plugin=$plugin_path_rebased",
145        "--plugin_out=$plugin_out_args",
146      ]
147    }
148
149    args += rebase_path(proto_sources, root_build_dir)
150
151    inputs = [
152      protoc_path,
153    ]
154
155    deps = [
156      protoc_label,
157    ]
158
159    # TODO(hjd): Avoid adding to deps here this.
160    # When we generate BUILD files we need find the transitive proto,
161    # dependencies, so also add link_deps to actual deps so they show up
162    # in gn desc.
163    if (defined(invoker.link_deps)) {
164      deps += invoker.link_deps
165    }
166    if (generate_with_plugin) {
167      inputs += [ plugin_path ]
168      if (defined(plugin_host_label)) {
169        # Action depends on native generator plugin but for host toolchain only.
170        deps += [ plugin_host_label ]
171      }
172    }
173
174    if (defined(invoker.deps)) {
175      deps += invoker.deps
176    }
177  }  # action "${target_name}_gen"
178
179  # The source_set that builds the generated .pb.cc files.
180  source_set(target_name) {
181    forward_variables_from(invoker,
182                           [
183                             "defines",
184                             "include_dirs",
185                             "public_configs",
186                             "testonly",
187                             "visibility",
188                           ])
189
190    sources = get_target_outputs(":$action_name")
191
192    configs -= [ "//gn/standalone:extra_warnings" ]
193    if (defined(invoker.extra_configs)) {
194      configs += invoker.extra_configs
195    }
196
197    if (!defined(invoker.public_configs)) {
198      public_configs = []
199    }
200
201    public_configs += [
202      "//buildtools:protobuf_gen_config",
203      ":$config_name",
204    ]
205
206    # Use protobuf_full only for tests.
207    if (defined(invoker.use_protobuf_full) &&
208        invoker.use_protobuf_full == true) {
209      deps = [
210        "//buildtools:protobuf_full",
211      ]
212    } else {
213      deps = [
214        "//buildtools:protobuf_lite",
215      ]
216    }
217
218    deps += [ ":$action_name" ]
219    if (defined(invoker.deps)) {
220      deps += invoker.deps
221    }
222  }  # source_set(target_name)
223}  # template
224