Skip to content

Commit

Permalink
rb_binary: include only wrapper script in default outputs
Browse files Browse the repository at this point in the history
without this, it is not possible to reliably locate (via runfiles
library or make variables) the executable output of a rb_binary target
from another target using it as a data dependency, e.g. a shell script.
adds an example of such a case to the 'gem' example workspace.

additionally try to avoid converting depsets to lists when possible
  • Loading branch information
pjjw committed Jan 25, 2025
1 parent 5462524 commit c37d53f
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 10 deletions.
29 changes: 29 additions & 0 deletions examples/gem/BUILD
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template")
load("@aspect_bazel_lib//lib:paths.bzl", "BASH_RLOCATION_FUNCTION")


load(
"@rules_ruby//ruby:defs.bzl",
"rb_binary",
Expand All @@ -9,6 +13,31 @@ load(

package(default_visibility = ["//:__subpackages__"])

expand_template(
name = "shell_wrapper",
template = "wrapper.tpl.sh",
out = "wrapper.sh",
substitutions = {
"@@rlocation_lib@@": BASH_RLOCATION_FUNCTION.replace("$", "$$"),
"@@rake_binary@@": "$(rlocationpaths :rake)",
"@@rakefile@@": "$(rlocationpaths :Rakefile)",
},
data = [
":rake",
":Rakefile",
],
)

sh_test(
name = "shell_wrapper_test",
srcs = [":shell_wrapper"],
deps = ["@bazel_tools//tools/bash/runfiles"],
data = [
":rake",
":Rakefile",
]
)

rb_binary(
name = "rake",
main = "@bundle//bin:rake",
Expand Down
1 change: 1 addition & 0 deletions examples/gem/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"Bazel dependencies"

bazel_dep(name = "bazel_skylib", version = "1.5.0", dev_dependency = True)
bazel_dep(name = "aspect_bazel_lib", version = "2.11.0", dev_dependency = True)
bazel_dep(name = "rules_ruby", version = "0.0.0", dev_dependency = True)
local_path_override(
module_name = "rules_ruby",
Expand Down
4 changes: 4 additions & 0 deletions examples/gem/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
desc "say goodnight to bash"
task "goodnight" do
puts "exit 0"
end
20 changes: 20 additions & 0 deletions examples/gem/wrapper.tpl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bash

@@rlocation_lib@@

set -euo pipefail

rake_binary_expansion=(@@rake_binary@@)

echo "calling the rake binary"
rake="$(rlocation @@rake_binary@@)"
rakefile="$(rlocation @@rakefile@@)"
"$rake" -f "$rakefile" goodnight
set -x
eval "$("$rake" -f "$rakefile" goodnight)"
set +x

echo "rake failed to fail"
echo "rlocationpaths for rake binary:"
printf ' %s\n' "${rake_binary_expansion[@]}"
exit 1
22 changes: 12 additions & 10 deletions ruby/private/binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,14 @@ def generate_rb_binary_script(ctx, binary, bundler = False, args = [], env = {},
# buildifier: disable=function-docstring
def rb_binary_impl(ctx):
bundler = False
bundler_srcs = []
env = {}
java_bin = ""

# TODO: avoid expanding the depset to a list, it may be expensive in a large graph
transitive_data = get_transitive_data(ctx.files.data, ctx.attr.deps).to_list()
transitive_deps = get_transitive_deps(ctx.attr.deps).to_list()
transitive_srcs = get_transitive_srcs(ctx.files.srcs, ctx.attr.deps).to_list()
transitive_data = get_transitive_data(ctx.files.data, ctx.attr.deps)
transitive_deps = get_transitive_deps(ctx.attr.deps)
transitive_srcs = get_transitive_srcs(ctx.files.srcs, ctx.attr.deps)

ruby_toolchain = ctx.toolchains["@rules_ruby//ruby:toolchain_type"]
if ctx.attr.ruby != None:
Expand All @@ -148,28 +149,30 @@ def rb_binary_impl(ctx):
tools.extend(java_toolchain.java_runtime.files.to_list())
java_bin = java_toolchain.java_runtime.java_executable_runfiles_path[3:]

for dep in transitive_deps:
for dep in transitive_deps.to_list():
# TODO: Remove workspace name check together with `rb_bundle()`
if dep.label.workspace_name.endswith("bundle"):
bundler = True

if BundlerInfo in dep:
info = dep[BundlerInfo]
transitive_srcs.extend([info.gemfile, info.bin, info.path])
bundler_srcs.extend([info.gemfile, info.bin, info.path])
bundler = True

# See https://bundler.io/v2.5/man/bundle-config.1.html for confiugration keys.
env.update({
"BUNDLE_GEMFILE": _to_rlocation_path(info.gemfile),
"BUNDLE_PATH": _to_rlocation_path(info.path),
})
if len(bundler_srcs) > 0:
transitive_srcs = depset(bundler_srcs, transitive=[transitive_srcs])

bundle_env = get_bundle_env(ctx.attr.env, ctx.attr.deps)
env.update(bundle_env)
env.update(ruby_toolchain.env)
env.update(ctx.attr.env)

runfiles = ctx.runfiles(transitive_srcs + transitive_data + tools)
runfiles = ctx.runfiles(tools, transitive_files=depset(transitive=[transitive_srcs, transitive_data]))
runfiles = get_transitive_runfiles(runfiles, ctx.attr.srcs, ctx.attr.deps, ctx.attr.data)

# Propagate executable from source rb_binary() targets.
Expand All @@ -188,14 +191,13 @@ def rb_binary_impl(ctx):
return [
DefaultInfo(
executable = script,
files = depset(transitive_srcs + transitive_data + tools),
runfiles = runfiles,
),
RubyFilesInfo(
binary = executable,
transitive_data = depset(transitive_data + tools),
transitive_deps = depset(transitive_deps),
transitive_srcs = depset(transitive_srcs),
transitive_data = depset(tools, transitive=[transitive_data]),
transitive_deps = transitive_deps,
transitive_srcs = transitive_srcs,
bundle_env = bundle_env,
),
RunEnvironmentInfo(
Expand Down

0 comments on commit c37d53f

Please sign in to comment.