xref: /aosp_15_r20/external/bazel-skylib/lib/subpackages.bzl (revision bcb5dc7965af6ee42bf2f21341a2ec00233a8c8a)
1*bcb5dc79SHONG Yifan# Copyright 2022 The Bazel Authors. All rights reserved.
2*bcb5dc79SHONG Yifan#
3*bcb5dc79SHONG Yifan# Licensed under the Apache License, Version 2.0 (the "License");
4*bcb5dc79SHONG Yifan# you may not use this file except in compliance with the License.
5*bcb5dc79SHONG Yifan# You may obtain a copy of the License at
6*bcb5dc79SHONG Yifan#
7*bcb5dc79SHONG Yifan#    http://www.apache.org/licenses/LICENSE-2.0
8*bcb5dc79SHONG Yifan#
9*bcb5dc79SHONG Yifan# Unless required by applicable law or agreed to in writing, software
10*bcb5dc79SHONG Yifan# distributed under the License is distributed on an "AS IS" BASIS,
11*bcb5dc79SHONG Yifan# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*bcb5dc79SHONG Yifan# See the License for the specific language governing permissions and
13*bcb5dc79SHONG Yifan# limitations under the License.
14*bcb5dc79SHONG Yifan
15*bcb5dc79SHONG Yifan"""Skylib module containing common functions for working with native.subpackages()
16*bcb5dc79SHONG Yifan"""
17*bcb5dc79SHONG Yifan_SUBPACKAGES_SUPPORTED = hasattr(native, "subpackages")
18*bcb5dc79SHONG Yifan
19*bcb5dc79SHONG Yifandef _supported():
20*bcb5dc79SHONG Yifan    return _SUBPACKAGES_SUPPORTED
21*bcb5dc79SHONG Yifan
22*bcb5dc79SHONG Yifandef _check_supported():
23*bcb5dc79SHONG Yifan    if not _SUBPACKAGES_SUPPORTED:
24*bcb5dc79SHONG Yifan        fail("native.subpackages not supported in this version of Bazel.")
25*bcb5dc79SHONG Yifan
26*bcb5dc79SHONG Yifandef _all(exclude = [], allow_empty = False, fully_qualified = True):
27*bcb5dc79SHONG Yifan    """List all direct subpackages of the current package regardless of directory depth.
28*bcb5dc79SHONG Yifan
29*bcb5dc79SHONG Yifan    The returned list contains all subpackages, but not subpackages of subpackages.
30*bcb5dc79SHONG Yifan
31*bcb5dc79SHONG Yifan    Example:
32*bcb5dc79SHONG Yifan    Assuming the following BUILD files exist:
33*bcb5dc79SHONG Yifan
34*bcb5dc79SHONG Yifan        BUILD
35*bcb5dc79SHONG Yifan        foo/BUILD
36*bcb5dc79SHONG Yifan        foo/sub/BUILD
37*bcb5dc79SHONG Yifan        bar/BUILD
38*bcb5dc79SHONG Yifan        baz/deep/dir/BUILD
39*bcb5dc79SHONG Yifan
40*bcb5dc79SHONG Yifan    If the current package is '//' all() will return ['//foo', '//bar',
41*bcb5dc79SHONG Yifan    '//baz/deep/dir'].  //foo/sub is not included because it is a direct
42*bcb5dc79SHONG Yifan    subpackage of '//foo' not '//'
43*bcb5dc79SHONG Yifan
44*bcb5dc79SHONG Yifan    NOTE: fail()s if native.subpackages() is not supported.
45*bcb5dc79SHONG Yifan
46*bcb5dc79SHONG Yifan    Args:
47*bcb5dc79SHONG Yifan      exclude:          see native.subpackages(exclude)
48*bcb5dc79SHONG Yifan      allow_empty:      see native.subpackages(allow_empty)
49*bcb5dc79SHONG Yifan      fully_qualified:  It true return fully qualified Labels for subpackages,
50*bcb5dc79SHONG Yifan          otherwise returns subpackage path relative to current package.
51*bcb5dc79SHONG Yifan
52*bcb5dc79SHONG Yifan    Returns:
53*bcb5dc79SHONG Yifan      A mutable sorted list containing all sub-packages of the current Bazel
54*bcb5dc79SHONG Yifan      package.
55*bcb5dc79SHONG Yifan    """
56*bcb5dc79SHONG Yifan    _check_supported()
57*bcb5dc79SHONG Yifan
58*bcb5dc79SHONG Yifan    subs = native.subpackages(include = ["**"], exclude = exclude, allow_empty = allow_empty)
59*bcb5dc79SHONG Yifan    if fully_qualified:
60*bcb5dc79SHONG Yifan        return [_fully_qualified(s) for s in subs]
61*bcb5dc79SHONG Yifan
62*bcb5dc79SHONG Yifan    return subs
63*bcb5dc79SHONG Yifan
64*bcb5dc79SHONG Yifandef _fully_qualified(relative_path):
65*bcb5dc79SHONG Yifan    return "//%s/%s" % (native.package_name(), relative_path)
66*bcb5dc79SHONG Yifan
67*bcb5dc79SHONG Yifandef _exists(relative_path):
68*bcb5dc79SHONG Yifan    """Checks to see if relative_path is a direct subpackage of the current package.
69*bcb5dc79SHONG Yifan
70*bcb5dc79SHONG Yifan    Example:
71*bcb5dc79SHONG Yifan
72*bcb5dc79SHONG Yifan        BUILD
73*bcb5dc79SHONG Yifan        foo/BUILD
74*bcb5dc79SHONG Yifan        foo/sub/BUILD
75*bcb5dc79SHONG Yifan
76*bcb5dc79SHONG Yifan    If the current package is '//' (the top-level BUILD file):
77*bcb5dc79SHONG Yifan        subpackages.exists("foo") == True
78*bcb5dc79SHONG Yifan        subpackages.exists("foo/sub") == False
79*bcb5dc79SHONG Yifan        subpackages.exists("bar") == False
80*bcb5dc79SHONG Yifan
81*bcb5dc79SHONG Yifan    NOTE: fail()s if native.subpackages() is not supported in the current Bazel version.
82*bcb5dc79SHONG Yifan
83*bcb5dc79SHONG Yifan    Args:
84*bcb5dc79SHONG Yifan      relative_path: a path to a subpackage to test, must not be an absolute Label.
85*bcb5dc79SHONG Yifan
86*bcb5dc79SHONG Yifan    Returns:
87*bcb5dc79SHONG Yifan      True if 'relative_path' is a subpackage of the current package.
88*bcb5dc79SHONG Yifan    """
89*bcb5dc79SHONG Yifan    _check_supported()
90*bcb5dc79SHONG Yifan    return relative_path in native.subpackages(include = [relative_path], allow_empty = True)
91*bcb5dc79SHONG Yifan
92*bcb5dc79SHONG Yifansubpackages = struct(
93*bcb5dc79SHONG Yifan    all = _all,
94*bcb5dc79SHONG Yifan    exists = _exists,
95*bcb5dc79SHONG Yifan    supported = _supported,
96*bcb5dc79SHONG Yifan)
97