| # Copyright (C) 2017 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import("../perfetto.gni") |
| |
| if (host_os == "win") { |
| _host_executable_suffix = ".exe" |
| } else { |
| _host_executable_suffix = "" |
| } |
| |
| template("proto_library") { |
| assert(defined(invoker.sources)) |
| proto_sources = invoker.sources |
| |
| # All the proto imports should be relative to the project root. |
| proto_in_dir = "//" |
| if (defined(invoker.proto_in_dir)) { |
| proto_in_dir = invoker.proto_in_dir |
| } |
| assert(defined(invoker.proto_out_dir), |
| "proto_out_dir must be explicitly defined") |
| proto_out_dir = invoker.proto_out_dir |
| |
| # We don't support generate_python in the standalone build, but still must |
| # check that the caller sets this to false. This is because when building in |
| # the chromium tree, chromium's proto_library.gni in chrome (!= this) defaults |
| # generate_python = true. |
| assert(defined(invoker.generate_python) && !invoker.generate_python) |
| |
| import_dirs = [] |
| if (defined(invoker.import_dirs)) { |
| import_dirs = invoker.import_dirs |
| } |
| |
| # If false will not generate the default .pb.{cc,h} files. Used for custom |
| # codegen plugins. |
| generate_cc = true |
| if (defined(invoker.generate_cc)) { |
| generate_cc = invoker.generate_cc |
| } |
| |
| generate_descriptor = "" |
| if (defined(invoker.generate_descriptor)) { |
| generate_descriptor = invoker.generate_descriptor |
| |
| # Include imports to descriptor by default, but use exclude_imports to omit |
| # them if needed. |
| if (defined(invoker.exclude_imports)) { |
| exclude_imports = invoker.exclude_imports |
| } else { |
| exclude_imports = false |
| } |
| } |
| |
| if (defined(invoker.generator_plugin_label)) { |
| 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 |
| } |
| } |
| |
| out_dir = "$root_gen_dir/" + proto_out_dir |
| rel_out_dir = rebase_path(out_dir, root_build_dir) |
| |
| # Prevent unused errors when generating descriptor only. |
| if (generate_descriptor != "") { |
| not_needed([ "rel_out_dir" ]) |
| } |
| |
| protos = rebase_path(proto_sources, proto_in_dir) |
| protogens = [] |
| |
| if (generate_descriptor != "") { |
| protogens += [ "$out_dir/${generate_descriptor}" ] |
| } |
| |
| foreach(proto, protos) { |
| proto_dir = get_path_info(proto, "dir") |
| proto_name = get_path_info(proto, "name") |
| proto_path = proto_dir + "/" + proto_name |
| |
| # Prevent unused errors when generating descriptor only. |
| if (generate_descriptor != "") { |
| not_needed([ "proto_path" ]) |
| } |
| |
| if (generate_cc) { |
| protogens += [ |
| "$out_dir/$proto_path.pb.h", |
| "$out_dir/$proto_path.pb.cc", |
| ] |
| } |
| if (generate_with_plugin) { |
| foreach(suffix, generator_plugin_suffixes) { |
| protogens += [ "$out_dir/${proto_path}${suffix}" ] |
| } |
| } |
| } |
| |
| config_name = "${target_name}_config" |
| if (generate_descriptor == "") { |
| action_name = "${target_name}_gen" |
| source_set_name = target_name |
| } else { |
| action_name = target_name |
| } |
| |
| config(config_name) { |
| include_dirs = [ out_dir ] |
| } |
| |
| # The XXX_gen action that generates the .pb.{cc,h} files. |
| action(action_name) { |
| if (generate_descriptor == "") { |
| visibility = [ ":$source_set_name" ] |
| } |
| sources = proto_sources |
| outputs = get_path_info(protogens, "abspath") |
| |
| if (perfetto_use_system_protobuf) { |
| protoc_rebased_path = "protoc" + _host_executable_suffix # from PATH |
| } else { |
| protoc_label = "//gn:protoc($host_toolchain)" |
| protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" + |
| _host_executable_suffix |
| protoc_rebased_path = "./" + rebase_path(protoc_path, root_build_dir) |
| } |
| script = "//gn/standalone/protoc.py" |
| args = [ |
| # 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_rebased_path, |
| "--proto_path", |
| rebase_path(proto_in_dir, root_build_dir), |
| ] |
| |
| foreach(path, import_dirs) { |
| args += [ |
| "--proto_path", |
| rebase_path(path, root_build_dir), |
| ] |
| } |
| |
| if (generate_cc) { |
| cc_generator_options_ = "" |
| if (defined(invoker.cc_generator_options)) { |
| cc_generator_options_ = invoker.cc_generator_options |
| } |
| args += [ |
| "--cpp_out", |
| cc_generator_options_ + rel_out_dir, |
| ] |
| } |
| if (generate_descriptor != "") { |
| depfile = "$root_gen_dir/$generate_descriptor.d" |
| |
| if (!exclude_imports) { |
| args += [ "--include_imports" ] |
| } |
| args += [ |
| "--descriptor_set_out", |
| rebase_path("$root_gen_dir/$generate_descriptor", root_build_dir), |
| "--dependency_out", |
| rebase_path(depfile, root_build_dir), |
| ] |
| } |
| |
| if (generate_with_plugin) { |
| plugin_path_rebased = rebase_path(plugin_path, root_build_dir) |
| plugin_out_args = "" |
| if (defined(invoker.generator_plugin_options)) { |
| plugin_out_args += invoker.generator_plugin_options |
| } |
| plugin_out_args += ":$rel_out_dir" |
| |
| args += [ |
| "--plugin=protoc-gen-plugin=$plugin_path_rebased", |
| "--plugin_out=$plugin_out_args", |
| ] |
| } |
| |
| args += rebase_path(proto_sources, root_build_dir) |
| |
| if (!perfetto_use_system_protobuf) { |
| inputs = [ protoc_path ] |
| deps = [ protoc_label ] |
| } else { |
| inputs = [] |
| deps = [] |
| } |
| |
| # TODO(hjd): Avoid adding to deps here this. |
| # When we generate BUILD files we need find the transitive proto, |
| # dependencies, so also add link_deps to actual deps so they show up |
| # in gn desc. |
| if (defined(invoker.link_deps)) { |
| deps += invoker.link_deps |
| } |
| if (generate_with_plugin) { |
| inputs += [ plugin_path ] |
| if (defined(plugin_host_label)) { |
| # Action depends on native generator plugin but for host toolchain only. |
| deps += [ plugin_host_label ] |
| } |
| } |
| |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| } # action(action_name) |
| |
| # The source_set that builds the generated .pb.cc files. |
| if (generate_descriptor == "") { |
| source_set(source_set_name) { |
| forward_variables_from(invoker, |
| [ |
| "defines", |
| "include_dirs", |
| "public_configs", |
| "testonly", |
| "visibility", |
| ]) |
| |
| sources = get_target_outputs(":$action_name") |
| |
| configs -= [ "//gn/standalone:extra_warnings" ] |
| if (defined(invoker.extra_configs)) { |
| configs += invoker.extra_configs |
| } |
| |
| if (!defined(invoker.public_configs)) { |
| public_configs = [] |
| } |
| |
| public_configs += [ ":$config_name" ] |
| |
| # Only include the protobuf_gen_config when generating .pb.cc files. |
| # Note that |generate_cc| is false for .{pbzero,ipc,gen etc.}.cc |
| if (generate_cc) { |
| public_configs += [ "//gn:protobuf_gen_config" ] |
| } |
| |
| # 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 { |
| configs += [ ":$config_name" ] |
| } |
| |
| # Use protobuf_full only for tests. |
| if (defined(invoker.use_protobuf_full) && |
| invoker.use_protobuf_full == true) { |
| deps = [ "//gn:protobuf_full" ] |
| } else if (generate_cc) { |
| deps = [ "//gn:protobuf_lite" ] |
| } else { |
| deps = [] |
| } |
| |
| deps += [ ":$action_name" ] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| } # source_set(source_set_name) |
| } |
| } # template |