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