1*f585d8a3SJacky Wang# Copyright (C) 2019 The Dagger Authors. 2*f585d8a3SJacky Wang# 3*f585d8a3SJacky Wang# Licensed under the Apache License, Version 2.0 (the "License"); 4*f585d8a3SJacky Wang# you may not use this file except in compliance with the License. 5*f585d8a3SJacky Wang# You may obtain a copy of the License at 6*f585d8a3SJacky Wang# 7*f585d8a3SJacky Wang# http://www.apache.org/licenses/LICENSE-2.0 8*f585d8a3SJacky Wang# 9*f585d8a3SJacky Wang# Unless required by applicable law or agreed to in writing, software 10*f585d8a3SJacky Wang# distributed under the License is distributed on an "AS IS" BASIS, 11*f585d8a3SJacky Wang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*f585d8a3SJacky Wang# See the License for the specific language governing permissions and 13*f585d8a3SJacky Wang# limitations under the License. 14*f585d8a3SJacky Wang"""Skylark rules to collect Maven artifacts information. 15*f585d8a3SJacky Wang""" 16*f585d8a3SJacky Wang 17*f585d8a3SJacky Wangload("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") 18*f585d8a3SJacky Wang 19*f585d8a3SJacky Wang# TODO(b/142057516): Unfork this file once we've settled on a more general API. 20*f585d8a3SJacky WangMavenInfo = provider( 21*f585d8a3SJacky Wang fields = { 22*f585d8a3SJacky Wang "artifact": """ 23*f585d8a3SJacky Wang The Maven coordinate for the artifact that is exported by this target, if one exists. 24*f585d8a3SJacky Wang """, 25*f585d8a3SJacky Wang "has_srcs": """ 26*f585d8a3SJacky Wang True if this library contains srcs.. 27*f585d8a3SJacky Wang """, 28*f585d8a3SJacky Wang "all_transitive_deps": """ 29*f585d8a3SJacky Wang All transitive deps of the target with srcs. 30*f585d8a3SJacky Wang """, 31*f585d8a3SJacky Wang "maven_nearest_artifacts": """ 32*f585d8a3SJacky Wang The nearest maven deps of the target. 33*f585d8a3SJacky Wang """, 34*f585d8a3SJacky Wang "maven_transitive_deps": """ 35*f585d8a3SJacky Wang All transitive deps that are included in some maven dependency. 36*f585d8a3SJacky Wang """, 37*f585d8a3SJacky Wang }, 38*f585d8a3SJacky Wang) 39*f585d8a3SJacky Wang 40*f585d8a3SJacky Wang_EMPTY_MAVEN_INFO = MavenInfo( 41*f585d8a3SJacky Wang artifact = None, 42*f585d8a3SJacky Wang has_srcs = False, 43*f585d8a3SJacky Wang maven_nearest_artifacts = depset(), 44*f585d8a3SJacky Wang maven_transitive_deps = depset(), 45*f585d8a3SJacky Wang all_transitive_deps = depset(), 46*f585d8a3SJacky Wang) 47*f585d8a3SJacky Wang 48*f585d8a3SJacky Wang_MAVEN_COORDINATES_PREFIX = "maven_coordinates=" 49*f585d8a3SJacky Wang 50*f585d8a3SJacky Wangdef _collect_maven_info_impl(target, ctx): 51*f585d8a3SJacky Wang tags = getattr(ctx.rule.attr, "tags", []) 52*f585d8a3SJacky Wang srcs = getattr(ctx.rule.attr, "srcs", []) 53*f585d8a3SJacky Wang deps = getattr(ctx.rule.attr, "deps", []) 54*f585d8a3SJacky Wang exports = getattr(ctx.rule.attr, "exports", []) 55*f585d8a3SJacky Wang 56*f585d8a3SJacky Wang artifact = None 57*f585d8a3SJacky Wang for tag in tags: 58*f585d8a3SJacky Wang if tag in ("maven:compile_only", "maven:shaded"): 59*f585d8a3SJacky Wang return [_EMPTY_MAVEN_INFO] 60*f585d8a3SJacky Wang if tag.startswith(_MAVEN_COORDINATES_PREFIX): 61*f585d8a3SJacky Wang artifact = tag[len(_MAVEN_COORDINATES_PREFIX):] 62*f585d8a3SJacky Wang 63*f585d8a3SJacky Wang all_deps = [dep.label for dep in (deps + exports) if dep[MavenInfo].has_srcs] 64*f585d8a3SJacky Wang all_transitive_deps = [dep[MavenInfo].all_transitive_deps for dep in (deps + exports)] 65*f585d8a3SJacky Wang 66*f585d8a3SJacky Wang maven_artifacts = [] 67*f585d8a3SJacky Wang maven_nearest_artifacts = [] 68*f585d8a3SJacky Wang maven_deps = [] 69*f585d8a3SJacky Wang maven_transitive_deps = [] 70*f585d8a3SJacky Wang for dep in (deps + exports): 71*f585d8a3SJacky Wang # If the dep is itself a maven artifact, add it and all of its transitive deps. 72*f585d8a3SJacky Wang # Otherwise, just propagate its transitive maven deps. 73*f585d8a3SJacky Wang if dep[MavenInfo].artifact or dep[MavenInfo] == _EMPTY_MAVEN_INFO: 74*f585d8a3SJacky Wang if (dep[MavenInfo].artifact): 75*f585d8a3SJacky Wang maven_artifacts.append(dep[MavenInfo].artifact) 76*f585d8a3SJacky Wang maven_deps.append(dep.label) 77*f585d8a3SJacky Wang maven_transitive_deps.append(dep[MavenInfo].all_transitive_deps) 78*f585d8a3SJacky Wang else: 79*f585d8a3SJacky Wang maven_nearest_artifacts.append(dep[MavenInfo].maven_nearest_artifacts) 80*f585d8a3SJacky Wang maven_transitive_deps.append(dep[MavenInfo].maven_transitive_deps) 81*f585d8a3SJacky Wang 82*f585d8a3SJacky Wang return [MavenInfo( 83*f585d8a3SJacky Wang artifact = artifact, 84*f585d8a3SJacky Wang has_srcs = len(srcs) > 0, 85*f585d8a3SJacky Wang maven_nearest_artifacts = depset(maven_artifacts, transitive = maven_nearest_artifacts), 86*f585d8a3SJacky Wang maven_transitive_deps = depset(maven_deps, transitive = maven_transitive_deps), 87*f585d8a3SJacky Wang all_transitive_deps = depset(all_deps, transitive = all_transitive_deps), 88*f585d8a3SJacky Wang )] 89*f585d8a3SJacky Wang 90*f585d8a3SJacky Wangcollect_maven_info = aspect( 91*f585d8a3SJacky Wang attr_aspects = [ 92*f585d8a3SJacky Wang "deps", 93*f585d8a3SJacky Wang "exports", 94*f585d8a3SJacky Wang ], 95*f585d8a3SJacky Wang doc = """ 96*f585d8a3SJacky Wang Collects the Maven information for targets, their dependencies, and their transitive exports. 97*f585d8a3SJacky Wang """, 98*f585d8a3SJacky Wang implementation = _collect_maven_info_impl, 99*f585d8a3SJacky Wang) 100*f585d8a3SJacky Wang 101*f585d8a3SJacky Wangdef _fake_java_library(name, deps = None, exports = None, is_artifact = True): 102*f585d8a3SJacky Wang src_file = ["%s.java" % name] 103*f585d8a3SJacky Wang native.genrule( 104*f585d8a3SJacky Wang name = "%s_source_file" % name, 105*f585d8a3SJacky Wang outs = src_file, 106*f585d8a3SJacky Wang cmd = "echo 'package pkg; class %s {}' > $@" % name, 107*f585d8a3SJacky Wang ) 108*f585d8a3SJacky Wang native.java_library( 109*f585d8a3SJacky Wang name = name, 110*f585d8a3SJacky Wang srcs = src_file, 111*f585d8a3SJacky Wang tags = ["maven_coordinates=%s:_:_" % name] if is_artifact else [], 112*f585d8a3SJacky Wang deps = deps or [], 113*f585d8a3SJacky Wang exports = exports or [], 114*f585d8a3SJacky Wang ) 115*f585d8a3SJacky Wang 116*f585d8a3SJacky Wangdef _maven_info_test_impl(ctx): 117*f585d8a3SJacky Wang env = unittest.begin(ctx) 118*f585d8a3SJacky Wang asserts.equals( 119*f585d8a3SJacky Wang env, 120*f585d8a3SJacky Wang expected = ctx.attr.artifact if ctx.attr.artifact else None, 121*f585d8a3SJacky Wang actual = ctx.attr.target[MavenInfo].artifact, 122*f585d8a3SJacky Wang msg = "MavenInfo.artifact", 123*f585d8a3SJacky Wang ) 124*f585d8a3SJacky Wang asserts.equals( 125*f585d8a3SJacky Wang env, 126*f585d8a3SJacky Wang expected = sorted([ctx.label.relative(dep) for dep in ctx.attr.maven_transitive_deps]), 127*f585d8a3SJacky Wang actual = sorted(ctx.attr.target[MavenInfo].maven_transitive_deps.to_list()), 128*f585d8a3SJacky Wang msg = "MavenInfo.maven_transitive_deps", 129*f585d8a3SJacky Wang ) 130*f585d8a3SJacky Wang asserts.equals( 131*f585d8a3SJacky Wang env, 132*f585d8a3SJacky Wang expected = sorted([ctx.label.relative(dep) for dep in ctx.attr.all_transitive_deps]), 133*f585d8a3SJacky Wang actual = sorted(ctx.attr.target[MavenInfo].all_transitive_deps.to_list()), 134*f585d8a3SJacky Wang msg = "MavenInfo.all_transitive_deps", 135*f585d8a3SJacky Wang ) 136*f585d8a3SJacky Wang return unittest.end(env) 137*f585d8a3SJacky Wang 138*f585d8a3SJacky Wang_maven_info_test = unittest.make( 139*f585d8a3SJacky Wang _maven_info_test_impl, 140*f585d8a3SJacky Wang attrs = { 141*f585d8a3SJacky Wang "target": attr.label(aspects = [collect_maven_info]), 142*f585d8a3SJacky Wang "artifact": attr.string(), 143*f585d8a3SJacky Wang "maven_transitive_deps": attr.string_list(), 144*f585d8a3SJacky Wang "all_transitive_deps": attr.string_list(), 145*f585d8a3SJacky Wang }, 146*f585d8a3SJacky Wang) 147*f585d8a3SJacky Wang 148*f585d8a3SJacky Wangdef maven_info_tests(): 149*f585d8a3SJacky Wang """Tests for `pom_file` and `MavenInfo`. 150*f585d8a3SJacky Wang """ 151*f585d8a3SJacky Wang _fake_java_library(name = "A") 152*f585d8a3SJacky Wang _fake_java_library( 153*f585d8a3SJacky Wang name = "DepOnA", 154*f585d8a3SJacky Wang deps = [":A"], 155*f585d8a3SJacky Wang ) 156*f585d8a3SJacky Wang 157*f585d8a3SJacky Wang _maven_info_test( 158*f585d8a3SJacky Wang name = "a_test", 159*f585d8a3SJacky Wang target = ":A", 160*f585d8a3SJacky Wang artifact = "A:_:_", 161*f585d8a3SJacky Wang maven_transitive_deps = [], 162*f585d8a3SJacky Wang all_transitive_deps = [], 163*f585d8a3SJacky Wang ) 164*f585d8a3SJacky Wang 165*f585d8a3SJacky Wang _maven_info_test( 166*f585d8a3SJacky Wang name = "dependencies_test", 167*f585d8a3SJacky Wang target = ":DepOnA", 168*f585d8a3SJacky Wang artifact = "DepOnA:_:_", 169*f585d8a3SJacky Wang maven_transitive_deps = [":A"], 170*f585d8a3SJacky Wang all_transitive_deps = [":A"], 171*f585d8a3SJacky Wang ) 172*f585d8a3SJacky Wang 173*f585d8a3SJacky Wang _fake_java_library( 174*f585d8a3SJacky Wang name = "ExportsA", 175*f585d8a3SJacky Wang exports = [":A"], 176*f585d8a3SJacky Wang ) 177*f585d8a3SJacky Wang 178*f585d8a3SJacky Wang _maven_info_test( 179*f585d8a3SJacky Wang name = "exports_test", 180*f585d8a3SJacky Wang target = ":ExportsA", 181*f585d8a3SJacky Wang artifact = "ExportsA:_:_", 182*f585d8a3SJacky Wang maven_transitive_deps = [":A"], 183*f585d8a3SJacky Wang all_transitive_deps = [":A"], 184*f585d8a3SJacky Wang ) 185*f585d8a3SJacky Wang 186*f585d8a3SJacky Wang _fake_java_library( 187*f585d8a3SJacky Wang name = "TransitiveExports", 188*f585d8a3SJacky Wang exports = [":ExportsA"], 189*f585d8a3SJacky Wang ) 190*f585d8a3SJacky Wang 191*f585d8a3SJacky Wang _maven_info_test( 192*f585d8a3SJacky Wang name = "transitive_exports_test", 193*f585d8a3SJacky Wang target = ":TransitiveExports", 194*f585d8a3SJacky Wang artifact = "TransitiveExports:_:_", 195*f585d8a3SJacky Wang maven_transitive_deps = [":ExportsA", ":A"], 196*f585d8a3SJacky Wang all_transitive_deps = [":ExportsA", ":A"], 197*f585d8a3SJacky Wang ) 198*f585d8a3SJacky Wang 199*f585d8a3SJacky Wang _fake_java_library( 200*f585d8a3SJacky Wang name = "TransitiveDeps", 201*f585d8a3SJacky Wang deps = [":ExportsA"], 202*f585d8a3SJacky Wang ) 203*f585d8a3SJacky Wang 204*f585d8a3SJacky Wang _maven_info_test( 205*f585d8a3SJacky Wang name = "transitive_deps_test", 206*f585d8a3SJacky Wang target = ":TransitiveDeps", 207*f585d8a3SJacky Wang artifact = "TransitiveDeps:_:_", 208*f585d8a3SJacky Wang maven_transitive_deps = [":ExportsA", ":A"], 209*f585d8a3SJacky Wang all_transitive_deps = [":ExportsA", ":A"], 210*f585d8a3SJacky Wang ) 211*f585d8a3SJacky Wang 212*f585d8a3SJacky Wang _fake_java_library(name = "Node1", is_artifact = False) 213*f585d8a3SJacky Wang _maven_info_test( 214*f585d8a3SJacky Wang name = "test_node1", 215*f585d8a3SJacky Wang target = ":Node1", 216*f585d8a3SJacky Wang maven_transitive_deps = [], 217*f585d8a3SJacky Wang all_transitive_deps = [], 218*f585d8a3SJacky Wang ) 219*f585d8a3SJacky Wang 220*f585d8a3SJacky Wang _fake_java_library(name = "Node2_Artifact", deps = [":Node1"]) 221*f585d8a3SJacky Wang _maven_info_test( 222*f585d8a3SJacky Wang name = "test_node2", 223*f585d8a3SJacky Wang target = ":Node2_Artifact", 224*f585d8a3SJacky Wang artifact = "Node2_Artifact:_:_", 225*f585d8a3SJacky Wang maven_transitive_deps = [], 226*f585d8a3SJacky Wang all_transitive_deps = [":Node1"], 227*f585d8a3SJacky Wang ) 228*f585d8a3SJacky Wang 229*f585d8a3SJacky Wang _fake_java_library(name = "Node3", deps = [":Node2_Artifact"], is_artifact = False) 230*f585d8a3SJacky Wang _maven_info_test( 231*f585d8a3SJacky Wang name = "test_node3", 232*f585d8a3SJacky Wang target = ":Node3", 233*f585d8a3SJacky Wang maven_transitive_deps = [":Node1", ":Node2_Artifact"], 234*f585d8a3SJacky Wang all_transitive_deps = [":Node1", ":Node2_Artifact"], 235*f585d8a3SJacky Wang ) 236*f585d8a3SJacky Wang 237*f585d8a3SJacky Wang _fake_java_library(name = "Node4", deps = [":Node3"], is_artifact = False) 238*f585d8a3SJacky Wang _maven_info_test( 239*f585d8a3SJacky Wang name = "test_node4", 240*f585d8a3SJacky Wang target = ":Node4", 241*f585d8a3SJacky Wang maven_transitive_deps = [":Node1", ":Node2_Artifact"], 242*f585d8a3SJacky Wang all_transitive_deps = [":Node1", ":Node2_Artifact", ":Node3"], 243*f585d8a3SJacky Wang ) 244