summaryrefslogtreecommitdiffstats
path: root/third_party/protobuf/proto_library.gni
blob: 8e7ea1411ba84b97506580fe35da11240f7b413b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# 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_out_dir (optional)
#       Specifies the path suffix that output files are generated under. This
#       path will be appended to the root_gen_dir.
#
#       Targets that depend on the proto target will be able to include the
#       resulting proto headers with an include like:
#         #include "dir/for/my_proto_lib/foo.pb.h"
#       If undefined, this defaults to matching the input directory for each
#       .proto file (you should almost always use the default mode).
#
#   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.
#
#   cc_include (optional)
#       String listing an extra include that should be passed.
#       Example: cc_include = "foo/bar.h"
#
#   deps (optional)
#       Additional dependencies.
#
# Parameters for compiling the generated code:
#
#   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.
#
# Example:
#  proto_library("mylib") {
#    sources = [
#      "foo.proto",
#    ]
#  }

template("proto_library") {
  assert(defined(invoker.sources), "Need sources for proto_library")

  # Don't apply OS-specific sources filtering to the assignments later on.
  # Platform files should have gotten filtered out in the sources assignment
  # when this template was invoked. If they weren't, it was on purpose and
  # this template shouldn't re-apply the filter.
  set_sources_assignment_filter([])

  action_name = "${target_name}_gen"
  source_set_name = target_name
  action_foreach(action_name) {
    visibility = [ ":$source_set_name" ]

    script = "//tools/protoc_wrapper/protoc_wrapper.py"

    sources = invoker.sources

    # Compute the output directory, both relative to the source root (for
    # declaring "outputs") and relative to the build dir (for passing to the
    # script).
    if (defined(invoker.proto_out_dir)) {
      # Put the results in the specified dir in the gen tree.
      out_dir = "$root_gen_dir/" + invoker.proto_out_dir
      rel_out_dir = rebase_path(out_dir, root_build_dir)
      py_out_dir = "$root_out_dir/pyproto/" + invoker.proto_out_dir
    } else {
      # Use the gen directory corresponding to the source file for C++ sources.
      # This expansion will be done differently in the outputs and the args, so
      # we don't need to worry about rebasing as above. Always put Python
      # sources in "pyproto".
      out_dir = "{{source_gen_dir}}"
      rel_out_dir = "{{source_gen_dir}}"
      py_out_dir = "$root_out_dir/pyproto/{{source_root_relative_dir}}"
    }
    rel_py_out_dir = rebase_path(py_out_dir, root_build_dir)

    outputs = [
      "$py_out_dir/{{source_name_part}}_pb2.py",
      "$out_dir/{{source_name_part}}.pb.cc",
      "$out_dir/{{source_name_part}}.pb.h",
    ]

    args = []
    if (defined(invoker.cc_include)) {
      args += [
        "--include",
        invoker.cc_include,
      ]
    }

    args += [
      "--protobuf",
      "$rel_out_dir/{{source_name_part}}.pb.h",
      "--proto-in-dir",
      "{{source_dir}}",
      "--proto-in-file",
      "{{source_file_part}}",

      # TODO(brettw) support system protobuf compiler.
      "--use-system-protobuf=0",
    ]

    protoc_label = "//third_party/protobuf:protoc($host_toolchain)"
    args += [
      "--",

      # Prepend with "./" so this will never pick up the system one (normally
      # when not cross-compiling, protoc's output directory will be the same
      # as the build dir, so the relative location will be empty).
      "./" +
          rebase_path(get_label_info(protoc_label, "root_out_dir") + "/protoc",
                      root_build_dir),
    ]

    # If passed cc_generator_options should end in a colon, which will separate
    # it from the directory when we concatenate them. The proto compiler
    # understands this syntax.
    if (defined(invoker.cc_generator_options)) {
      cc_generator_options = invoker.cc_generator_options
    } else {
      cc_generator_options = ""
    }
    args += [
      # cc_generator_options is supposed to end in a colon if it's nonempty.
      "--cpp_out",
      "$cc_generator_options$rel_out_dir",
      "--python_out",
      rel_py_out_dir,
    ]

    deps = [
      protoc_label,
    ]
    if (defined(invoker.deps)) {
      deps += invoker.deps
    }
  }

  source_set(target_name) {
    forward_variables_from(invoker,
                           [
                             "visibility",
                             "defines",
                           ])

    sources = get_target_outputs(":$action_name")

    if (defined(invoker.extra_configs)) {
      configs += invoker.extra_configs
    }

    public_configs = [ "//third_party/protobuf:using_proto" ]

    public_deps = [
      # The generated headers reference headers within protobuf_lite, so
      # dependencies must be able to find those headers too.
      "//third_party/protobuf:protobuf_lite",
    ]
    deps = [
      ":$action_name",
    ]
  }
}