1*9bb1b549SSpandan Das# Copyright 2021 The Bazel Go Rules Authors. All rights reserved. 2*9bb1b549SSpandan Das# 3*9bb1b549SSpandan Das# Licensed under the Apache License, Version 2.0 (the "License"); 4*9bb1b549SSpandan Das# you may not use this file except in compliance with the License. 5*9bb1b549SSpandan Das# You may obtain a copy of the License at 6*9bb1b549SSpandan Das# 7*9bb1b549SSpandan Das# http://www.apache.org/licenses/LICENSE-2.0 8*9bb1b549SSpandan Das# 9*9bb1b549SSpandan Das# Unless required by applicable law or agreed to in writing, software 10*9bb1b549SSpandan Das# distributed under the License is distributed on an "AS IS" BASIS, 11*9bb1b549SSpandan Das# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9bb1b549SSpandan Das# See the License for the specific language governing permissions and 13*9bb1b549SSpandan Das# limitations under the License. 14*9bb1b549SSpandan Das 15*9bb1b549SSpandan Dasload( 16*9bb1b549SSpandan Das "//go/private:providers.bzl", 17*9bb1b549SSpandan Das "GoArchive", 18*9bb1b549SSpandan Das "GoStdLib", 19*9bb1b549SSpandan Das) 20*9bb1b549SSpandan Dasload( 21*9bb1b549SSpandan Das "@bazel_skylib//lib:paths.bzl", 22*9bb1b549SSpandan Das "paths", 23*9bb1b549SSpandan Das) 24*9bb1b549SSpandan Das 25*9bb1b549SSpandan DasGoPkgInfo = provider() 26*9bb1b549SSpandan Das 27*9bb1b549SSpandan DasDEPS_ATTRS = [ 28*9bb1b549SSpandan Das "deps", 29*9bb1b549SSpandan Das "embed", 30*9bb1b549SSpandan Das] 31*9bb1b549SSpandan Das 32*9bb1b549SSpandan DasPROTO_COMPILER_ATTRS = [ 33*9bb1b549SSpandan Das "compiler", 34*9bb1b549SSpandan Das "compilers", 35*9bb1b549SSpandan Das "library", 36*9bb1b549SSpandan Das] 37*9bb1b549SSpandan Das 38*9bb1b549SSpandan Dasdef bazel_supports_canonical_label_literals(): 39*9bb1b549SSpandan Das return str(Label("//:bogus")).startswith("@@") 40*9bb1b549SSpandan Das 41*9bb1b549SSpandan Dasdef is_file_external(f): 42*9bb1b549SSpandan Das return f.owner.workspace_root != "" 43*9bb1b549SSpandan Das 44*9bb1b549SSpandan Dasdef file_path(f): 45*9bb1b549SSpandan Das prefix = "__BAZEL_WORKSPACE__" 46*9bb1b549SSpandan Das if not f.is_source: 47*9bb1b549SSpandan Das prefix = "__BAZEL_EXECROOT__" 48*9bb1b549SSpandan Das elif is_file_external(f): 49*9bb1b549SSpandan Das prefix = "__BAZEL_OUTPUT_BASE__" 50*9bb1b549SSpandan Das return paths.join(prefix, f.path) 51*9bb1b549SSpandan Das 52*9bb1b549SSpandan Dasdef _go_archive_to_pkg(archive): 53*9bb1b549SSpandan Das return struct( 54*9bb1b549SSpandan Das ID = str(archive.data.label), 55*9bb1b549SSpandan Das PkgPath = archive.data.importpath, 56*9bb1b549SSpandan Das ExportFile = file_path(archive.data.export_file), 57*9bb1b549SSpandan Das GoFiles = [ 58*9bb1b549SSpandan Das file_path(src) 59*9bb1b549SSpandan Das for src in archive.data.orig_srcs 60*9bb1b549SSpandan Das if src.path.endswith(".go") 61*9bb1b549SSpandan Das ], 62*9bb1b549SSpandan Das CompiledGoFiles = [ 63*9bb1b549SSpandan Das file_path(src) 64*9bb1b549SSpandan Das for src in archive.data.srcs 65*9bb1b549SSpandan Das if src.path.endswith(".go") 66*9bb1b549SSpandan Das ], 67*9bb1b549SSpandan Das OtherFiles = [ 68*9bb1b549SSpandan Das file_path(src) 69*9bb1b549SSpandan Das for src in archive.data.orig_srcs 70*9bb1b549SSpandan Das if not src.path.endswith(".go") 71*9bb1b549SSpandan Das ], 72*9bb1b549SSpandan Das Imports = { 73*9bb1b549SSpandan Das pkg.data.importpath: str(pkg.data.label) 74*9bb1b549SSpandan Das for pkg in archive.direct 75*9bb1b549SSpandan Das }, 76*9bb1b549SSpandan Das ) 77*9bb1b549SSpandan Das 78*9bb1b549SSpandan Dasdef make_pkg_json(ctx, name, pkg_info): 79*9bb1b549SSpandan Das pkg_json_file = ctx.actions.declare_file(name + ".pkg.json") 80*9bb1b549SSpandan Das ctx.actions.write(pkg_json_file, content = pkg_info.to_json()) 81*9bb1b549SSpandan Das return pkg_json_file 82*9bb1b549SSpandan Das 83*9bb1b549SSpandan Dasdef _go_pkg_info_aspect_impl(target, ctx): 84*9bb1b549SSpandan Das # Fetch the stdlib JSON file from the inner most target 85*9bb1b549SSpandan Das stdlib_json_file = None 86*9bb1b549SSpandan Das 87*9bb1b549SSpandan Das transitive_json_files = [] 88*9bb1b549SSpandan Das transitive_export_files = [] 89*9bb1b549SSpandan Das transitive_compiled_go_files = [] 90*9bb1b549SSpandan Das 91*9bb1b549SSpandan Das for attr in DEPS_ATTRS + PROTO_COMPILER_ATTRS: 92*9bb1b549SSpandan Das deps = getattr(ctx.rule.attr, attr, []) or [] 93*9bb1b549SSpandan Das 94*9bb1b549SSpandan Das # Some attrs are not iterable, ensure that deps is always iterable. 95*9bb1b549SSpandan Das if type(deps) != type([]): 96*9bb1b549SSpandan Das deps = [deps] 97*9bb1b549SSpandan Das 98*9bb1b549SSpandan Das for dep in deps: 99*9bb1b549SSpandan Das if GoPkgInfo in dep: 100*9bb1b549SSpandan Das pkg_info = dep[GoPkgInfo] 101*9bb1b549SSpandan Das transitive_json_files.append(pkg_info.pkg_json_files) 102*9bb1b549SSpandan Das transitive_compiled_go_files.append(pkg_info.compiled_go_files) 103*9bb1b549SSpandan Das transitive_export_files.append(pkg_info.export_files) 104*9bb1b549SSpandan Das 105*9bb1b549SSpandan Das # Fetch the stdlib json from the first dependency 106*9bb1b549SSpandan Das if not stdlib_json_file: 107*9bb1b549SSpandan Das stdlib_json_file = pkg_info.stdlib_json_file 108*9bb1b549SSpandan Das 109*9bb1b549SSpandan Das pkg_json_files = [] 110*9bb1b549SSpandan Das compiled_go_files = [] 111*9bb1b549SSpandan Das export_files = [] 112*9bb1b549SSpandan Das 113*9bb1b549SSpandan Das if GoArchive in target: 114*9bb1b549SSpandan Das archive = target[GoArchive] 115*9bb1b549SSpandan Das compiled_go_files.extend(archive.source.srcs) 116*9bb1b549SSpandan Das export_files.append(archive.data.export_file) 117*9bb1b549SSpandan Das pkg = _go_archive_to_pkg(archive) 118*9bb1b549SSpandan Das pkg_json_files.append(make_pkg_json(ctx, archive.data.name, pkg)) 119*9bb1b549SSpandan Das 120*9bb1b549SSpandan Das if ctx.rule.kind == "go_test": 121*9bb1b549SSpandan Das for dep_archive in archive.direct: 122*9bb1b549SSpandan Das # find the archive containing the test sources 123*9bb1b549SSpandan Das if archive.data.label == dep_archive.data.label: 124*9bb1b549SSpandan Das pkg = _go_archive_to_pkg(dep_archive) 125*9bb1b549SSpandan Das pkg_json_files.append(make_pkg_json(ctx, dep_archive.data.name, pkg)) 126*9bb1b549SSpandan Das compiled_go_files.extend(dep_archive.source.srcs) 127*9bb1b549SSpandan Das export_files.append(dep_archive.data.export_file) 128*9bb1b549SSpandan Das break 129*9bb1b549SSpandan Das 130*9bb1b549SSpandan Das # If there was no stdlib json in any dependencies, fetch it from the 131*9bb1b549SSpandan Das # current go_ node. 132*9bb1b549SSpandan Das if not stdlib_json_file: 133*9bb1b549SSpandan Das stdlib_json_file = ctx.attr._go_stdlib[GoStdLib]._list_json 134*9bb1b549SSpandan Das 135*9bb1b549SSpandan Das pkg_info = GoPkgInfo( 136*9bb1b549SSpandan Das stdlib_json_file = stdlib_json_file, 137*9bb1b549SSpandan Das pkg_json_files = depset( 138*9bb1b549SSpandan Das direct = pkg_json_files, 139*9bb1b549SSpandan Das transitive = transitive_json_files, 140*9bb1b549SSpandan Das ), 141*9bb1b549SSpandan Das compiled_go_files = depset( 142*9bb1b549SSpandan Das direct = compiled_go_files, 143*9bb1b549SSpandan Das transitive = transitive_compiled_go_files, 144*9bb1b549SSpandan Das ), 145*9bb1b549SSpandan Das export_files = depset( 146*9bb1b549SSpandan Das direct = export_files, 147*9bb1b549SSpandan Das transitive = transitive_export_files, 148*9bb1b549SSpandan Das ), 149*9bb1b549SSpandan Das ) 150*9bb1b549SSpandan Das 151*9bb1b549SSpandan Das return [ 152*9bb1b549SSpandan Das pkg_info, 153*9bb1b549SSpandan Das OutputGroupInfo( 154*9bb1b549SSpandan Das go_pkg_driver_json_file = pkg_info.pkg_json_files, 155*9bb1b549SSpandan Das go_pkg_driver_srcs = pkg_info.compiled_go_files, 156*9bb1b549SSpandan Das go_pkg_driver_export_file = pkg_info.export_files, 157*9bb1b549SSpandan Das go_pkg_driver_stdlib_json_file = depset([pkg_info.stdlib_json_file] if pkg_info.stdlib_json_file else []), 158*9bb1b549SSpandan Das ), 159*9bb1b549SSpandan Das ] 160*9bb1b549SSpandan Das 161*9bb1b549SSpandan Dasgo_pkg_info_aspect = aspect( 162*9bb1b549SSpandan Das implementation = _go_pkg_info_aspect_impl, 163*9bb1b549SSpandan Das attr_aspects = DEPS_ATTRS + PROTO_COMPILER_ATTRS, 164*9bb1b549SSpandan Das attrs = { 165*9bb1b549SSpandan Das "_go_stdlib": attr.label( 166*9bb1b549SSpandan Das default = "//:stdlib", 167*9bb1b549SSpandan Das ), 168*9bb1b549SSpandan Das }, 169*9bb1b549SSpandan Das) 170