| # Copyright 2019 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. |
| |
| load("//internal:common.bzl", "executable_extension") |
| |
| # Change to trigger cache invalidation: 1 |
| |
| def _go_repository_cache_impl(ctx): |
| if ctx.attr.go_sdk_name: |
| go_sdk_name = ctx.attr.go_sdk_name |
| else: |
| host_platform = _detect_host_platform(ctx) |
| matches = [ |
| name |
| for name, platform in ctx.attr.go_sdk_info.items() |
| if host_platform == platform or platform == "host" |
| ] |
| if len(matches) > 1: |
| fail('gazelle found more than one suitable Go SDK ({}). Specify which one to use with gazelle_dependencies(go_sdk = "go_sdk").'.format(", ".join(matches))) |
| if len(matches) == 0: |
| fail('gazelle could not find a Go SDK. Specify which one to use with gazelle_dependencies(go_sdk = "go_sdk").') |
| if len(matches) == 1: |
| go_sdk_name = matches[0] |
| |
| go_sdk_label = Label("@" + go_sdk_name + "//:ROOT") |
| |
| go_root = str(ctx.path(go_sdk_label).dirname) |
| go_path = str(ctx.path(".")) |
| go_cache = str(ctx.path("gocache")) |
| go_mod_cache = "" |
| if ctx.os.environ.get("GO_REPOSITORY_USE_HOST_CACHE", "") == "1": |
| extension = executable_extension(ctx) |
| go_tool = go_root + "/bin/go" + extension |
| go_mod_cache = read_go_env(ctx, go_tool, "GOMODCACHE") |
| go_path = read_go_env(ctx, go_tool, "GOPATH") |
| if not go_mod_cache and not go_path: |
| fail("GOPATH or GOMODCACHE must be set when GO_REPOSITORY_USE_HOST_CACHE is enabled.") |
| go_cache = read_go_env(ctx, go_tool, "GOCACHE") |
| if not go_cache: |
| fail("GOCACHE must be set when GO_REPOSITORY_USE_HOST_CACHE is enabled.") |
| |
| cache_env = { |
| "GOROOT": go_root, |
| "GOCACHE": go_cache, |
| } |
| if go_path: |
| cache_env["GOPATH"] = go_path |
| if go_mod_cache: |
| cache_env["GOMODCACHE"] = go_mod_cache |
| |
| for key, value in ctx.attr.go_env.items(): |
| if key in cache_env: |
| fail("{} cannot be set in go_env".format(key)) |
| cache_env[key] = value |
| env_content = "\n".join(["{k}='{v}'\n".format(k = k, v = v) for k, v in cache_env.items()]) |
| |
| ctx.file("go.env", env_content) |
| ctx.file("BUILD.bazel", 'exports_files(["go.env"])') |
| |
| go_repository_cache = repository_rule( |
| _go_repository_cache_impl, |
| attrs = { |
| "go_sdk_name": attr.string(), |
| "go_sdk_info": attr.string_dict(), |
| "go_env": attr.string_dict(), |
| }, |
| # Don't put anything in environ. If we switch between the host cache |
| # and Bazel's cache, it shouldn't actually invalidate Bazel's cache. |
| ) |
| |
| def read_go_env(ctx, go_tool, var): |
| res = ctx.execute([go_tool, "env", var]) |
| if res.return_code: |
| fail("failed to read go environment: " + res.stderr) |
| return res.stdout.strip() |
| |
| def read_cache_env(ctx, path): |
| contents = ctx.read(path) |
| env = {} |
| lines = contents.split("\n") |
| for line in lines: |
| line = line.strip() |
| if line == "" or line.startswith("#"): |
| continue |
| k, sep, v = line.partition("=") |
| if sep == "": |
| fail("failed to parse cache environment") |
| env[k] = v.strip("'") |
| return env |
| |
| # copied from rules_go. Keep in sync. |
| def _detect_host_platform(ctx): |
| if ctx.os.name == "linux": |
| host = "linux_amd64" |
| res = ctx.execute(["uname", "-p"]) |
| if res.return_code == 0: |
| uname = res.stdout.strip() |
| if uname == "s390x": |
| host = "linux_s390x" |
| elif uname == "i686": |
| host = "linux_386" |
| |
| # uname -p is not working on Aarch64 boards |
| # or for ppc64le on some distros |
| res = ctx.execute(["uname", "-m"]) |
| if res.return_code == 0: |
| uname = res.stdout.strip() |
| if uname == "aarch64": |
| host = "linux_arm64" |
| elif uname == "armv6l": |
| host = "linux_arm" |
| elif uname == "armv7l": |
| host = "linux_arm" |
| elif uname == "ppc64le": |
| host = "linux_ppc64le" |
| |
| # Default to amd64 when uname doesn't return a known value. |
| |
| elif ctx.os.name == "mac os x": |
| host = "darwin_amd64" |
| elif ctx.os.name.startswith("windows"): |
| host = "windows_amd64" |
| elif ctx.os.name == "freebsd": |
| host = "freebsd_amd64" |
| else: |
| fail("Unsupported operating system: " + ctx.os.name) |
| |
| return host |