| # 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_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 pkg_dir(workspace_root, package_name): |
| """Returns a path to a package directory from the root of the sandbox.""" |
| if workspace_root and package_name: |
| return workspace_root + "/" + package_name |
| if workspace_root: |
| return workspace_root |
| if package_name: |
| return package_name |
| return "." |
| |
| 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 env_execute(ctx, arguments, environment = {}, **kwargs): |
| """Executes a command in for a repository rule. |
| |
| It prepends "env -i" to "arguments" before calling "ctx.execute". |
| Variables that aren't explicitly mentioned in "environment" |
| are removed from the environment. This should be preferred to "ctx.execute" |
| in most situations. |
| """ |
| if ctx.os.name.startswith("windows"): |
| return ctx.execute(arguments, environment = environment, **kwargs) |
| env_args = ["env", "-i"] |
| environment = dict(environment) |
| for var in ["TMP", "TMPDIR"]: |
| if var in ctx.os.environ and not var in environment: |
| environment[var] = ctx.os.environ[var] |
| for k, v in environment.items(): |
| env_args.append("%s=%s" % (k, v)) |
| arguments = env_args + arguments |
| return ctx.execute(arguments, **kwargs) |
| |
| 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 = "4.2.1" |
| |
| 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 |