xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/path.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2018 The Bazel Authors. All rights reserved.
2*9e965d6fSRomain Jobredeaux#
3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License");
4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License.
5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at
6*9e965d6fSRomain Jobredeaux#
7*9e965d6fSRomain Jobredeaux#    http://www.apache.org/licenses/LICENSE-2.0
8*9e965d6fSRomain Jobredeaux#
9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software
10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS,
11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and
13*9e965d6fSRomain Jobredeaux# limitations under the License.
14*9e965d6fSRomain Jobredeaux
15*9e965d6fSRomain Jobredeaux"""Bazel Path APIs for the Android rules."""
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeaux# TODO(djwhang): Get the path separator in a platform agnostic manner.
18*9e965d6fSRomain Jobredeaux_PATH_SEP = "/"
19*9e965d6fSRomain Jobredeaux_TEST_SRCDIR = "${TEST_SRCDIR}"
20*9e965d6fSRomain Jobredeaux
21*9e965d6fSRomain Jobredeauxdef _is_absolute(path):
22*9e965d6fSRomain Jobredeaux    # TODO(djwhang): This is not cross platform safe. Windows absolute paths
23*9e965d6fSRomain Jobredeaux    # do not start with "//", rather "C:\".
24*9e965d6fSRomain Jobredeaux    return path.startswith(_PATH_SEP)
25*9e965d6fSRomain Jobredeaux
26*9e965d6fSRomain Jobredeauxdef _split(path):
27*9e965d6fSRomain Jobredeaux    return path.split(_PATH_SEP)
28*9e965d6fSRomain Jobredeaux
29*9e965d6fSRomain Jobredeauxdef _join(path_segments):
30*9e965d6fSRomain Jobredeaux    return _PATH_SEP.join(path_segments)
31*9e965d6fSRomain Jobredeaux
32*9e965d6fSRomain Jobredeauxdef _normalize_path(path, posix = False):
33*9e965d6fSRomain Jobredeaux    return _PATH_SEP.join(
34*9e965d6fSRomain Jobredeaux        _normalize_path_fragments(
35*9e965d6fSRomain Jobredeaux            path.split(_PATH_SEP),
36*9e965d6fSRomain Jobredeaux            posix = posix,
37*9e965d6fSRomain Jobredeaux        ),
38*9e965d6fSRomain Jobredeaux    )
39*9e965d6fSRomain Jobredeaux
40*9e965d6fSRomain Jobredeauxdef _normalize_path_fragments(path_fragments, posix = False):
41*9e965d6fSRomain Jobredeaux    normalized_path_fragments = []
42*9e965d6fSRomain Jobredeaux    for idx, fragment in enumerate(path_fragments):
43*9e965d6fSRomain Jobredeaux        if not fragment and idx > 0:
44*9e965d6fSRomain Jobredeaux            continue
45*9e965d6fSRomain Jobredeaux        if fragment == ".":
46*9e965d6fSRomain Jobredeaux            continue
47*9e965d6fSRomain Jobredeaux        if fragment == ".." and not posix:
48*9e965d6fSRomain Jobredeaux            if normalized_path_fragments:
49*9e965d6fSRomain Jobredeaux                last = normalized_path_fragments.pop()
50*9e965d6fSRomain Jobredeaux                if last == ".." or last == "":
51*9e965d6fSRomain Jobredeaux                    normalized_path_fragments.append(last)
52*9e965d6fSRomain Jobredeaux                else:
53*9e965d6fSRomain Jobredeaux                    continue
54*9e965d6fSRomain Jobredeaux        normalized_path_fragments.append(fragment)
55*9e965d6fSRomain Jobredeaux    if len(normalized_path_fragments) == 1 and not normalized_path_fragments[0]:
56*9e965d6fSRomain Jobredeaux        normalized_path_fragments.append("")
57*9e965d6fSRomain Jobredeaux    return normalized_path_fragments
58*9e965d6fSRomain Jobredeaux
59*9e965d6fSRomain Jobredeauxdef _relative_path(path1, path2):
60*9e965d6fSRomain Jobredeaux    if not path1 or _is_absolute(path2):
61*9e965d6fSRomain Jobredeaux        return path2
62*9e965d6fSRomain Jobredeaux
63*9e965d6fSRomain Jobredeaux    path1_fragments = _normalize_path_fragments(_split(path1))
64*9e965d6fSRomain Jobredeaux    path2_fragments = _normalize_path_fragments(_split(path2))
65*9e965d6fSRomain Jobredeaux    path1_idx = len(path1_fragments)  # index move backwards
66*9e965d6fSRomain Jobredeaux    path2_idx = -1
67*9e965d6fSRomain Jobredeaux    for idx, fragment in enumerate(path2_fragments):
68*9e965d6fSRomain Jobredeaux        if fragment == "..":
69*9e965d6fSRomain Jobredeaux            path1_idx -= 1
70*9e965d6fSRomain Jobredeaux        else:
71*9e965d6fSRomain Jobredeaux            path2_idx = idx
72*9e965d6fSRomain Jobredeaux            break
73*9e965d6fSRomain Jobredeaux
74*9e965d6fSRomain Jobredeaux    relative_path_fragments = []
75*9e965d6fSRomain Jobredeaux    if path1_idx >= 0:
76*9e965d6fSRomain Jobredeaux        relative_path_fragments.extend(path1_fragments[:path1_idx])
77*9e965d6fSRomain Jobredeaux    if path2_idx >= 0:
78*9e965d6fSRomain Jobredeaux        relative_path_fragments.extend(path2_fragments[path2_idx:])
79*9e965d6fSRomain Jobredeaux    return _join(_normalize_path_fragments(relative_path_fragments))
80*9e965d6fSRomain Jobredeaux
81*9e965d6fSRomain Jobredeauxdef _make_test_srcdir_path(ctx, *path_fragments):
82*9e965d6fSRomain Jobredeaux    """Creates a filepath relative to TEST_SRCDIR.
83*9e965d6fSRomain Jobredeaux
84*9e965d6fSRomain Jobredeaux    Args:
85*9e965d6fSRomain Jobredeaux        ctx: Starlark context.
86*9e965d6fSRomain Jobredeaux        *path_fragments: Directories/file to join into a single path.
87*9e965d6fSRomain Jobredeaux    Returns:
88*9e965d6fSRomain Jobredeaux        A filepath that's spearated by the host's filepath separator.
89*9e965d6fSRomain Jobredeaux    """
90*9e965d6fSRomain Jobredeaux    fragments = [_TEST_SRCDIR, ctx.workspace_name]
91*9e965d6fSRomain Jobredeaux    for path_fragment in path_fragments:
92*9e965d6fSRomain Jobredeaux        fragments += _normalize_path_fragments(_split(path_fragment))
93*9e965d6fSRomain Jobredeaux    return _join(fragments)
94*9e965d6fSRomain Jobredeaux
95*9e965d6fSRomain Jobredeauxpath = struct(
96*9e965d6fSRomain Jobredeaux    is_absolute = _is_absolute,
97*9e965d6fSRomain Jobredeaux    join = _join,
98*9e965d6fSRomain Jobredeaux    normalize = _normalize_path,
99*9e965d6fSRomain Jobredeaux    relative = _relative_path,
100*9e965d6fSRomain Jobredeaux    split = _split,
101*9e965d6fSRomain Jobredeaux    make_test_srcdir_path = _make_test_srcdir_path,
102*9e965d6fSRomain Jobredeaux)
103