diff --git a/tool/gocross/gocross-wrapper.sh b/tool/gocross/gocross-wrapper.sh index 1bfd67092..6817b6e4e 100755 --- a/tool/gocross/gocross-wrapper.sh +++ b/tool/gocross/gocross-wrapper.sh @@ -26,40 +26,29 @@ repo_root="${BASH_SOURCE%/*}/../.." # being invoked from somewhere else. cd "$repo_root" -toolchain="$HOME/.cache/tailscale-go" +# toolchain, set below, is the root of the Go toolchain we'll use to build +# gocross. +# +# It's set to either an explicit Go toolchain directory (if go.toolchain.rev has +# a value with a leading slash, for testing new toolchains), or otherwise in the +# common case it'll be "$HOME/.cache/tsgo/GITHASH" where GITHASH is the contents +# of the go.toolchain.rev file and the git commit of the +# https://github.com/tailscale/go release artifact to download. +toolchain="" -if [[ -d "$toolchain" ]]; then - # A toolchain exists, but is it recent enough to compile gocross? If not, - # wipe it out so that the next if block fetches a usable one. - want_go_minor=$(grep -E '^go ' "go.mod" | cut -f2 -d'.') - have_go_minor="" - if [[ -f "$toolchain/VERSION" ]]; then - have_go_minor=$(head -1 "$toolchain/VERSION" | cut -f2 -d'.') - fi - # Shortly before stable releases, we run release candidate - # toolchains, which have a non-numeric suffix on the version - # number. Remove the rc qualifier, we just care about the minor - # version. - have_go_minor="${have_go_minor%rc*}" - if [[ -z "$have_go_minor" || "$have_go_minor" -lt "$want_go_minor" ]]; then +read -r REV &2 - case "$REV" in - /*) - toolchain="$REV" - ;; - *) # This works for linux and darwin, which is sufficient # (we do not build tailscale-go for other targets). HOST_OS=$(uname -s | tr A-Z a-z) @@ -71,15 +60,38 @@ if [[ ! -d "$toolchain" ]]; then # Go uses the name "amd64". HOST_ARCH="amd64" fi - - rm -rf "$toolchain" "$toolchain.extracted" curl -f -L -o "$toolchain.tar.gz" "https://github.com/tailscale/go/releases/download/build-${REV}/${HOST_OS}-${HOST_ARCH}.tar.gz" mkdir -p "$toolchain" (cd "$toolchain" && tar --strip-components=1 -xf "$toolchain.tar.gz") echo "$REV" >"$toolchain.extracted" rm -f "$toolchain.tar.gz" - ;; - esac + + # Do some cleanup of old toolchains while we're here. + for hash in $(find "$HOME/.cache/tsgo" -type f -maxdepth 1 -name '*.extracted' -mtime 90 -exec basename {} \; | sed 's/.extracted$//'); do + echo "# Cleaning up old Go toolchain $hash" >&2 + rm -rf "$HOME/.cache/tsgo/$hash" + rm -rf "$HOME/.cache/tsgo/$hash.extracted" + done + fi + ;; +esac + +if [[ -d "$toolchain" ]]; then + # A toolchain exists, but is it recent enough to compile gocross? If not, + # wipe it out so that the next if block fetches a usable one. + want_go_minor="$(grep -E '^go ' "go.mod" | cut -f2 -d'.')" + have_go_minor="" + if [[ -f "$toolchain/VERSION" ]]; then + have_go_minor="$(head -1 "$toolchain/VERSION" | cut -f2 -d'.')" + fi + # Shortly before stable releases, we run release candidate + # toolchains, which have a non-numeric suffix on the version + # number. Remove the rc qualifier, we just care about the minor + # version. + have_go_minor="${have_go_minor%rc*}" + if [[ -z "$have_go_minor" || "$have_go_minor" -lt "$want_go_minor" ]]; then + rm -rf "$toolchain" "$toolchain.extracted" + fi fi # Binaries run with `gocross run` can reinvoke gocross, resulting in a diff --git a/tool/gocross/toolchain.go b/tool/gocross/toolchain.go index 5980dff04..e701662f5 100644 --- a/tool/gocross/toolchain.go +++ b/tool/gocross/toolchain.go @@ -55,8 +55,13 @@ func readRevFile(path string) (string, error) { } func getToolchain() (toolchainDir, gorootDir string, err error) { + rev, err := toolchainRev() + if err != nil { + return "", "", err + } + cache := filepath.Join(os.Getenv("HOME"), ".cache") - toolchainDir = filepath.Join(cache, "tailscale-go") + toolchainDir = filepath.Join(cache, "tsgo", rev) gorootDir = filepath.Join(toolchainDir, "gocross-goroot") // You might wonder why getting the toolchain also provisions and returns a