xref: /aosp_15_r20/external/dagger2/tools/maven_info.bzl (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
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