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