File: proto_info.bzl

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (186 lines) | stat: -rw-r--r-- 8,763 bytes parent folder | download | duplicates (6)
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
176
177
178
179
180
181
182
183
184
185
186
# Protocol Buffers - Google's data interchange format
# Copyright 2024 Google Inc.  All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
#
"""
Definition of ProtoInfo provider.
"""

_warning = """ Don't use this field. It's intended for internal use and will be changed or removed
    without warning."""

def _uniq(iterable):
    unique_elements = {element: None for element in iterable}
    return list(unique_elements.keys())

def _join(*path):
    return "/".join([p for p in path if p != ""])

def _empty_to_dot(path):
    return path if path else "."

def _from_root(root, repo, relpath):
    """Constructs an exec path from root to relpath"""
    if not root:
        # `relpath` is a directory with an input source file, the exec path is one of:
        # - when in main repo: `package/path`
        # - when in a external repository: `external/repo/package/path`
        #   - with sibling layout: `../repo/package/path`
        return _join(repo, relpath)
    else:
        # `relpath` is a directory with a generated file or an output directory:
        # - when in main repo: `{root}/package/path`
        # - when in an external repository: `{root}/external/repo/package/path`
        #   - with sibling layout: `{root}/package/path`
        return _join(root, "" if repo.startswith("../") else repo, relpath)

def _create_proto_info(*, srcs, deps, descriptor_set, proto_path = "", workspace_root = "", bin_dir = None, allow_exports = None):
    """Constructs ProtoInfo.

    Args:
      srcs: ([File]) List of .proto files (possibly under _virtual path)
      deps: ([ProtoInfo]) List of dependencies
      descriptor_set: (File) Descriptor set for this Proto
      proto_path: (str) Path that should be stripped from files in srcs. When
        stripping is needed, the files should be symlinked into `_virtual_imports/target_name`
        directory. Only such paths are accepted.
      workspace_root: (str) Set to ctx.workspace_root if this is not the main repository.
      bin_dir: (str) Set to ctx.bin_dir if _virtual_imports are used.
      allow_exports: (Target) The packages where this proto_library can be exported.

    Returns:
      (ProtoInfo)
    """

    # Validate parameters
    src_prefix = _join(workspace_root.replace("external/", "../"), proto_path)
    for src in srcs:
        if type(src) != "File":
            fail("srcs parameter expects a list of Files")
        if src.owner.workspace_root != workspace_root:
            fail("srcs parameter expects all files to have the same workspace_root: ", workspace_root)
        if not src.short_path.startswith(src_prefix):
            fail("srcs parameter expects all files start with %s" % src_prefix)
    if type(descriptor_set) != "File":
        fail("descriptor_set parameter expected to be a File")
    if proto_path:
        if "_virtual_imports/" not in proto_path:
            fail("proto_path needs to contain '_virtual_imports' directory")
        if proto_path.split("/")[-2] != "_virtual_imports":
            fail("proto_path needs to be formed like '_virtual_imports/target_name'")
        if not bin_dir:
            fail("bin_dir parameter should be set when _virtual_imports are used")

    direct_proto_sources = srcs
    transitive_proto_sources = depset(
        direct = direct_proto_sources,
        transitive = [dep._transitive_proto_sources for dep in deps],
        order = "preorder",
    )
    transitive_sources = depset(
        direct = srcs,
        transitive = [dep.transitive_sources for dep in deps],
        order = "preorder",
    )

    # There can be up more than 1 direct proto_paths, for example when there's
    # a generated and non-generated .proto file in srcs
    root_paths = _uniq([src.root.path for src in srcs])
    transitive_proto_path = depset(
        direct = [_empty_to_dot(_from_root(root, workspace_root, proto_path)) for root in root_paths],
        transitive = [dep.transitive_proto_path for dep in deps],
    )

    if srcs:
        check_deps_sources = depset(direct = srcs)
    else:
        check_deps_sources = depset(transitive = [dep.check_deps_sources for dep in deps])

    transitive_descriptor_sets = depset(
        direct = [descriptor_set],
        transitive = [dep.transitive_descriptor_sets for dep in deps],
    )

    # Layering checks.
    if srcs:
        exported_sources = depset(direct = direct_proto_sources)
    else:
        exported_sources = depset(transitive = [dep._exported_sources for dep in deps])

    if "_virtual_imports/" in proto_path:
        #TODO: remove bin_dir from proto_source_root (when users assuming it's there are migrated)
        proto_source_root = _empty_to_dot(_from_root(bin_dir, workspace_root, proto_path))
    elif workspace_root.startswith("../"):
        proto_source_root = proto_path
    else:
        proto_source_root = _empty_to_dot(_join(workspace_root, proto_path))

    proto_info = dict(
        direct_sources = srcs,
        transitive_sources = transitive_sources,
        direct_descriptor_set = descriptor_set,
        transitive_descriptor_sets = transitive_descriptor_sets,
        proto_source_root = proto_source_root,
        transitive_proto_path = transitive_proto_path,
        check_deps_sources = check_deps_sources,
        transitive_imports = transitive_sources,
        _direct_proto_sources = direct_proto_sources,
        _transitive_proto_sources = transitive_proto_sources,
        _exported_sources = exported_sources,
    )
    if allow_exports:
        proto_info["allow_exports"] = allow_exports
    return proto_info

ProtoInfo, _ = provider(
    doc = "Encapsulates information provided by a `proto_library.`",
    fields = {
        "direct_sources": "(list[File]) The `.proto` source files from the `srcs` attribute.",
        "transitive_sources": """(depset[File]) The `.proto` source files from this rule and all
                    its dependent protocol buffer rules.""",
        "direct_descriptor_set": """(File) The descriptor set of the direct sources. If no srcs,
            contains an empty file.""",
        "transitive_descriptor_sets": """(depset[File]) A set of descriptor set files of all
            dependent `proto_library` rules, and this one's. This is not the same as passing
            --include_imports to proto-compiler. Will be empty if no dependencies.""",
        "proto_source_root": """(str) The directory relative to which the `.proto` files defined in
            the `proto_library` are defined. For example, if this is `a/b` and the rule has the
            file `a/b/c/d.proto` as a source, that source file would be imported as
            `import c/d.proto`

            In principle, the `proto_source_root` directory itself should always
            be relative to the output directory (`ctx.bin_dir`).

            This is at the moment not true for `proto_libraries` using (additional and/or strip)
            import prefixes. `proto_source_root` is in this case prefixed with the output
            directory. For example, the value is similar to
            `bazel-out/k8-fastbuild/bin/a/_virtual_includes/b` for an input file in
            `a/_virtual_includes/b/c.proto` that should be imported as `c.proto`.

            When using the value please account for both cases in a general way.
            That is assume the value is either prefixed with the output directory or not.
            This will make it possible to fix `proto_library` in the future.
            """,
        "transitive_proto_path": """(depset(str) A set of `proto_source_root`s collected from the
            transitive closure of this rule.""",
        "check_deps_sources": """(depset[File]) The `.proto` sources from the 'srcs' attribute.
            If the library is a proxy library that has no sources, it contains the
            `check_deps_sources` from this library's direct deps.""",
        "allow_exports": """(Target) The packages where this proto_library can be exported.""",

        # Deprecated fields:
        "transitive_imports": """(depset[File]) Deprecated: use `transitive_sources` instead.""",

        # Internal fields:
        "_direct_proto_sources": """(list[File]) The `ProtoSourceInfo`s from the `srcs`
            attribute.""" + _warning,
        "_transitive_proto_sources": """(depset[File]) The `ProtoSourceInfo`s from this
            rule and all its dependent protocol buffer rules.""" + _warning,
        "_exported_sources": """(depset[File]) A set of `ProtoSourceInfo`s that may be
            imported by another `proto_library` depending on this one.""" + _warning,
    },
    init = _create_proto_info,
)