...

Text file src/github.com/bazelbuild/rules_go/go/tools/gopackagesdriver/aspect.bzl

Documentation: github.com/bazelbuild/rules_go/go/tools/gopackagesdriver

     1# Copyright 2021 The Bazel Go Rules Authors. All rights reserved.
     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
    15load(
    16    "//go/private:providers.bzl",
    17    "GoArchive",
    18    "GoStdLib",
    19)
    20load(
    21    "@bazel_skylib//lib:paths.bzl",
    22    "paths",
    23)
    24
    25GoPkgInfo = provider()
    26
    27DEPS_ATTRS = [
    28    "deps",
    29    "embed",
    30]
    31
    32PROTO_COMPILER_ATTRS = [
    33    "compiler",
    34    "compilers",
    35    "library",
    36]
    37
    38def bazel_supports_canonical_label_literals():
    39    return str(Label("//:bogus")).startswith("@@")
    40
    41def is_file_external(f):
    42    return f.owner.workspace_root != ""
    43
    44def file_path(f):
    45    prefix = "__BAZEL_WORKSPACE__"
    46    if not f.is_source:
    47        prefix = "__BAZEL_EXECROOT__"
    48    elif is_file_external(f):
    49        prefix = "__BAZEL_OUTPUT_BASE__"
    50    return paths.join(prefix, f.path)
    51
    52def _go_archive_to_pkg(archive):
    53    return struct(
    54        ID = str(archive.data.label),
    55        PkgPath = archive.data.importpath,
    56        ExportFile = file_path(archive.data.export_file),
    57        GoFiles = [
    58            file_path(src)
    59            for src in archive.data.orig_srcs
    60            if src.path.endswith(".go")
    61        ],
    62        CompiledGoFiles = [
    63            file_path(src)
    64            for src in archive.data.srcs
    65            if src.path.endswith(".go")
    66        ],
    67        OtherFiles = [
    68            file_path(src)
    69            for src in archive.data.orig_srcs
    70            if not src.path.endswith(".go")
    71        ],
    72        Imports = {
    73            pkg.data.importpath: str(pkg.data.label)
    74            for pkg in archive.direct
    75        },
    76    )
    77
    78def make_pkg_json(ctx, name, pkg_info):
    79    pkg_json_file = ctx.actions.declare_file(name + ".pkg.json")
    80    ctx.actions.write(pkg_json_file, content = pkg_info.to_json())
    81    return pkg_json_file
    82
    83def _go_pkg_info_aspect_impl(target, ctx):
    84    # Fetch the stdlib JSON file from the inner most target
    85    stdlib_json_file = None
    86
    87    transitive_json_files = []
    88    transitive_export_files = []
    89    transitive_compiled_go_files = []
    90
    91    for attr in DEPS_ATTRS + PROTO_COMPILER_ATTRS:
    92        deps = getattr(ctx.rule.attr, attr, []) or []
    93
    94        # Some attrs are not iterable, ensure that deps is always iterable.
    95        if type(deps) != type([]):
    96            deps = [deps]
    97
    98        for dep in deps:
    99            if GoPkgInfo in dep:
   100                pkg_info = dep[GoPkgInfo]
   101                transitive_json_files.append(pkg_info.pkg_json_files)
   102                transitive_compiled_go_files.append(pkg_info.compiled_go_files)
   103                transitive_export_files.append(pkg_info.export_files)
   104
   105                # Fetch the stdlib json from the first dependency
   106                if not stdlib_json_file:
   107                    stdlib_json_file = pkg_info.stdlib_json_file
   108
   109    pkg_json_files = []
   110    compiled_go_files = []
   111    export_files = []
   112
   113    if GoArchive in target:
   114        archive = target[GoArchive]
   115        compiled_go_files.extend(archive.source.srcs)
   116        export_files.append(archive.data.export_file)
   117        pkg = _go_archive_to_pkg(archive)
   118        pkg_json_files.append(make_pkg_json(ctx, archive.data.name, pkg))
   119
   120        if ctx.rule.kind == "go_test":
   121            for dep_archive in archive.direct:
   122                # find the archive containing the test sources
   123                if archive.data.label == dep_archive.data.label:
   124                    pkg = _go_archive_to_pkg(dep_archive)
   125                    pkg_json_files.append(make_pkg_json(ctx, dep_archive.data.name, pkg))
   126                    compiled_go_files.extend(dep_archive.source.srcs)
   127                    export_files.append(dep_archive.data.export_file)
   128                    break
   129
   130    # If there was no stdlib json in any dependencies, fetch it from the
   131    # current go_ node.
   132    if not stdlib_json_file:
   133        stdlib_json_file = ctx.attr._go_stdlib[GoStdLib]._list_json
   134
   135    pkg_info = GoPkgInfo(
   136        stdlib_json_file = stdlib_json_file,
   137        pkg_json_files = depset(
   138            direct = pkg_json_files,
   139            transitive = transitive_json_files,
   140        ),
   141        compiled_go_files = depset(
   142            direct = compiled_go_files,
   143            transitive = transitive_compiled_go_files,
   144        ),
   145        export_files = depset(
   146            direct = export_files,
   147            transitive = transitive_export_files,
   148        ),
   149    )
   150
   151    return [
   152        pkg_info,
   153        OutputGroupInfo(
   154            go_pkg_driver_json_file = pkg_info.pkg_json_files,
   155            go_pkg_driver_srcs = pkg_info.compiled_go_files,
   156            go_pkg_driver_export_file = pkg_info.export_files,
   157            go_pkg_driver_stdlib_json_file = depset([pkg_info.stdlib_json_file] if pkg_info.stdlib_json_file else []),
   158        ),
   159    ]
   160
   161go_pkg_info_aspect = aspect(
   162    implementation = _go_pkg_info_aspect_impl,
   163    attr_aspects = DEPS_ATTRS + PROTO_COMPILER_ATTRS,
   164    attrs = {
   165        "_go_stdlib": attr.label(
   166            default = "//:stdlib",
   167        ),
   168    },
   169)

View as plain text