xref: /aosp_15_r20/external/tink/java_src/tools/check_deps.bzl (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang# Copyright 2022 Google LLC
2*e7b1675dSTing-Kang Chang#
3*e7b1675dSTing-Kang Chang# Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang# you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang# You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang#
7*e7b1675dSTing-Kang Chang# http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang#
9*e7b1675dSTing-Kang Chang# Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang# distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang# See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang# limitations under the License.
14*e7b1675dSTing-Kang Chang
15*e7b1675dSTing-Kang Chang"""Defines a rule to check the dependencies of a given target."""
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Changload("@bazel_skylib//lib:new_sets.bzl", "sets")
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Chang# Traverse the dependency graph along the "deps" attribute of the
20*e7b1675dSTing-Kang Chang# target and return a struct with one field called 'tf_collected_deps'.
21*e7b1675dSTing-Kang Chang# tf_collected_deps will be the union of the deps of the current target
22*e7b1675dSTing-Kang Chang# and the tf_collected_deps of the dependencies of this target.
23*e7b1675dSTing-Kang Chang# Borrowed from TensorFlow (https://github.com/tensorflow/tensorflow).
24*e7b1675dSTing-Kang Changdef _collect_deps_aspect_impl(target, ctx):
25*e7b1675dSTing-Kang Chang    direct, transitive = [], []
26*e7b1675dSTing-Kang Chang    all_deps = []
27*e7b1675dSTing-Kang Chang    if hasattr(ctx.rule.attr, "deps"):
28*e7b1675dSTing-Kang Chang        all_deps += ctx.rule.attr.deps
29*e7b1675dSTing-Kang Chang    if hasattr(ctx.rule.attr, "data"):
30*e7b1675dSTing-Kang Chang        all_deps += ctx.rule.attr.data
31*e7b1675dSTing-Kang Chang    for dep in all_deps:
32*e7b1675dSTing-Kang Chang        direct.append(dep.label)
33*e7b1675dSTing-Kang Chang        if hasattr(dep, "tf_collected_deps"):
34*e7b1675dSTing-Kang Chang            transitive.append(dep.tf_collected_deps)
35*e7b1675dSTing-Kang Chang    return struct(tf_collected_deps = depset(direct = direct, transitive = transitive))
36*e7b1675dSTing-Kang Chang
37*e7b1675dSTing-Kang Changcollect_deps_aspect = aspect(
38*e7b1675dSTing-Kang Chang    attr_aspects = ["deps", "data"],
39*e7b1675dSTing-Kang Chang    implementation = _collect_deps_aspect_impl,
40*e7b1675dSTing-Kang Chang)
41*e7b1675dSTing-Kang Chang
42*e7b1675dSTing-Kang Changdef _dep_label(dep):
43*e7b1675dSTing-Kang Chang    label = dep.label
44*e7b1675dSTing-Kang Chang    return label.package + ":" + label.name
45*e7b1675dSTing-Kang Chang
46*e7b1675dSTing-Kang Chang# This rule checks that transitive dependencies don't depend on the targets
47*e7b1675dSTing-Kang Chang# listed in the 'disallowed_deps' attribute, but do depend on the targets listed
48*e7b1675dSTing-Kang Chang# in the 'required_deps' attribute. Dependencies considered are targets in the
49*e7b1675dSTing-Kang Chang# 'deps' attribute or the 'data' attribute.
50*e7b1675dSTing-Kang Chang# Borrowed from TensorFlow (https://github.com/tensorflow/tensorflow).
51*e7b1675dSTing-Kang Changdef _check_deps_impl(ctx):
52*e7b1675dSTing-Kang Chang    required_deps = ctx.attr.required_deps
53*e7b1675dSTing-Kang Chang    disallowed_deps = ctx.attr.disallowed_deps
54*e7b1675dSTing-Kang Chang    for input_dep in ctx.attr.deps:
55*e7b1675dSTing-Kang Chang        if not hasattr(input_dep, "tf_collected_deps"):
56*e7b1675dSTing-Kang Chang            continue
57*e7b1675dSTing-Kang Chang        collected_deps = sets.make(input_dep.tf_collected_deps.to_list())
58*e7b1675dSTing-Kang Chang        for disallowed_dep in disallowed_deps:
59*e7b1675dSTing-Kang Chang            if sets.contains(collected_deps, disallowed_dep.label):
60*e7b1675dSTing-Kang Chang                fail(
61*e7b1675dSTing-Kang Chang                    _dep_label(input_dep) + " cannot depend on " +
62*e7b1675dSTing-Kang Chang                    _dep_label(disallowed_dep),
63*e7b1675dSTing-Kang Chang                )
64*e7b1675dSTing-Kang Chang        for required_dep in required_deps:
65*e7b1675dSTing-Kang Chang            if not sets.contains(collected_deps, required_dep.label):
66*e7b1675dSTing-Kang Chang                fail(
67*e7b1675dSTing-Kang Chang                    _dep_label(input_dep) + " must depend on " +
68*e7b1675dSTing-Kang Chang                    _dep_label(required_dep),
69*e7b1675dSTing-Kang Chang                )
70*e7b1675dSTing-Kang Chang
71*e7b1675dSTing-Kang Changcheck_deps = rule(
72*e7b1675dSTing-Kang Chang    _check_deps_impl,
73*e7b1675dSTing-Kang Chang    attrs = {
74*e7b1675dSTing-Kang Chang        "deps": attr.label_list(
75*e7b1675dSTing-Kang Chang            aspects = [collect_deps_aspect],
76*e7b1675dSTing-Kang Chang            mandatory = True,
77*e7b1675dSTing-Kang Chang            allow_files = True,
78*e7b1675dSTing-Kang Chang        ),
79*e7b1675dSTing-Kang Chang        "disallowed_deps": attr.label_list(
80*e7b1675dSTing-Kang Chang            default = [],
81*e7b1675dSTing-Kang Chang            allow_files = True,
82*e7b1675dSTing-Kang Chang        ),
83*e7b1675dSTing-Kang Chang        "required_deps": attr.label_list(
84*e7b1675dSTing-Kang Chang            default = [],
85*e7b1675dSTing-Kang Chang            allow_files = True,
86*e7b1675dSTing-Kang Chang        ),
87*e7b1675dSTing-Kang Chang    },
88*e7b1675dSTing-Kang Chang)
89