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