xref: /aosp_15_r20/external/bazelbuild-rules_go/go/private/common.bzl (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1# Copyright 2014 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15go_exts = [
16    ".go",
17]
18
19asm_exts = [
20    ".s",
21    ".S",
22    ".h",  # may be included by .s
23]
24
25# be consistent to cc_library.
26hdr_exts = [
27    ".h",
28    ".hh",
29    ".hpp",
30    ".hxx",
31    ".inc",
32]
33
34c_exts = [
35    ".c",
36    ".h",
37]
38
39cxx_exts = [
40    ".cc",
41    ".cxx",
42    ".cpp",
43    ".h",
44    ".hh",
45    ".hpp",
46    ".hxx",
47]
48
49objc_exts = [
50    ".m",
51    ".mm",
52    ".h",
53    ".hh",
54    ".hpp",
55    ".hxx",
56]
57
58cgo_exts = [
59    ".c",
60    ".cc",
61    ".cpp",
62    ".cxx",
63    ".h",
64    ".hh",
65    ".hpp",
66    ".hxx",
67    ".inc",
68    ".m",
69    ".mm",
70]
71
72def split_srcs(srcs):
73    """Returns a struct of sources, divided by extension."""
74    sources = struct(
75        go = [],
76        asm = [],
77        headers = [],
78        c = [],
79        cxx = [],
80        objc = [],
81    )
82    ext_pairs = (
83        (sources.go, go_exts),
84        (sources.headers, hdr_exts),
85        (sources.asm, asm_exts),
86        (sources.c, c_exts),
87        (sources.cxx, cxx_exts),
88        (sources.objc, objc_exts),
89    )
90    extmap = {}
91    for outs, exts in ext_pairs:
92        for ext in exts:
93            ext = ext[1:]  # strip the dot
94            if ext in extmap:
95                break
96            extmap[ext] = outs
97    for src in as_iterable(srcs):
98        extouts = extmap.get(src.extension)
99        if extouts == None:
100            fail("Unknown source type {0}".format(src.basename))
101        extouts.append(src)
102    return sources
103
104def join_srcs(source):
105    """Combines source from a split_srcs struct into a single list."""
106    return source.go + source.headers + source.asm + source.c + source.cxx + source.objc
107
108def os_path(ctx, path):
109    path = str(path)  # maybe convert from path type
110    if ctx.os.name.startswith("windows"):
111        path = path.replace("/", "\\")
112    return path
113
114def executable_path(ctx, path):
115    path = os_path(ctx, path)
116    if ctx.os.name.startswith("windows"):
117        path += ".exe"
118    return path
119
120def executable_extension(ctx):
121    extension = ""
122    if ctx.os.name.startswith("windows"):
123        extension = ".exe"
124    return extension
125
126def goos_to_extension(goos):
127    if goos == "windows":
128        return ".exe"
129    return ""
130
131ARCHIVE_EXTENSION = ".a"
132
133SHARED_LIB_EXTENSIONS = [".dll", ".dylib", ".so"]
134
135def goos_to_shared_extension(goos):
136    return {
137        "windows": ".dll",
138        "darwin": ".dylib",
139    }.get(goos, ".so")
140
141def has_shared_lib_extension(path):
142    """
143    Matches filenames of shared libraries, with or without a version number extension.
144    """
145    return (has_simple_shared_lib_extension(path) or
146            get_versioned_shared_lib_extension(path))
147
148def has_simple_shared_lib_extension(path):
149    """
150    Matches filenames of shared libraries, without a version number extension.
151    """
152    return any([path.endswith(ext) for ext in SHARED_LIB_EXTENSIONS])
153
154def get_versioned_shared_lib_extension(path):
155    """If appears to be an versioned .so or .dylib file, return the extension; otherwise empty"""
156    parts = path.split("/")[-1].split(".")
157    if not parts[-1].isdigit():
158        return ""
159
160    # only iterating to 1 because parts[0] has to be the lib name
161    for i in range(len(parts) - 1, 0, -1):
162        if not parts[i].isdigit():
163            if parts[i] == "dylib" or parts[i] == "so":
164                return ".".join(parts[i:])
165
166            # something like foo.bar.1.2 or dylib.1.2
167            return ""
168
169    # something like 1.2.3, or so.1.2, or dylib.1.2, or foo.1.2
170    return ""
171
172MINIMUM_BAZEL_VERSION = "5.4.0"
173
174def as_list(v):
175    """Returns a list, tuple, or depset as a list."""
176    if type(v) == "list":
177        return v
178    if type(v) == "tuple":
179        return list(v)
180    if type(v) == "depset":
181        return v.to_list()
182    fail("as_list failed on {}".format(v))
183
184def as_iterable(v):
185    """Returns a list, tuple, or depset as something iterable."""
186    if type(v) == "list":
187        return v
188    if type(v) == "tuple":
189        return v
190    if type(v) == "depset":
191        return v.to_list()
192    fail("as_iterator failed on {}".format(v))
193
194def as_tuple(v):
195    """Returns a list, tuple, or depset as a tuple."""
196    if type(v) == "tuple":
197        return v
198    if type(v) == "list":
199        return tuple(v)
200    if type(v) == "depset":
201        return tuple(v.to_list())
202    fail("as_tuple failed on {}".format(v))
203
204def as_set(v):
205    """Returns a list, tuple, or depset as a depset."""
206    if type(v) == "depset":
207        return v
208    if type(v) == "list":
209        return depset(v)
210    if type(v) == "tuple":
211        return depset(v)
212    fail("as_tuple failed on {}".format(v))
213
214_STRUCT_TYPE = type(struct())
215
216def is_struct(v):
217    """Returns true if v is a struct."""
218    return type(v) == _STRUCT_TYPE
219
220def count_group_matches(v, prefix, suffix):
221    """Counts reluctant substring matches between prefix and suffix.
222
223    Equivalent to the number of regular expression matches "prefix.+?suffix"
224    in the string v.
225    """
226
227    count = 0
228    idx = 0
229    for i in range(0, len(v)):
230        if idx > i:
231            continue
232
233        idx = v.find(prefix, idx)
234        if idx == -1:
235            break
236
237        # If there is another prefix before the next suffix, the previous prefix is discarded.
238        # This is OK; it does not affect our count.
239        idx = v.find(suffix, idx)
240        if idx == -1:
241            break
242
243        count = count + 1
244
245    return count
246
247# C/C++ compiler and linker options related to coverage instrumentation.
248COVERAGE_OPTIONS_DENYLIST = {
249    "--coverage": None,
250    "-ftest-coverage": None,
251    "-fprofile-arcs": None,
252    "-fprofile-instr-generate": None,
253    "-fcoverage-mapping": None,
254}
255