123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- # Copyright 2014 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- # Compile a protocol buffer.
- #
- # Protobuf parameters:
- #
- # proto_in_dir (optional)
- # Specifies the path relative to the current BUILD.gn file where
- # proto files are located and the directory structure of
- # this proto library starts.
- #
- # This option can be calculated automatically but it will raise an
- # assertion error if any nested directories are found.
- #
- # proto_out_dir (optional)
- # Specifies the path suffix that output files are generated under.
- # This path will be appended to |root_gen_dir|, but for python stubs
- # it will be appended to |root_build_dir|/pyproto.
- #
- # generate_python (optional, default true)
- # Generate Python protobuf stubs.
- #
- # generate_cc (optional, default true)
- # Generate C++ protobuf stubs.
- #
- # generate_javascript (optional, default false)
- # Generate Javascript protobuf stubs.
- #
- # generate_library (optional, default true)
- # Generate a "static_library" target for linking with the generated code.
- #
- # generate_py_runtime (optional, default false)
- # Generates a "_py_runtime"-suffixed target for test targets that need the
- # Python stubs available at runtime.
- #
- # TODO(crbug.com/1237958): Remove allow_optional when proto rolls to 3.15.
- # allow_optional (optional, default false)
- # Enables experimental_allow_proto3_optional.
- #
- # cc_generator_options (optional)
- # List of extra flags passed to the protocol compiler. If you need to
- # add an EXPORT macro to a protobuf's C++ header, set the
- # 'cc_generator_options' variable with the value:
- # 'dllexport_decl=FOO_EXPORT:' (note trailing colon).
- #
- # It is likely you also need to #include a file for the above EXPORT
- # macro to work (see cc_include) and set
- # component_build_force_source_set = true.
- #
- # cc_include (optional)
- # String listing an extra include that should be passed.
- # Example: cc_include = "foo/bar.h"
- #
- # generator_plugin_label (optional)
- # GN label for plugin executable which generates custom cc stubs.
- # Don't specify a toolchain, host toolchain is assumed.
- #
- # generator_plugin_script (optional)
- # Path to plugin script. Mutually exclusive with |generator_plugin_label|.
- #
- # generator_plugin_script_deps (optional)
- # List of additional files required for generator plugin script.
- #
- # generator_plugin_suffix[es] (required if using a plugin)
- # Suffix (before extension) for generated .cc and .h files
- # or list of suffixes for all files (with extensions).
- #
- # generator_plugin_options (optional)
- # Extra flags passed to the plugin. See cc_generator_options.
- #
- # deps (optional)
- # DEPRECATED: use proto_deps or link_deps instead (crbug.com/938011).
- # Additional dependencies.
- #
- # link_deps (optional)
- # Additional dependencies linked to library.
- #
- # proto_deps (optional)
- # Additional dependencies required before running protoc.
- # e.g. proto file generating action.
- #
- # use_protobuf_full (optional)
- # If adding protobuf library would be required, adds protobuf_full to deps
- # instead of protobuf_lite.
- #
- # import_dirs (optional)
- # A list of extra import directories to be passed to protoc compiler.
- # WARNING: This circumvents proto checkdeps, and should only be used when
- # needed, typically when proto files cannot cleanly import through
- # absolute paths, such as for third_party or generated .proto files.
- # http://crbug.com/691451 tracks fixing this.
- #
- # Parameters for compiling the generated code:
- #
- # force_source_set (Default=false)
- # When set true the generated code will be compiled as a source set.
- # This can be useful if you need to export the generated symbols from a
- # shared library. You should use this carefully, as you probably only
- # want this if your dependencies are *always* shared libraries. Most
- # of the time, you probably want `component_build_force_source_set`
- # instead (see the next option).
- # component_build_force_source_set (Default=false)
- # When set true the generated code will be compiled as a source set in
- # the component build. This does not affect static builds. If you are
- # exporting symbols from a component, this is required to prevent those
- # symbols from being stripped. If you're not using dllexports in
- # cc_generator_options, it's usually best to leave this false.
- #
- # defines (optional)
- # Defines to supply to the source set that compiles the generated source
- # code.
- #
- # extra_configs (optional)
- # A list of config labels that will be appended to the configs applying
- # to the source set.
- #
- # remove_configs (optional)
- # A list of config labels that will be removed from the configs apllying
- # to the source set.
- #
- # propagate_imports_configs (optional)
- # A boolean value (defaults to true) that specifies whether the config
- # generated for the library's import directories will be propagated to
- # dependents as one of the library target's public_configs. See
- # crbug.com/1043279#c11 and crbug.com/gn/142 for why this option exists.
- # WARNING: If set to false, the embedder target is responsible for
- # propagating a suitable config, so that any dependent headers can resolve
- # includes generated by proto imports.
- #
- # Example:
- # proto_library("mylib") {
- # sources = [
- # "foo.proto",
- # ]
- # }
- import("//build/config/sanitizers/sanitizers.gni")
- import("//build/toolchain/kythe.gni")
- declare_args() {
- # Allows subprojects to omit javascript dependencies (e.g.) closure_compiler
- # and google-closure-library.
- enable_js_protobuf = true
- }
- if (enable_js_protobuf) {
- import("//third_party/closure_compiler/compile_js.gni")
- }
- if (host_os == "win") {
- _host_executable_suffix = ".exe"
- } else {
- _host_executable_suffix = ""
- }
- _protoc_label = "//third_party/protobuf:protoc($host_toolchain)"
- _protoc_path = get_label_info(_protoc_label, "root_out_dir") + "/protoc" +
- _host_executable_suffix
- template("proto_library") {
- assert(defined(invoker.sources), "Need sources for proto_library")
- proto_sources = invoker.sources
- if (defined(invoker.generate_cc)) {
- generate_cc = invoker.generate_cc
- } else {
- generate_cc = true
- }
- if (defined(invoker.generate_python)) {
- generate_python = invoker.generate_python
- } else {
- generate_python = true
- }
- if (defined(invoker.generate_javascript)) {
- generate_javascript = invoker.generate_javascript
- } else {
- generate_javascript = false
- }
- if (defined(invoker.generate_descriptor)) {
- generate_descriptor = invoker.generate_descriptor
- } else {
- generate_descriptor = ""
- }
- if (defined(invoker.generate_py_runtime)) {
- generate_py_runtime = invoker.generate_py_runtime
- } else {
- generate_py_runtime = false
- }
- if (generate_py_runtime) {
- generate_python = true
- }
- # exclude_imports is only used for generating the descriptor. Therefore, the
- # check needs to be here to avoid complaints from GN about the unused
- # variable.
- if (generate_descriptor != "") {
- if (defined(invoker.exclude_imports)) {
- exclude_imports = invoker.exclude_imports
- } else {
- exclude_imports = false
- }
- }
- if (defined(invoker.generator_plugin_label)) {
- # Straightforward way to get the name of executable doesn't work because
- # |root_out_dir| and |root_build_dir| may differ in cross-compilation and
- # also Windows executables have .exe at the end.
- plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
- plugin_path =
- get_label_info(plugin_host_label, "root_out_dir") + "/" +
- get_label_info(plugin_host_label, "name") + _host_executable_suffix
- generate_with_plugin = true
- } else if (defined(invoker.generator_plugin_script)) {
- plugin_path = invoker.generator_plugin_script
- generate_with_plugin = true
- } else {
- generate_with_plugin = false
- }
- if (generate_with_plugin) {
- if (defined(invoker.generator_plugin_suffix)) {
- generator_plugin_suffixes = [
- "${invoker.generator_plugin_suffix}.h",
- "${invoker.generator_plugin_suffix}.cc",
- ]
- } else {
- generator_plugin_suffixes = invoker.generator_plugin_suffixes
- }
- }
- if (defined(invoker.proto_in_dir)) {
- proto_in_dir = invoker.proto_in_dir
- has_nested_dirs = false
- foreach(proto_source, proto_sources) {
- if (get_path_info(proto_source, "dir") != proto_in_dir) {
- has_nested_dirs = true
- }
- }
- } else {
- proto_in_dir = get_path_info(proto_sources[0], "dir")
- has_nested_dirs = false
- # Sanity check, |proto_in_dir| should be defined to allow sub-directories.
- foreach(proto_source, proto_sources) {
- assert(get_path_info(proto_source, "dir") == proto_in_dir,
- "Please define |proto_in_dir| to allow nested directories.")
- }
- }
- # Avoid absolute path because of the assumption that |proto_in_dir| is
- # relative to the directory of current BUILD.gn file.
- proto_in_dir = rebase_path(proto_in_dir, ".")
- if (defined(invoker.proto_out_dir)) {
- proto_out_dir = invoker.proto_out_dir
- } else {
- # Absolute path to the directory of current BUILD.gn file excluding "//".
- proto_out_dir = rebase_path(".", "//")
- if (proto_in_dir != ".") {
- proto_out_dir += "/$proto_in_dir"
- }
- }
- # We need both absolute path to use in GN statements and a relative one
- # to pass to external script.
- if (generate_cc || generate_with_plugin) {
- cc_out_dir = "$root_gen_dir/" + proto_out_dir
- rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir)
- }
- if (generate_python) {
- py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir
- rel_py_out_dir = rebase_path(py_out_dir, root_build_dir)
- }
- if (generate_javascript) {
- js_out_dir = "$root_out_dir/jsproto/" + proto_out_dir
- rel_js_out_dir = rebase_path(js_out_dir, root_build_dir)
- }
- if (generate_descriptor != "") {
- descriptor_out =
- "$root_gen_dir/" + proto_out_dir + "/" + generate_descriptor
- rel_descriptor_out = rebase_path(descriptor_out, root_build_dir)
- }
- protos = rebase_path(invoker.sources, proto_in_dir)
- protogens = []
- protogens_py = []
- protogens_cc = []
- protogens_js = []
- # Whether source code bindings should be generated.
- generate_sources = generate_cc || generate_python || generate_with_plugin ||
- generate_javascript
- # Whether library should be generated.
- # Library is not needed when proto_library is used to generate binary descriptor, in which case
- # corresponding library target should be omitted entirely.
- if (defined(invoker.generate_library)) {
- generate_library = invoker.generate_library
- } else {
- generate_library = generate_sources
- }
- # List output files.
- if (generate_sources) {
- foreach(proto, protos) {
- proto_dir = get_path_info(proto, "dir")
- proto_name = get_path_info(proto, "name")
- proto_path = proto_dir + "/" + proto_name
- if (generate_cc) {
- protogens_cc += [
- "$cc_out_dir/$proto_path.pb.h",
- "$cc_out_dir/$proto_path.pb.cc",
- ]
- }
- if (generate_python) {
- protogens_py += [ "$py_out_dir/${proto_path}_pb2.py" ]
- }
- if (generate_with_plugin) {
- foreach(suffix, generator_plugin_suffixes) {
- protogens_cc += [ "$cc_out_dir/${proto_path}${suffix}" ]
- }
- }
- if (generate_javascript) {
- protogens_js += [ "$js_out_dir/${proto_path}.js" ]
- }
- }
- }
- # If descriptor needs to be generated, it should be added to list of outputs once.
- if (generate_descriptor != "") {
- protogens += [ descriptor_out ]
- }
- action_name = "${target_name}_gen"
- source_set_name = target_name
- javascript_name = "${target_name}_js"
- py_runtime_name = "${target_name}_py_runtime"
- # Generate protobuf stubs.
- action(action_name) {
- visibility = [
- ":$javascript_name",
- ":$py_runtime_name",
- ":$source_set_name",
- ]
- script = "//tools/protoc_wrapper/protoc_wrapper.py"
- args = protos
- sources = proto_sources
- outputs =
- get_path_info(protogens + protogens_cc + protogens_js + protogens_py,
- "abspath")
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
- }
- args += [
- # Wrapper should never pick a system protoc.
- # Path should be rebased because |root_build_dir| for current toolchain
- # may be different from |root_out_dir| of protoc built on host toolchain.
- "--protoc",
- "./" + rebase_path(_protoc_path, root_build_dir),
- "--proto-in-dir",
- rebase_path(proto_in_dir, root_build_dir),
- ]
- if (generate_cc) {
- args += [
- "--cc-out-dir",
- rel_cc_out_dir,
- ]
- if (enable_kythe_annotations) {
- args += [ "--enable-kythe-annotation" ]
- }
- if (defined(invoker.cc_generator_options)) {
- args += [
- "--cc-options",
- invoker.cc_generator_options,
- ]
- }
- if (defined(invoker.allow_optional) && invoker.allow_optional == true) {
- args += [ "--allow-optional" ]
- }
- if (defined(invoker.cc_include)) {
- args += [
- "--include",
- invoker.cc_include,
- ]
- }
- }
- if (generate_python) {
- args += [
- "--py-out-dir",
- rel_py_out_dir,
- ]
- }
- if (generate_javascript) {
- args += [
- "--js-out-dir",
- rel_js_out_dir,
- ]
- }
- if (generate_with_plugin) {
- args += [
- "--plugin",
- rebase_path(plugin_path, root_build_dir),
- "--plugin-out-dir",
- rel_cc_out_dir,
- ]
- if (defined(invoker.generator_plugin_options)) {
- args += [
- "--plugin-options",
- invoker.generator_plugin_options,
- ]
- }
- }
- if (generate_descriptor != "") {
- depfile =
- "$root_gen_dir/" + proto_out_dir + "/" + generate_descriptor + ".d"
- rel_depfile = rebase_path(depfile, root_build_dir)
- if (exclude_imports) {
- args += [ "--exclude-imports" ]
- }
- args += [
- "--descriptor-set-out",
- rel_descriptor_out,
- "--descriptor-set-dependency-file",
- rel_depfile,
- ]
- }
- if (defined(invoker.import_dirs)) {
- foreach(path, invoker.import_dirs) {
- args += [ "--import-dir=" + rebase_path(path, root_build_dir) ]
- }
- }
- # System protoc is not used so it's necessary to build a chromium one.
- inputs = [ _protoc_path ]
- deps = [ _protoc_label ]
- if (generate_with_plugin) {
- inputs += [ plugin_path ]
- if (defined(invoker.generator_plugin_script_deps)) {
- # Additional scripts for plugin.
- inputs += invoker.generator_plugin_script_deps
- }
- if (defined(plugin_host_label)) {
- # Action depends on native generator plugin but for host toolchain only.
- deps += [ plugin_host_label ]
- }
- }
- # The deps may have steps that have to run before running protoc.
- if (defined(invoker.proto_deps)) {
- deps += invoker.proto_deps
- }
- if (defined(invoker.deps)) {
- deps += invoker.deps
- }
- }
- if (!generate_library) {
- # If only descriptor is required, just generate a group wrapper for action output.
- link_target_type = "group"
- } else if ((defined(invoker.force_source_set) && invoker.force_source_set) ||
- (defined(invoker.component_build_force_source_set) &&
- invoker.component_build_force_source_set && is_component_build)) {
- # Option to disable building a library in component build.
- link_target_type = "source_set"
- } else {
- link_target_type = "static_library"
- }
- # Generated files may include other generated headers. These includes always
- # use relative paths starting at |cc_out_dir|.
- # However there is no necessity to add an additional directory, if all protos
- # are located in the same directory which is in the search path by default.
- config_name = "${target_name}_config"
- config(config_name) {
- include_dirs = []
- if (has_nested_dirs && generate_cc) {
- include_dirs += [ cc_out_dir ]
- }
- if (defined(invoker.import_dirs)) {
- foreach(path, invoker.import_dirs) {
- include_dirs += [ "$root_gen_dir/" + rebase_path(path, "//") ]
- }
- }
- }
- # Build generated javascript stubs.
- if (generate_javascript) {
- js_library(javascript_name) {
- forward_variables_from(invoker,
- [
- "testonly",
- "visibility",
- ])
- sources = protogens_js
- deps = [ "//third_party/protobuf:js_proto" ]
- extra_deps = [ ":$action_name" ]
- }
- }
- # Build generated protobuf stubs as libary or source set.
- target(link_target_type, target_name) {
- forward_variables_from(invoker,
- [
- "defines",
- "testonly",
- "visibility",
- ])
- if (generate_library) {
- sources = get_path_info(protogens_cc, "abspath")
- if (defined(invoker.remove_configs)) {
- configs -= invoker.remove_configs
- }
- if (defined(invoker.extra_configs)) {
- configs += invoker.extra_configs
- }
- # Remove Sanitizer and coverage instrumentation for a performance boost when
- # fuzzing, since the only fuzzers that use protobuf are libprotobuf-mutator
- # based fuzzers, and they don't actually target protobuf code.
- configs -= not_fuzzed_remove_configs
- configs += [ "//build/config/sanitizers:not_fuzzed" ]
- }
- public_configs = [
- "//third_party/protobuf:using_proto",
- "//third_party/protobuf:allow_deprecated_proto_fields",
- ]
- public_deps = []
- if (generate_cc || generate_with_plugin) {
- # Not necessary if all protos are located in the same directory.
- if (has_nested_dirs || defined(invoker.import_dirs)) {
- # By default, propagate the config for |include_dirs| to dependent
- # targets, so that public imports can be resolved to corresponding
- # header files. In some cases, the embedder target handles include
- # directory propagation itself, e.g. via a common config.
- propagate_imports_configs =
- !defined(invoker.propagate_imports_configs) ||
- invoker.propagate_imports_configs
- if (propagate_imports_configs) {
- public_configs += [ ":$config_name" ]
- } else {
- # Embedder handles include directory propagation to dependents.
- configs += [ ":$config_name" ]
- }
- }
- # If using built-in cc generator, the resulting headers reference headers
- # within protobuf_lite. Hence, dependencies require those headers too.
- # If using generator plugin, extra deps should be resolved by the invoker.
- if (generate_cc) {
- if (defined(invoker.use_protobuf_full) &&
- invoker.use_protobuf_full == true) {
- public_deps += [ "//third_party/protobuf:protobuf_full" ]
- } else {
- public_deps += [ "//third_party/protobuf:protobuf_lite" ]
- }
- if (is_win) {
- cflags = [
- # disable: C4125 decimal digit terminates octal escape sequence
- # Protoc generates such sequences frequently, there's no obvious
- # superior replacement behavior. Since this code is autogenerated,
- # the warning would never catch a legitimate bug.
- "/wd4125",
- ]
- }
- }
- }
- public_deps += [ ":$action_name" ]
- deps = []
- # This will link any libraries in the deps (the use of invoker.deps in the
- # action won't link it).
- if (defined(invoker.deps)) {
- deps += invoker.deps
- }
- if (defined(invoker.link_deps)) {
- deps += invoker.link_deps
- }
- }
- if (generate_py_runtime) {
- group(py_runtime_name) {
- data = protogens_py
- deps = [
- ":$action_name",
- "//third_party/protobuf:py_proto_runtime",
- ]
- }
- }
- }
- # Convert a protocol buffer between text and binary formats.
- # This can be used to run protoc with the --encode or --decode options.
- # Parameters:
- #
- # sources: list of string
- # The sources to loop over and run protoc on
- #
- # inputs: list of string
- # The file dependencies for the action. This should be the list of .proto
- # files involved in the conversion operation.
- #
- # output_pattern: string
- # A path pattern with source expansion variables (like source_name_part)
- # for where the result of conversion should be placed.
- #
- # deps: (optional) list of label
- # Additional dependencies for the target.
- #
- # args: list of string
- # Arguments to pass to the protoc tool. This could include -I for include
- # paths, as well as the name of the proto file.
- #
- #
- # Example to convert a .textproto to a .binarybp:
- # protoc_convert("convert_foo") {
- # sources = [
- # "test/data/example1.textproto",
- # "test/data/example2.textproto",
- # ]
- # inputs = [
- # "//component/core/foo.proto",
- # ]
- # output_pattern = "$target_gen_dir/foo_data/{{source_name_part}}.binarypb"
- # args = [
- # "--encode=foo.FooMessage",
- # "-I",
- # rebase_path("//"),
- # "component/core/foo.proto",
- # ]
- # }
- template("protoc_convert") {
- action_foreach(target_name) {
- script = "//tools/protoc_wrapper/protoc_convert.py"
- sources = invoker.sources
- inputs = invoker.inputs
- deps = [ _protoc_label ]
- if (defined(invoker.deps)) {
- deps += invoker.deps
- }
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
- }
- outputs = [ invoker.output_pattern ]
- args = [
- "--protoc",
- "./" + rebase_path(_protoc_path, root_build_dir),
- "--infile",
- "{{source}}",
- "--outfile",
- rebase_path(invoker.output_pattern),
- ] + invoker.args
- }
- }
|