Home | History | Annotate | Download | only in standalone
      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