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 15 template("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 if (defined(invoker.generator_plugin_label)) { 42 plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)" 43 plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" + 44 get_label_info(plugin_host_label, "name") 45 generate_with_plugin = true 46 } else if (defined(invoker.generator_plugin_script)) { 47 plugin_path = invoker.generator_plugin_script 48 generate_with_plugin = true 49 } else { 50 generate_with_plugin = false 51 } 52 53 if (generate_with_plugin) { 54 if (defined(invoker.generator_plugin_suffix)) { 55 generator_plugin_suffixes = [ 56 "${invoker.generator_plugin_suffix}.h", 57 "${invoker.generator_plugin_suffix}.cc", 58 ] 59 } else { 60 generator_plugin_suffixes = invoker.generator_plugin_suffixes 61 } 62 } 63 64 cc_out_dir = "$root_gen_dir/" + proto_out_dir 65 rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir) 66 67 protos = rebase_path(proto_sources, proto_in_dir) 68 protogens = [] 69 70 foreach(proto, protos) { 71 proto_dir = get_path_info(proto, "dir") 72 proto_name = get_path_info(proto, "name") 73 proto_path = proto_dir + "/" + proto_name 74 75 if (generate_cc) { 76 protogens += [ 77 "$cc_out_dir/$proto_path.pb.h", 78 "$cc_out_dir/$proto_path.pb.cc", 79 ] 80 } 81 if (generate_with_plugin) { 82 foreach(suffix, generator_plugin_suffixes) { 83 protogens += [ "$cc_out_dir/${proto_path}${suffix}" ] 84 } 85 } 86 } 87 88 config_name = "${target_name}_config" 89 action_name = "${target_name}_gen" 90 source_set_name = target_name 91 92 config(config_name) { 93 include_dirs = [ cc_out_dir ] 94 } 95 96 # The XXX_gen action that generates the .pb.{cc,h} files. 97 action(action_name) { 98 visibility = [ ":$source_set_name" ] 99 script = "//gn/standalone/build_tool_wrapper.py" 100 sources = proto_sources 101 outputs = get_path_info(protogens, "abspath") 102 103 protoc_label = "//buildtools:protoc($host_toolchain)" 104 protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" 105 args = [ 106 # Path should be rebased because |root_build_dir| for current toolchain 107 # may be different from |root_out_dir| of protoc built on host toolchain. 108 "./" + rebase_path(protoc_path, root_build_dir), 109 "--proto_path", 110 rebase_path(proto_in_dir, root_build_dir), 111 ] 112 if (generate_cc) { 113 args += [ 114 "--cpp_out", 115 rel_cc_out_dir, 116 ] 117 } 118 119 if (generate_with_plugin) { 120 plugin_path_rebased = rebase_path(plugin_path, root_build_dir) 121 plugin_out_args = "" 122 if (defined(invoker.generator_plugin_options)) { 123 plugin_out_args += invoker.generator_plugin_options 124 } 125 plugin_out_args += ":$rel_cc_out_dir" 126 127 args += [ 128 "--plugin=protoc-gen-plugin=$plugin_path_rebased", 129 "--plugin_out=$plugin_out_args", 130 ] 131 } 132 133 args += rebase_path(proto_sources, root_build_dir) 134 135 inputs = [ 136 protoc_path, 137 ] 138 139 deps = [ 140 protoc_label, 141 ] 142 if (generate_with_plugin) { 143 inputs += [ plugin_path ] 144 if (defined(plugin_host_label)) { 145 # Action depends on native generator plugin but for host toolchain only. 146 deps += [ plugin_host_label ] 147 } 148 } 149 150 if (defined(invoker.deps)) { 151 deps += invoker.deps 152 } 153 } # action "${target_name}_gen" 154 155 # The source_set that builds the generated .pb.cc files. 156 source_set(target_name) { 157 forward_variables_from(invoker, 158 [ 159 "defines", 160 "include_dirs", 161 "public_configs", 162 "testonly", 163 "visibility", 164 ]) 165 166 sources = get_target_outputs(":$action_name") 167 168 configs -= [ "//gn/standalone:extra_warnings" ] 169 if (defined(invoker.extra_configs)) { 170 configs += invoker.extra_configs 171 } 172 173 if (!defined(invoker.public_configs)) { 174 public_configs = [] 175 } 176 177 public_configs += [ 178 "//buildtools:protobuf_gen_config", 179 ":$config_name", 180 ] 181 182 # Use protobuf_full only for tests. 183 if (defined(invoker.use_protobuf_full) && 184 invoker.use_protobuf_full == true) { 185 deps = [ 186 "//buildtools:protobuf_full", 187 ] 188 } else { 189 deps = [ 190 "//buildtools:protobuf_lite", 191 ] 192 } 193 194 deps += [ ":$action_name" ] 195 if (defined(invoker.deps)) { 196 deps += invoker.deps 197 } 198 } # source_set(target_name) 199 } # template 200