github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/internal/go_repository_cache.bzl (about) 1 # Copyright 2019 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 15 load("//internal:common.bzl", "executable_extension") 16 17 # Change to trigger cache invalidation: 1 18 19 def _go_repository_cache_impl(ctx): 20 if ctx.attr.go_sdk_name: 21 go_sdk_name = ctx.attr.go_sdk_name 22 else: 23 host_platform = _detect_host_platform(ctx) 24 matches = [ 25 name 26 for name, platform in ctx.attr.go_sdk_info.items() 27 if host_platform == platform or platform == "host" 28 ] 29 if len(matches) > 1: 30 fail('gazelle found more than one suitable Go SDK ({}). Specify which one to use with gazelle_dependencies(go_sdk = "go_sdk").'.format(", ".join(matches))) 31 if len(matches) == 0: 32 fail('gazelle could not find a Go SDK. Specify which one to use with gazelle_dependencies(go_sdk = "go_sdk").') 33 if len(matches) == 1: 34 go_sdk_name = matches[0] 35 36 go_sdk_label = Label("@" + go_sdk_name + "//:ROOT") 37 38 go_root = str(ctx.path(go_sdk_label).dirname) 39 go_path = str(ctx.path(".")) 40 go_cache = str(ctx.path("gocache")) 41 go_mod_cache = "" 42 if ctx.os.environ.get("GO_REPOSITORY_USE_HOST_MODCACHE", "") == "1": 43 extension = executable_extension(ctx) 44 go_tool = go_root + "/bin/go" + extension 45 go_mod_cache = read_go_env(ctx, go_tool, "GOMODCACHE") 46 if not go_mod_cache: 47 fail("GOMODCACHE must be set when GO_REPOSITORY_USE_HOST_MODCACHE is enabled.") 48 if ctx.os.environ.get("GO_REPOSITORY_USE_HOST_CACHE", "") == "1": 49 extension = executable_extension(ctx) 50 go_tool = go_root + "/bin/go" + extension 51 go_mod_cache = read_go_env(ctx, go_tool, "GOMODCACHE") 52 go_path = read_go_env(ctx, go_tool, "GOPATH") 53 if not go_mod_cache and not go_path: 54 fail("GOPATH or GOMODCACHE must be set when GO_REPOSITORY_USE_HOST_CACHE is enabled.") 55 go_cache = read_go_env(ctx, go_tool, "GOCACHE") 56 if not go_cache: 57 fail("GOCACHE must be set when GO_REPOSITORY_USE_HOST_CACHE is enabled.") 58 59 cache_env = { 60 "GOROOT": go_root, 61 "GOCACHE": go_cache, 62 } 63 if go_path: 64 cache_env["GOPATH"] = go_path 65 if go_mod_cache: 66 cache_env["GOMODCACHE"] = go_mod_cache 67 68 for key, value in ctx.attr.go_env.items(): 69 if key in cache_env: 70 fail("{} cannot be set in go_env".format(key)) 71 cache_env[key] = value 72 env_content = "\n".join(["{k}='{v}'\n".format(k = k, v = v) for k, v in cache_env.items()]) 73 74 ctx.file("go.env", env_content) 75 ctx.file("BUILD.bazel", 'exports_files(["go.env"])') 76 77 go_repository_cache = repository_rule( 78 _go_repository_cache_impl, 79 attrs = { 80 "go_sdk_name": attr.string(), 81 "go_sdk_info": attr.string_dict(), 82 "go_env": attr.string_dict(), 83 }, 84 # Don't put anything in environ. If we switch between the host cache 85 # and Bazel's cache, it shouldn't actually invalidate Bazel's cache. 86 ) 87 88 def read_go_env(ctx, go_tool, var): 89 res = ctx.execute([go_tool, "env", var]) 90 if res.return_code: 91 fail("failed to read go environment: " + res.stderr) 92 return res.stdout.strip() 93 94 def read_cache_env(ctx, path): 95 contents = ctx.read(path) 96 env = {} 97 lines = contents.split("\n") 98 for line in lines: 99 line = line.strip() 100 if line == "" or line.startswith("#"): 101 continue 102 k, sep, v = line.partition("=") 103 if sep == "": 104 fail("failed to parse cache environment") 105 env[k] = v.strip("'") 106 return env 107 108 # copied from rules_go. Keep in sync. 109 def _detect_host_platform(ctx): 110 if ctx.os.name == "linux": 111 host = "linux_amd64" 112 res = ctx.execute(["uname", "-p"]) 113 if res.return_code == 0: 114 uname = res.stdout.strip() 115 if uname == "s390x": 116 host = "linux_s390x" 117 elif uname == "i686": 118 host = "linux_386" 119 120 # uname -p is not working on Aarch64 boards 121 # or for ppc64le on some distros 122 res = ctx.execute(["uname", "-m"]) 123 if res.return_code == 0: 124 uname = res.stdout.strip() 125 if uname == "aarch64": 126 host = "linux_arm64" 127 elif uname == "armv6l": 128 host = "linux_arm" 129 elif uname == "armv7l": 130 host = "linux_arm" 131 elif uname == "ppc64le": 132 host = "linux_ppc64le" 133 134 # Default to amd64 when uname doesn't return a known value. 135 136 elif ctx.os.name == "mac os x": 137 host = "darwin_amd64" 138 elif ctx.os.name.startswith("windows"): 139 host = "windows_amd64" 140 elif ctx.os.name == "freebsd": 141 host = "freebsd_amd64" 142 else: 143 fail("Unsupported operating system: " + ctx.os.name) 144 145 return host