mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 15:31:48 +00:00
Currently, we provide single-file tools such as `ctags`, `gsutil` etc via an `sh_binary` wrapper, to have a single target to reference that automatically does platform selection of the underlying tool. Due to some [unfortunate reason](https://github.com/bazelbuild/bazel/issues/11820), the underlying srcs (which is [a single file](https://bazel.build/reference/be/shell#sh_binary.srcs)) of an `sh_binary` are also exposed as outputs (rather than just as typical runfiles) alongside the script that wraps. This is _sometimes_ problematic when doing location expansion (e.g. `$(location ...)`) due to these only allowing a single output (dont ask why this works in some contexts but not others, I dont know). To address this, we create a wrapper macro + rule to replicate what we want from `sh_binary` (automatic platform selection + tool naming), while only exposing a singular file. See example of currently required approach to consuming a tool: [BUILD.bazel](https://github.com/sourcegraph/sourcegraph/pull/62801/files#diff-e2a562c2e13908933b2ee24f0ac596829b38a5325cc69a4aee05c383aaa2e494R8) & [main_test.go](https://github.com/sourcegraph/sourcegraph/pull/62801/files#diff-7a91cb5143064bfc8993ef97baf68b718ef49747ccc1d3c5e1150d4696b88305R66). With this change, `rlocationpath` (singular) can be used instead (or any of the other singular nouns in different contexts), as well as no `strings.Split/strings.Fields` being required ## Test plan `bazel cquery --output=files //dev/tools:dropdb` yields 1 vs 2 files. Also updated the rule behind `//internal/database:generate_schemas` due to the workaround in it for the fact that the underlying srcs was also exposed. The correctness is verified by running said target (locally + CI)
48 lines
1.9 KiB
Python
48 lines
1.9 KiB
Python
load("@aspect_bazel_lib//lib:output_files.bzl", "make_output_files")
|
|
|
|
# Convenience wrapper for rules that provide a single executable (binary/script/etc) that
|
|
# we want to rename. For example, files produced by http_file have the name `downloaded`,
|
|
# we may want to rename them with sh_binary, however this has a weird quirk whereby both
|
|
# the sh_binary wrapper "script" and the input binary/script itself are included in the outputs.
|
|
# This results in some less ergonomic usage when trying to use them in e.g. go tests, having to
|
|
# use $(rlocationpaths ...) and then filepath.Dir(runfiles.Rlocation(strings.Split(..., " ")[0])) in
|
|
# order to get the path.
|
|
# With this macro, its slightly simplified by being able to use $(rlocationpath ...) (singular) and
|
|
# not having to strings.Split(..., " ") as a result.
|
|
# See more: https://github.com/bazelbuild/bazel/issues/11820
|
|
def tool(name, src, visibility = ["//visibility:public"]):
|
|
native.sh_binary(
|
|
name = name + "_sh",
|
|
srcs = src,
|
|
)
|
|
make_bin_and_deps_available(
|
|
name = name,
|
|
out = name,
|
|
data = make_output_files(
|
|
name = name + "_out",
|
|
target = name + "_sh",
|
|
paths = [native.package_name() + "/" + name + "_sh"],
|
|
),
|
|
visibility = visibility,
|
|
)
|
|
|
|
def _make_bin_and_deps_available_impl(ctx):
|
|
symlink = ctx.actions.declare_file(ctx.attr.out)
|
|
ctx.actions.symlink(output = symlink, target_file = ctx.file.data)
|
|
return [
|
|
DefaultInfo(
|
|
executable = symlink,
|
|
files = depset(direct = [symlink]),
|
|
runfiles = ctx.runfiles(files = ctx.files.data),
|
|
),
|
|
]
|
|
|
|
make_bin_and_deps_available = rule(
|
|
_make_bin_and_deps_available_impl,
|
|
executable = True,
|
|
attrs = {
|
|
"out": attr.string(mandatory = True),
|
|
"data": attr.label(mandatory = True, allow_single_file = True),
|
|
},
|
|
)
|