xref: /aosp_15_r20/external/executorch/third-party/glob_defs.bzl (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1# Copy from caffe2/tools/build_defs/glob_defs.bzl
2# Only used for PyTorch open source BUCK build
3
4"""Provides utility macros for working with globs."""
5
6load("@prelude//:paths.bzl", "paths")
7
8def subdir_glob(glob_specs, exclude = None, prefix = ""):
9    """Returns a dict of sub-directory relative paths to full paths.
10
11    The subdir_glob() function is useful for defining header maps for C/C++
12    libraries which should be relative the given sub-directory.
13    Given a list of tuples, the form of (relative-sub-directory, glob-pattern),
14    it returns a dict of sub-directory relative paths to full paths.
15
16    Please refer to native.glob() for explanations and examples of the pattern.
17
18    Args:
19      glob_specs: The array of tuples in form of
20        (relative-sub-directory, glob-pattern inside relative-sub-directory).
21        type: List[Tuple[str, str]]
22      exclude: A list of patterns to identify files that should be removed
23        from the set specified by the first argument. Defaults to [].
24        type: Optional[List[str]]
25      prefix: If is not None, prepends it to each key in the dictionary.
26        Defaults to None.
27        type: Optional[str]
28
29    Returns:
30      A dict of sub-directory relative paths to full paths.
31    """
32    if exclude == None:
33        exclude = []
34
35    results = []
36
37    for dirpath, glob_pattern in glob_specs:
38        results.append(
39            _single_subdir_glob(dirpath, glob_pattern, exclude, prefix),
40        )
41
42    return _merge_maps(*results)
43
44def _merge_maps(*file_maps):
45    result = {}
46    for file_map in file_maps:
47        for key in file_map:
48            if key in result and result[key] != file_map[key]:
49                fail(
50                    "Conflicting files in file search paths. " +
51                    "\"%s\" maps to both \"%s\" and \"%s\"." %
52                    (key, result[key], file_map[key]),
53                )
54
55            result[key] = file_map[key]
56
57    return result
58
59def _single_subdir_glob(dirpath, glob_pattern, exclude = None, prefix = None):
60    if exclude == None:
61        exclude = []
62    results = {}
63    files = native.glob([paths.join(dirpath, glob_pattern)], exclude = exclude)
64    for f in files:
65        if dirpath:
66            key = f[len(dirpath) + 1:]
67        else:
68            key = f
69        if prefix:
70            key = paths.join(prefix, key)
71        results[key] = f
72
73    return results
74
75# Using a flat list will trigger build errors on Android.
76# cxx_library will generate an apple_library on iOS, a cxx_library on Android.
77# Those rules have different behaviors. Using a map will make the behavior consistent.
78#
79def glob_private_headers(glob_patterns, exclude = []):
80    result = {}
81    headers = native.glob(glob_patterns, exclude = exclude)
82    for header in headers:
83        result[paths.basename(header)] = header
84    return result
85
86def glob(include, exclude = (), **kwargs):
87    buildfile = native.read_config("buildfile", "name", "BUCK")
88    subpkgs = [
89        target[:-len(buildfile)] + "**/*"
90        for target in native.glob(["*/**/" + buildfile])
91    ]
92    return native.glob(include, exclude = list(exclude) + subpkgs, **kwargs)
93