Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be | 
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. | 
| 4 | 4 | 
| 5 # Compile a protocol buffer. | 5 # Compile a protocol buffer. | 
| 6 # | 6 # | 
| 7 # Protobuf parameters: | 7 # Protobuf parameters: | 
| 8 # | 8 # | 
| 9 # proto_in_dir (optional) | |
| 10 # Specifies the path relative to the current BUILD.gn file where | |
| 11 # proto files are located and the directory structure of | |
| 12 # this proto library starts. | |
| 13 # | |
| 14 # This option can be calculated automatically but it will raise an | |
| 15 # assertion error if any nested directories are found. | |
| 16 # | |
| 9 # proto_out_dir (optional) | 17 # proto_out_dir (optional) | 
| 10 # Specifies the path suffix that output files are generated under. This | 18 # Specifies the path suffix that output files are generated under. | 
| 11 # path will be appended to the root_gen_dir. | 19 # This path will be appended to |root_gen_dir|, but for python stubs | 
| 12 # | 20 # it will be appended to |root_build_dir|/pyproto. | 
| 13 # Targets that depend on the proto target will be able to include the | |
| 14 # resulting proto headers with an include like: | |
| 15 # #include "dir/for/my_proto_lib/foo.pb.h" | |
| 16 # If undefined, this defaults to matching the input directory for each | |
| 17 # .proto file (you should almost always use the default mode). | |
| 18 # | 21 # | 
| 19 # generate_python (optional, default true) | 22 # generate_python (optional, default true) | 
| 20 # Generate Python protobuf stubs. | 23 # Generate Python protobuf stubs. | 
| 21 # | 24 # | 
| 22 # generate_cc (optional, default true) | 25 # generate_cc (optional, default true) | 
| 23 # Generate C++ protobuf stubs. | 26 # Generate C++ protobuf stubs. | 
| 24 # | 27 # | 
| 25 # cc_generator_options (optional) | 28 # cc_generator_options (optional) | 
| 26 # List of extra flags passed to the protocol compiler. If you need to | 29 # List of extra flags passed to the protocol compiler. If you need to | 
| 27 # add an EXPORT macro to a protobuf's C++ header, set the | 30 # add an EXPORT macro to a protobuf's C++ header, set the | 
| 28 # 'cc_generator_options' variable with the value: | 31 # 'cc_generator_options' variable with the value: | 
| 29 # 'dllexport_decl=FOO_EXPORT:' (note trailing colon). | 32 # 'dllexport_decl=FOO_EXPORT:' (note trailing colon). | 
| 30 # | 33 # | 
| 31 # It is likely you also need to #include a file for the above EXPORT | 34 # It is likely you also need to #include a file for the above EXPORT | 
| 32 # macro to work (see cc_include) and set | 35 # macro to work (see cc_include) and set | 
| 33 # component_build_force_source_set = true. | 36 # component_build_force_source_set = true. | 
| 34 # | 37 # | 
| 38 # cc_include (optional) | |
| 39 # String listing an extra include that should be passed. | |
| 40 # Example: cc_include = "foo/bar.h" | |
| 41 # | |
| 35 # generator_plugin_label (optional) | 42 # generator_plugin_label (optional) | 
| 36 # GN label for plugin executable which generates custom cc stubs. | 43 # GN label for plugin executable which generates custom cc stubs. | 
| 44 # Don't specify a toolchain, host toolchain is assumed. | |
| 37 # | 45 # | 
| 38 # generator_plugin_suffix (required if generator_plugin_label set) | 46 # generator_plugin_suffix (required if |generator_plugin_label| set) | 
| 39 # Suffix (before extension) for generated .cc and .h files. | 47 # Suffix (before extension) for generated .cc and .h files. | 
| 40 # | 48 # | 
| 41 # generator_plugin_options (optional) | 49 # generator_plugin_options (optional) | 
| 42 # Extra flags passed to the plugin. See cc_generator_options. | 50 # Extra flags passed to the plugin. See cc_generator_options. | 
| 43 # | 51 # | 
| 44 # cc_include (optional) | |
| 45 # String listing an extra include that should be passed. | |
| 46 # Example: cc_include = "foo/bar.h" | |
| 47 # | |
| 48 # deps (optional) | 52 # deps (optional) | 
| 49 # Additional dependencies. | 53 # Additional dependencies. | 
| 50 # | 54 # | 
| 51 # Parameters for compiling the generated code: | 55 # Parameters for compiling the generated code: | 
| 52 # | 56 # | 
| 53 # component_build_force_source_set (Default=false) | 57 # component_build_force_source_set (Default=false) | 
| 54 # When set true the generated code will be compiled as a source set in | 58 # When set true the generated code will be compiled as a source set in | 
| 55 # the component build. This does not affect static builds. If you are | 59 # the component build. This does not affect static builds. If you are | 
| 56 # exporting symbols from a component, this is required to prevent those | 60 # exporting symbols from a component, this is required to prevent those | 
| 57 # symbols from being stripped. If you're not using dllexports in | 61 # symbols from being stripped. If you're not using dllexports in | 
| 58 # cc_generator_options, it's usually best to leave this false. | 62 # cc_generator_options, it's usually best to leave this false. | 
| 59 # | 63 # | 
| 60 # defines (optional) | 64 # defines (optional) | 
| 61 # Defines to supply to the source set that compiles the generated source | 65 # Defines to supply to the source set that compiles the generated source | 
| 62 # code. | 66 # code. | 
| 63 # | 67 # | 
| 64 # extra_configs (optional) | 68 # extra_configs (optional) | 
| 65 # A list of config labels that will be appended to the configs applying | 69 # A list of config labels that will be appended to the configs applying | 
| 66 # to the source set. | 70 # to the source set. | 
| 67 # | 71 # | 
| 68 # Example | 72 # Example: | 
| 69 # proto_library("mylib") { | 73 # proto_library("mylib") { | 
| 70 # sources = [ | 74 # sources = [ | 
| 71 # "foo.proto", | 75 # "foo.proto", | 
| 72 # ] | 76 # ] | 
| 73 # } | 77 # } | 
| 74 | 78 | 
| 75 template("proto_library") { | 79 template("proto_library") { | 
| 76 assert(defined(invoker.sources), "Need sources for proto_library") | 80 assert(defined(invoker.sources), "Need sources for proto_library") | 
| 81 proto_sources = invoker.sources | |
| 77 | 82 | 
| 78 # Don't apply OS-specific sources filtering to the assignments later on. | 83 # Don't apply OS-specific sources filtering to the assignments later on. | 
| 79 # Platform files should have gotten filtered out in the sources assignment | 84 # Platform files should have gotten filtered out in the sources assignment | 
| 80 # when this template was invoked. If they weren't, it was on purpose and | 85 # when this template was invoked. If they weren't, it was on purpose and | 
| 81 # this template shouldn't re-apply the filter. | 86 # this template shouldn't re-apply the filter. | 
| 82 set_sources_assignment_filter([]) | 87 set_sources_assignment_filter([]) | 
| 83 | 88 | 
| 89 if (defined(invoker.generate_cc)) { | |
| 90 generate_cc = invoker.generate_cc | |
| 91 } else { | |
| 92 generate_cc = true | |
| 93 } | |
| 94 | |
| 95 if (defined(invoker.generate_python)) { | |
| 96 generate_python = invoker.generate_python | |
| 97 } else { | |
| 98 generate_python = true | |
| 99 } | |
| 100 | |
| 101 if (defined(invoker.generator_plugin_label)) { | |
| 102 generator_plugin_label = invoker.generator_plugin_label | |
| 103 generator_plugin_suffix = invoker.generator_plugin_suffix | |
| 104 generate_with_plugin = true | |
| 105 | |
| 106 # Straightforward way to get the name of executable doesn't work because | |
| 107 # |root_out_dir| and |root_build_dir| may differ in cross-compilation and | |
| 108 # also Windows executables have .exe at the end. | |
| 109 | |
| 110 plugin_host_label = generator_plugin_label + "($host_toolchain)" | |
| 111 plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" + | |
| 112 get_label_info(plugin_host_label, "name") | |
| 113 if (host_os == "win") { | |
| 114 plugin_path += ".exe" | |
| 115 } | |
| 116 plugin_path = rebase_path(plugin_path, root_build_dir) | |
| 117 } else { | |
| 118 generate_with_plugin = false | |
| 119 } | |
| 120 | |
| 121 if (defined(invoker.proto_in_dir)) { | |
| 122 proto_in_dir = invoker.proto_in_dir | |
| 123 } else { | |
| 124 proto_in_dir = get_path_info(proto_sources[0], "dir") | |
| 125 | |
| 126 # Sanity check, |proto_in_dir| should be defined to allow sub-directories. | |
| 127 foreach(proto_source, proto_sources) { | |
| 128 assert(get_path_info(proto_source, "dir") == proto_in_dir, | |
| 129 "Please define |proto_in_dir| to allow nested directories.") | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 # Avoid absolute path because of the assumption that |proto_in_dir| is | |
| 134 # relative to the directory of current BUILD.gn file. | |
| 135 proto_in_dir = rebase_path(proto_in_dir, ".") | |
| 136 | |
| 137 if (defined(invoker.proto_out_dir)) { | |
| 138 proto_out_dir = invoker.proto_out_dir | |
| 139 } else { | |
| 140 # Absolute path to the directory of current BUILD.gn file excluding "//". | |
| 141 proto_out_dir = rebase_path(".", "//") | |
| 142 if (proto_in_dir != ".") { | |
| 143 proto_out_dir += "/$proto_in_dir" | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 # We need both absolute path to use in GN statements and a relative one | |
| 148 # to pass to external script. | |
| 149 if (generate_cc || generate_with_plugin) { | |
| 150 cc_out_dir = "$root_gen_dir/" + proto_out_dir | |
| 151 rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir) | |
| 152 } | |
| 153 if (generate_python) { | |
| 154 py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir | |
| 155 rel_py_out_dir = rebase_path(py_out_dir, root_build_dir) | |
| 156 } | |
| 157 | |
| 158 protos = rebase_path(invoker.sources, proto_in_dir) | |
| 159 protogens = [] | |
| 160 | |
| 161 # List output files. | |
| 162 foreach(proto, protos) { | |
| 163 proto_dir = get_path_info(proto, "dir") | |
| 164 proto_name = get_path_info(proto, "name") | |
| 165 proto_path = proto_dir + "/" + proto_name | |
| 166 | |
| 167 if (generate_cc) { | |
| 168 protogens += [ | |
| 169 "$cc_out_dir/$proto_path.pb.h", | |
| 170 "$cc_out_dir/$proto_path.pb.cc", | |
| 171 ] | |
| 172 } | |
| 173 if (generate_python) { | |
| 174 protogens += [ "$py_out_dir/${proto_path}_pb2.py" ] | |
| 175 } | |
| 176 if (generate_with_plugin) { | |
| 177 protogens += [ | |
| 178 "$cc_out_dir/${proto_path}$generator_plugin_suffix.h", | |
| 179 "$cc_out_dir/${proto_path}$generator_plugin_suffix.cc", | |
| 180 ] | |
| 181 } | |
| 182 } | |
| 183 | |
| 84 action_name = "${target_name}_gen" | 184 action_name = "${target_name}_gen" | 
| 85 source_set_name = target_name | 185 source_set_name = target_name | 
| 86 action_foreach(action_name) { | 186 | 
| 187 # Generate protobuf stubs. | |
| 188 action(action_name) { | |
| 87 visibility = [ ":$source_set_name" ] | 189 visibility = [ ":$source_set_name" ] | 
| 190 script = "//tools/protoc_wrapper/protoc_wrapper.py" | |
| 191 sources = proto_sources | |
| 192 outputs = get_path_info(protogens, "abspath") | |
| 193 args = protos | |
| 88 | 194 | 
| 89 script = "//tools/protoc_wrapper/protoc_wrapper.py" | 195 protoc_label = "//third_party/protobuf:protoc($host_toolchain)" | 
| 196 protoc_out_dir = get_label_info(protoc_label, "root_out_dir") | |
| 197 args += [ | |
| 198 # Wrapper should never pick a system protoc. | |
| 199 # Path should be rebased because |root_build_dir| for current toolchain | |
| 200 # may be different from |root_out_dir| of protoc built on host toolchain. | |
| 201 "--protoc", | |
| 202 "./" + rebase_path(protoc_out_dir, root_build_dir) + "/protoc", | |
| 203 "--proto-in-dir", | |
| 204 rebase_path(proto_in_dir, root_build_dir), | |
| 205 ] | |
| 90 | 206 | 
| 91 sources = invoker.sources | 207 if (generate_cc) { | 
| 92 | |
| 93 # Compute the output directory, both relative to the source root (for | |
| 94 # declaring "outputs") and relative to the build dir (for passing to the | |
| 95 # script). | |
| 96 if (defined(invoker.proto_out_dir)) { | |
| 97 proto_out_dir = invoker.proto_out_dir | |
| 98 } else { | |
| 99 proto_out_dir = "{{source_root_relative_dir}}" | |
| 100 } | |
| 101 out_dir = "$root_gen_dir/" + proto_out_dir | |
| 102 rel_out_dir = rebase_path(out_dir, root_build_dir) | |
| 103 | |
| 104 outputs = [] | |
| 105 | |
| 106 args = [] | |
| 107 if (defined(invoker.cc_include)) { | |
| 108 args += [ | 208 args += [ | 
| 109 "--include", | 209 "--cc-out-dir", | 
| 110 invoker.cc_include, | 210 rel_cc_out_dir, | 
| 111 "--protobuf", | |
| 112 "$rel_out_dir/{{source_name_part}}.pb.h", | |
| 113 ] | 211 ] | 
| 212 if (defined(invoker.cc_generator_options)) { | |
| 213 args += [ | |
| 214 "--cc-options", | |
| 215 invoker.cc_generator_options, | |
| 216 ] | |
| 217 } | |
| 218 if (defined(invoker.cc_include)) { | |
| 219 args += [ | |
| 220 "--include", | |
| 221 invoker.cc_include, | |
| 222 ] | |
| 223 } | |
| 114 } | 224 } | 
| 115 | 225 | 
| 116 args += [ | 226 if (generate_python) { | 
| 117 "--proto-in-dir", | |
| 118 "{{source_dir}}", | |
| 119 "--proto-in-file", | |
| 120 "{{source_file_part}}", | |
| 121 | |
| 122 # TODO(brettw) support system protobuf compiler. | |
| 123 "--use-system-protobuf=0", | |
| 124 ] | |
| 125 | |
| 126 protoc_label = "//third_party/protobuf:protoc($host_toolchain)" | |
| 127 args += [ | |
| 128 "--", | |
| 129 | |
| 130 # Prepend with "./" so this will never pick up the system one (normally | |
| 131 # when not cross-compiling, protoc's output directory will be the same | |
| 132 # as the build dir, so the relative location will be empty). | |
| 133 "./" + | |
| 134 rebase_path(get_label_info(protoc_label, "root_out_dir") + "/protoc", | |
| 135 root_build_dir), | |
| 136 ] | |
| 137 | |
| 138 if (!defined(invoker.generate_python) || invoker.generate_python) { | |
| 139 py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir | |
| 140 rel_py_out_dir = rebase_path(py_out_dir, root_build_dir) | |
| 141 | |
| 142 outputs += [ "$py_out_dir/{{source_name_part}}_pb2.py" ] | |
| 143 args += [ | 227 args += [ | 
| 144 "--python_out", | 228 "--py-out-dir", | 
| 145 rel_py_out_dir, | 229 rel_py_out_dir, | 
| 146 ] | 230 ] | 
| 147 } | 231 } | 
| 148 | 232 | 
| 149 if (!defined(invoker.generate_cc) || invoker.generate_cc) { | 233 if (generate_with_plugin) { | 
| 150 # If passed cc_generator_options should end in a colon, which will | |
| 151 # separate it from the directory when we concatenate them. The proto | |
| 152 # compiler understands this syntax. | |
| 153 if (defined(invoker.cc_generator_options)) { | |
| 154 cc_generator_options = invoker.cc_generator_options | |
| 155 } else { | |
| 156 cc_generator_options = "" | |
| 157 } | |
| 158 outputs += [ | |
| 159 "$out_dir/{{source_name_part}}.pb.cc", | |
| 160 "$out_dir/{{source_name_part}}.pb.h", | |
| 161 ] | |
| 162 args += [ | |
| 163 "--cpp_out", | |
| 164 "$cc_generator_options$rel_out_dir", # Separated by colon. | |
| 165 ] | |
| 166 } | |
| 167 | |
| 168 if (defined(invoker.generator_plugin_label)) { | |
| 169 generator_plugin_label = invoker.generator_plugin_label | |
| 170 generator_plugin_suffix = invoker.generator_plugin_suffix | |
| 171 if (defined(invoker.generator_plugin_options)) { | |
| 172 generator_plugin_options = invoker.generator_plugin_options | |
| 173 } else { | |
| 174 generator_plugin_options = "" | |
| 175 } | |
| 176 outputs += [ | |
| 177 "$out_dir/{{source_name_part}}$generator_plugin_suffix.cc", | |
| 178 "$out_dir/{{source_name_part}}$generator_plugin_suffix.h", | |
| 179 ] | |
| 180 | |
| 181 # Straightforward way to get the name of executable doesn't work because | |
| 182 # root_out_dir and root_build_dir may differ in cross-compilation and | |
| 183 # also Windows executables have .exe at the end. | |
| 184 | |
| 185 plugin_host_label = generator_plugin_label + "($host_toolchain)" | |
| 186 plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" + | |
| 187 get_label_info(plugin_host_label, "name") | |
| 188 if (host_os == "win") { | |
| 189 plugin_path += ".exe" | |
| 190 } | |
| 191 | |
| 192 # Need "./" for script to find plugin binary (working dir is not on PATH). | |
| 193 args += [ | 234 args += [ | 
| 194 "--plugin", | 235 "--plugin", | 
| 195 "protoc-gen-plugin=./" + rebase_path(plugin_path, root_build_dir), | 236 plugin_path, | 
| 196 "--plugin_out", | 237 "--plugin-out-dir", | 
| 197 "$generator_plugin_options$rel_out_dir", # Separated by colon. | 238 rel_cc_out_dir, | 
| 198 ] | 239 ] | 
| 240 if (defined(invoker.generator_plugin_options)) { | |
| 241 args += [ | |
| 242 "--plugin-options", | |
| 243 invoker.generator_plugin_options, | |
| 244 ] | |
| 245 } | |
| 199 } | 246 } | 
| 200 | 247 | 
| 201 deps = [ | 248 deps = [ | 
| 249 # System protoc is not used so it's necessary to build a chromium one. | |
| 202 protoc_label, | 250 protoc_label, | 
| 203 ] | 251 ] | 
| 204 if (defined(plugin_host_label)) { | 252 if (defined(plugin_host_label)) { | 
| 253 # Action depends on generator plugin but for host toolchain only. | |
| 205 deps += [ plugin_host_label ] | 254 deps += [ plugin_host_label ] | 
| 206 } | 255 } | 
| 207 | |
| 208 # The deps may have steps that have to run before running protobuf. | |
| 209 if (defined(invoker.deps)) { | 256 if (defined(invoker.deps)) { | 
| 257 # The deps may have steps that have to run before running protoc. | |
| 210 deps += invoker.deps | 258 deps += invoker.deps | 
| 211 } | 259 } | 
| 212 } | 260 } | 
| 213 | 261 | 
| 262 # Option to disable building a library in component build. | |
| 214 if (defined(invoker.component_build_force_source_set) && | 263 if (defined(invoker.component_build_force_source_set) && | 
| 215 invoker.component_build_force_source_set && | 264 invoker.component_build_force_source_set && | 
| 216 is_component_build) { | 265 is_component_build) { | 
| 217 link_target_type = "source_set" | 266 link_target_type = "source_set" | 
| 218 } else { | 267 } else { | 
| 219 link_target_type = "static_library" | 268 link_target_type = "static_library" | 
| 220 } | 269 } | 
| 270 | |
| 271 # Build generated protobuf stubs as libary or source set. | |
| 221 target(link_target_type, target_name) { | 272 target(link_target_type, target_name) { | 
| 222 forward_variables_from(invoker, | 273 forward_variables_from(invoker, | 
| 223 [ | 274 [ | 
| 224 "visibility", | 275 "visibility", | 
| 225 "defines", | 276 "defines", | 
| 226 ]) | 277 ]) | 
| 227 | 278 | 
| 228 sources = get_target_outputs(":$action_name") | 279 sources = get_target_outputs(":$action_name") | 
| 229 | 280 | 
| 230 if (defined(invoker.extra_configs)) { | 281 if (defined(invoker.extra_configs)) { | 
| 231 configs += invoker.extra_configs | 282 configs += invoker.extra_configs | 
| 232 } | 283 } | 
| 233 | 284 | 
| 234 public_configs = [ "//third_party/protobuf:using_proto" ] | 285 public_configs = [ "//third_party/protobuf:using_proto" ] | 
| 235 | 286 | 
| 236 # If using built-in cc generator the resulting headers reference headers | 287 include_dirs = [] | 
| 237 # within protobuf_lite, hence dependencies require those headers too. | 288 if (generate_cc) { | 
| 238 # In case of generator plugin such issues should be resolved by invoker. | 289 include_dirs += [ cc_out_dir ] | 
| 
 
brettw
2016/08/16 22:08:10
Does this include directory need to be applied to
 
kraynov
2016/08/17 00:40:34
Thank you! This case now fortified by unit test.
 
 | |
| 239 if (!defined(invoker.generate_cc) || invoker.generate_cc) { | 290 | 
| 291 # If using built-in cc generator, the resulting headers reference headers | |
| 292 # within protobuf_lite. Hence, dependencies require those headers too. | |
| 293 # If using generator plugin, extra deps should be resolved by the invoker. | |
| 240 public_deps = [ | 294 public_deps = [ | 
| 241 "//third_party/protobuf:protobuf_lite", | 295 "//third_party/protobuf:protobuf_lite", | 
| 242 ] | 296 ] | 
| 243 } | 297 } | 
| 298 if (generate_with_plugin) { | |
| 299 include_dirs += [ cc_out_dir ] | |
| 300 } | |
| 301 | |
| 244 deps = [ | 302 deps = [ | 
| 245 ":$action_name", | 303 ":$action_name", | 
| 246 ] | 304 ] | 
| 247 | 305 | 
| 248 # This will link any libraries in the deps (the use of invoker.deps in the | 306 # This will link any libraries in the deps (the use of invoker.deps in the | 
| 249 # action won't link it). | 307 # action won't link it). | 
| 250 if (defined(invoker.deps)) { | 308 if (defined(invoker.deps)) { | 
| 251 deps += invoker.deps | 309 deps += invoker.deps | 
| 252 } | 310 } | 
| 253 } | 311 } | 
| 254 } | 312 } | 
| OLD | NEW |