blob: 51056f65cdfa0d04aa38e5a533feb7a3d18e7196 [file] [log] [blame]
# Copyright 2014 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.
GO_TOOLCHAIN = "@io_bazel_rules_go//go:toolchain"
GO_TOOLCHAIN_LABEL = Label(GO_TOOLCHAIN)
go_exts = [
".go",
]
asm_exts = [
".s",
".S",
".h", # may be included by .s
]
# be consistent to cc_library.
hdr_exts = [
".h",
".hh",
".hpp",
".hxx",
".inc",
]
c_exts = [
".c",
".h",
]
cxx_exts = [
".cc",
".cxx",
".cpp",
".h",
".hh",
".hpp",
".hxx",
]
objc_exts = [
".m",
".mm",
".h",
".hh",
".hpp",
".hxx",
]
cgo_exts = [
".c",
".cc",
".cpp",
".cxx",
".h",
".hh",
".hpp",
".hxx",
".inc",
".m",
".mm",
]
def split_srcs(srcs):
"""Returns a struct of sources, divided by extension."""
sources = struct(
go = [],
asm = [],
headers = [],
c = [],
cxx = [],
objc = [],
)
ext_pairs = (
(sources.go, go_exts),
(sources.headers, hdr_exts),
(sources.asm, asm_exts),
(sources.c, c_exts),
(sources.cxx, cxx_exts),
(sources.objc, objc_exts),
)
extmap = {}
for outs, exts in ext_pairs:
for ext in exts:
ext = ext[1:] # strip the dot
if ext in extmap:
break
extmap[ext] = outs
for src in as_iterable(srcs):
extouts = extmap.get(src.extension)
if extouts == None:
fail("Unknown source type {0}".format(src.basename))
extouts.append(src)
return sources
def join_srcs(source):
"""Combines source from a split_srcs struct into a single list."""
return source.go + source.headers + source.asm + source.c + source.cxx + source.objc
def os_path(ctx, path):
path = str(path) # maybe convert from path type
if ctx.os.name.startswith("windows"):
path = path.replace("/", "\\")
return path
def executable_path(ctx, path):
path = os_path(ctx, path)
if ctx.os.name.startswith("windows"):
path += ".exe"
return path
def executable_extension(ctx):
extension = ""
if ctx.os.name.startswith("windows"):
extension = ".exe"
return extension
def goos_to_extension(goos):
if goos == "windows":
return ".exe"
return ""
ARCHIVE_EXTENSION = ".a"
SHARED_LIB_EXTENSIONS = [".dll", ".dylib", ".so"]
def goos_to_shared_extension(goos):
return {
"windows": ".dll",
"darwin": ".dylib",
}.get(goos, ".so")
def has_shared_lib_extension(path):
"""
Matches filenames of shared libraries, with or without a version number extension.
"""
return (has_simple_shared_lib_extension(path) or
get_versioned_shared_lib_extension(path))
def has_simple_shared_lib_extension(path):
"""
Matches filenames of shared libraries, without a version number extension.
"""
return any([path.endswith(ext) for ext in SHARED_LIB_EXTENSIONS])
def get_versioned_shared_lib_extension(path):
"""If appears to be an versioned .so or .dylib file, return the extension; otherwise empty"""
parts = path.split("/")[-1].split(".")
if not parts[-1].isdigit():
return ""
# only iterating to 1 because parts[0] has to be the lib name
for i in range(len(parts) - 1, 0, -1):
if not parts[i].isdigit():
if parts[i] == "dylib" or parts[i] == "so":
return ".".join(parts[i:])
# something like foo.bar.1.2 or dylib.1.2
return ""
# something like 1.2.3, or so.1.2, or dylib.1.2, or foo.1.2
return ""
MINIMUM_BAZEL_VERSION = "5.4.0"
def as_list(v):
"""Returns a list, tuple, or depset as a list."""
if type(v) == "list":
return v
if type(v) == "tuple":
return list(v)
if type(v) == "depset":
return v.to_list()
fail("as_list failed on {}".format(v))
def as_iterable(v):
"""Returns a list, tuple, or depset as something iterable."""
if type(v) == "list":
return v
if type(v) == "tuple":
return v
if type(v) == "depset":
return v.to_list()
fail("as_iterator failed on {}".format(v))
def as_tuple(v):
"""Returns a list, tuple, or depset as a tuple."""
if type(v) == "tuple":
return v
if type(v) == "list":
return tuple(v)
if type(v) == "depset":
return tuple(v.to_list())
fail("as_tuple failed on {}".format(v))
def as_set(v):
"""Returns a list, tuple, or depset as a depset."""
if type(v) == "depset":
return v
if type(v) == "list":
return depset(v)
if type(v) == "tuple":
return depset(v)
fail("as_tuple failed on {}".format(v))
_STRUCT_TYPE = type(struct())
def is_struct(v):
"""Returns true if v is a struct."""
return type(v) == _STRUCT_TYPE
def count_group_matches(v, prefix, suffix):
"""Counts reluctant substring matches between prefix and suffix.
Equivalent to the number of regular expression matches "prefix.+?suffix"
in the string v.
"""
count = 0
idx = 0
for i in range(0, len(v)):
if idx > i:
continue
idx = v.find(prefix, idx)
if idx == -1:
break
# If there is another prefix before the next suffix, the previous prefix is discarded.
# This is OK; it does not affect our count.
idx = v.find(suffix, idx)
if idx == -1:
break
count = count + 1
return count
# C/C++ compiler and linker options related to coverage instrumentation.
COVERAGE_OPTIONS_DENYLIST = {
"--coverage": None,
"-ftest-coverage": None,
"-fprofile-arcs": None,
"-fprofile-instr-generate": None,
"-fcoverage-mapping": None,
}
_RULES_GO_RAW_REPO_NAME = str(Label("//:unused"))[:-len("//:unused")]
# When rules_go is the main repository and Bazel < 6 is used, the repo name does
# not start with a "@", so we need to add it.
RULES_GO_REPO_NAME = _RULES_GO_RAW_REPO_NAME if _RULES_GO_RAW_REPO_NAME.startswith("@") else "@" + _RULES_GO_RAW_REPO_NAME
RULES_GO_STDLIB_PREFIX = RULES_GO_REPO_NAME + "//stdlib:"
# TODO: Remove the "and" once the rules_go repo itself uses Bzlmod.
RULES_GO_IS_BZLMOD_REPO = _RULES_GO_RAW_REPO_NAME.lstrip("@") != "io_bazel_rules_go" and _RULES_GO_RAW_REPO_NAME.lstrip("@")