From e3deb49b65ad8d7ec6cbc54b7ff511a537f8de56 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Tue, 29 Aug 2023 11:23:26 +0200 Subject: [PATCH] Improve Gazelle launcher's runfiles discovery on Windows (#1604) The Bash runfiles library consumes paths of the form `repo/path/to/pkg/file` and is more reliable than the custom runfiles discovery function. Co-authored-by: Shashank --- def.bzl | 15 +++++++++----- internal/gazelle.bash.in | 45 +++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/def.bzl b/def.bzl index a9c389b76..d07ae6c70 100644 --- a/def.bzl +++ b/def.bzl @@ -63,6 +63,12 @@ def _valid_env_variable_name(name): return False return True +def _rlocation_path(ctx, file): + if file.short_path.startswith("../"): + return file.short_path[3:] + else: + return ctx.workspace_name + "/" + file.short_path + def _gazelle_runner_impl(ctx): args = [ctx.attr.command] if ctx.attr.mode: @@ -88,16 +94,14 @@ def _gazelle_runner_impl(ctx): repo_config = ctx.file._repo_config substitutions = { "@@ARGS@@": shell.array_literal(args), - "@@GAZELLE_LABEL@@": shell.quote(str(ctx.attr.gazelle.label)), - "@@GAZELLE_SHORT_PATH@@": shell.quote(ctx.executable.gazelle.short_path), + "@@GAZELLE_PATH@@": shell.quote(_rlocation_path(ctx, ctx.executable.gazelle)), "@@GENERATED_MESSAGE@@": """ # Generated by {label} # DO NOT EDIT """.format(label = str(ctx.label)), - "@@RUNNER_LABEL@@": shell.quote(str(ctx.label)), - "@@GOTOOL@@": shell.quote(go_tool.short_path), + "@@GOTOOL@@": shell.quote(_rlocation_path(ctx, go_tool)), "@@ENV@@": env, - "@@REPO_CONFIG_SHORT_PATH@@": shell.quote(repo_config.short_path) if repo_config else "", + "@@REPO_CONFIG_PATH@@": shell.quote(_rlocation_path(ctx, repo_config)) if repo_config else "", } ctx.actions.expand_template( template = ctx.file._template, @@ -186,5 +190,6 @@ def gazelle(name, **kwargs): srcs = [runner_name], tags = tags, visibility = visibility, + deps = ["@bazel_tools//tools/bash/runfiles"], data = kwargs["data"] if "data" in kwargs else [], ) diff --git a/internal/gazelle.bash.in b/internal/gazelle.bash.in index d309ba9ce..8fd23add4 100644 --- a/internal/gazelle.bash.in +++ b/internal/gazelle.bash.in @@ -14,41 +14,34 @@ # See the License for the specific language governing permissions and # limitations under the License. +# --- begin runfiles.bash initialization v3 --- +# Copy-pasted from the Bazel Bash runfiles library v3. +set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e +# --- end runfiles.bash initialization v3 --- + @@GENERATED_MESSAGE@@ set -euo pipefail -RUNNER_LABEL=@@RUNNER_LABEL@@ -GAZELLE_SHORT_PATH=@@GAZELLE_SHORT_PATH@@ -GAZELLE_LABEL=@@GAZELLE_LABEL@@ +GAZELLE_PATH=@@GAZELLE_PATH@@ ARGS=@@ARGS@@ GOTOOL=@@GOTOOL@@ -REPO_CONFIG_SHORT_PATH=@@REPO_CONFIG_SHORT_PATH@@ +REPO_CONFIG_PATH=@@REPO_CONFIG_PATH@@ @@ENV@@ -# find_runfile prints the location of a runfile in the source workspace, -# either by reading the symbolic link or reading the runfiles manifest. -function find_runfile { - local runfile=$1 - if [ -f "$runfile" ]; then - readlink "$runfile" - return - fi - runfile=${runfile#external/} - if grep -q "^$runfile" "$0.runfiles_manifest"; then - grep "^$runfile" "$0.runfiles_manifest" | head -n 1 | cut -d' ' -f2 - return - fi - # printing nothing indicates failure -} - # set_goroot attempts to set GOROOT to the SDK used by rules_go. gazelle # invokes tools inside the Go SDK for dependency management. It's good to # use the SDK used by the workspace in case the Go SDK is not installed # on the host system or is a different version. function set_goroot { - local gotool=$(find_runfile "$GOTOOL") + local gotool=$(rlocation "$GOTOOL") if [ -z "$gotool" ]; then echo "$0: warning: could not locate GOROOT used by rules_go" >&2 return @@ -76,8 +69,8 @@ esac # able to find runfiles, and some extensions rely on that. Gazelle can use # BUILD_WORKSPACE_DIRECTORY to interpret relative paths on the command line. set_goroot -gazelle_short_path=$(find_runfile "$GAZELLE_SHORT_PATH") -if [ -z "$gazelle_short_path" ]; then +gazelle_path=$(rlocation "$GAZELLE_PATH") +if [ -z "$gazelle_path" ]; then echo "error: could not locate gazelle binary" >&2 exit 1 fi @@ -101,8 +94,8 @@ fi # When running with Bzlmod, there is no WORKSPACE file for Gazelle to read # the definitions of go_repository rules from. Instead, we pass the path to # the repo config file as a flag. -if [[ "${is_fix_or_update:-}" == "true" ]] && [[ -n $REPO_CONFIG_SHORT_PATH ]]; then - ARGS=("${ARGS[0]}" "-repo_config" "$(find_runfile "$REPO_CONFIG_SHORT_PATH")" "${ARGS[@]:1}") +if [[ "${is_fix_or_update:-}" == "true" ]] && [[ -n $REPO_CONFIG_PATH ]]; then + ARGS=("${ARGS[0]}" "-repo_config" "$(rlocation "$REPO_CONFIG_PATH")" "${ARGS[@]:1}") fi -"$gazelle_short_path" "${ARGS[@]}" +"$gazelle_path" "${ARGS[@]}"