# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing common functions for working with native.subpackages() """ _SUBPACKAGES_SUPPORTED = hasattr(native, "subpackages") def _supported(): return _SUBPACKAGES_SUPPORTED def _check_supported(): if not _SUBPACKAGES_SUPPORTED: fail("native.subpackages not supported in this version of Bazel.") def _all(exclude = [], allow_empty = False, fully_qualified = True): """List all direct subpackages of the current package regardless of directory depth. The returned list contains all subpackages, but not subpackages of subpackages. Example: Assuming the following BUILD files exist: BUILD foo/BUILD foo/sub/BUILD bar/BUILD baz/deep/dir/BUILD If the current package is '//' all() will return ['//foo', '//bar', '//baz/deep/dir']. //foo/sub is not included because it is a direct subpackage of '//foo' not '//' NOTE: fail()s if native.subpackages() is not supported. Args: exclude: see native.subpackages(exclude) allow_empty: see native.subpackages(allow_empty) fully_qualified: It true return fully qualified Labels for subpackages, otherwise returns subpackage path relative to current package. Returns: A mutable sorted list containing all sub-packages of the current Bazel package. """ _check_supported() subs = native.subpackages(include = ["**"], exclude = exclude, allow_empty = allow_empty) if fully_qualified: return [_fully_qualified(s) for s in subs] return subs def _fully_qualified(relative_path): package_name = native.package_name() if package_name: return "//%s/%s" % (package_name, relative_path) return "//" + relative_path def _exists(relative_path): """Checks to see if relative_path is a direct subpackage of the current package. Example: BUILD foo/BUILD foo/sub/BUILD If the current package is '//' (the top-level BUILD file): subpackages.exists("foo") == True subpackages.exists("foo/sub") == False subpackages.exists("bar") == False NOTE: fail()s if native.subpackages() is not supported in the current Bazel version. Args: relative_path: a path to a subpackage to test, must not be an absolute Label. Returns: True if 'relative_path' is a subpackage of the current package. """ _check_supported() return relative_path in native.subpackages(include = [relative_path], allow_empty = True) subpackages = struct( all = _all, exists = _exists, supported = _supported, )