From 76047a3569817ee1da3085159016dd796764164f Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Mon, 2 Oct 2023 03:07:27 -0700 Subject: [PATCH] chore(rules): use bzlmod (#320) Requires fixing up the brittle runfiles logic in one example, since bzlmod changes the repository names and requires a proper runfiles helper library. /cc @fmeum --- rules/.bazelrc | 1 + rules/.bazelversion | 1 + rules/MODULE.bazel | 4 ++++ rules/WORKSPACE | 35 +--------------------------- rules/runfiles/complex_tool.bzl | 41 ++++++++++++++++++++++----------- 5 files changed, 34 insertions(+), 48 deletions(-) create mode 100644 rules/.bazelrc create mode 100644 rules/.bazelversion create mode 100644 rules/MODULE.bazel diff --git a/rules/.bazelrc b/rules/.bazelrc new file mode 100644 index 000000000..3ce91d272 --- /dev/null +++ b/rules/.bazelrc @@ -0,0 +1 @@ +common --enable_bzlmod diff --git a/rules/.bazelversion b/rules/.bazelversion new file mode 100644 index 000000000..91e4a9f26 --- /dev/null +++ b/rules/.bazelversion @@ -0,0 +1 @@ +6.3.2 diff --git a/rules/MODULE.bazel b/rules/MODULE.bazel new file mode 100644 index 000000000..18dd2e2bb --- /dev/null +++ b/rules/MODULE.bazel @@ -0,0 +1,4 @@ +"Bazel dependencies, see https://registry.bazel.build" + +bazel_dep(name = "bazel_skylib", version = "1.4.2") +bazel_dep(name = "rules_python", version = "0.25.0") diff --git a/rules/WORKSPACE b/rules/WORKSPACE index a8700fc3e..37b7eacd8 100644 --- a/rules/WORKSPACE +++ b/rules/WORKSPACE @@ -1,34 +1 @@ -workspace(name = "examples") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "rules_python", - sha256 = "aa96a691d3a8177f3215b14b0edc9641787abaaa30363a080165d06ab65e1161", - url = "https://github.com/bazelbuild/rules_python/releases/download/0.0.1/rules_python-0.0.1.tar.gz", -) - -load("@rules_python//python:repositories.bzl", "py_repositories") - -py_repositories() - -# Only needed if using the packaging rules. -load("@rules_python//python:pip.bzl", "pip_repositories") - -pip_repositories() - -# Load Skylib 0.9.0 as instructed at -# https://github.com/bazelbuild/bazel-skylib/releases/tag/1.0.2 - -http_archive( - name = "bazel_skylib", - sha256 = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz", - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz", - ], -) - -load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") - -bazel_skylib_workspace() +# Marker that this folder is the root of the Bazel workspace diff --git a/rules/runfiles/complex_tool.bzl b/rules/runfiles/complex_tool.bzl index ace76096f..8fb138020 100644 --- a/rules/runfiles/complex_tool.bzl +++ b/rules/runfiles/complex_tool.bzl @@ -3,17 +3,27 @@ A tool (executable used for action registration) may depend on another tool with its own runfiles. This example demonstrates this scenario.""" +# Bash helper function for looking up runfiles. +# Vendored from +# https://github.com/bazelbuild/bazel/blob/master/tools/bash/runfiles/runfiles.bash +BASH_RLOCATION_FUNCTION = r"""\ +# --- begin runfiles.bash initialization 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 --- +""" + def _sub_tool_impl(ctx): # Since this tool may be used by another tool, it must support accepting - # a different runfiles directory root. The runfiles directory is always - # adjacent to the *root* tool being run, which may not be this tool. - # (In this case, this is done by environment variable RUNFILES_DIR.) - command = """ -if [[ -z "${RUNFILES_DIR}" ]]; then - RUNFILES_DIR=${0}.runfiles -fi + # a different runfiles directory root. The runfiles helper library does this correctly. + command = BASH_RLOCATION_FUNCTION + """ -cat ${RUNFILES_DIR}/examples/runfiles/data.txt > $1""" +cat $(rlocation examples/runfiles/data.txt) > $1""" # Using root_symlinks or symlinks for a tool is very brittle if the # tool may be used by another tool; there will be a collision when merging @@ -43,7 +53,7 @@ sub_tool = rule( ) def _complex_tool_impl(ctx): - my_runfiles = ctx.runfiles(files = [ctx.files._data[0]]) + my_runfiles = ctx.runfiles(files = [ctx.files._data[0], ctx.files._runfiles_lib[0]]) # Use runfiles.merge to merge the runfiles of both tools. All runfiles will # be rooted under the runfiles directory owned by this rule, however. @@ -60,11 +70,10 @@ def _complex_tool_impl(ctx): runfiles_relative_tool_path = ctx.workspace_name + "/" + ctx.attr._subtool[DefaultInfo].files_to_run.executable.short_path - # This tool forwards its runfiles directory via the RUNFILES_DIR to the - # subtool, otherwise the subtool would be looking to $0.runfiles, which does - # not exist. - command = ("#!/bin/bash\nexport RUNFILES_DIR=\"$0.runfiles\" && " + - "${RUNFILES_DIR}/%s $1 && cat ${RUNFILES_DIR}/examples/%s >> $1") % ( + # This tool expects that the subtool will correctly resolve its runfiles. + command = ("#!/bin/bash\n{}" + + "$(rlocation {}) $1 && cat $(rlocation examples/{}) >> $1").format( + BASH_RLOCATION_FUNCTION, runfiles_relative_tool_path, ctx.files._data[0].short_path, ) @@ -92,5 +101,9 @@ complex_tool = rule( allow_files = True, default = ":complex_tool_data.txt", ), + "_runfiles_lib": attr.label( + allow_single_file = True, + default = "@bazel_tools//tools/bash/runfiles", + ), }, )