Hi all,
Sincere apologies for a long post.
I'm very new to bazel and trying to use it to build a golang based project that builds quite a few golang plugins (linkmode="plugin").
I have managed use gazelle to generate the BUILD.bazel files in the entire directory hierarchy and the builds happen correctly - but, ends up producing the final ".so" files deep within this hierarchy.
The app that loads these plugins expects them to be available in a certain directory structure with each plugin having its path encoded as base64 string (don't ask why - I'm not the owner/designer/developer of this app).
Earlier, these plugins were getting built using a serially running bash script and took a lot of time. Bazel helps us parallelise the builds nicely.
I wrote a custom rule to both generate the base64 encoded filename as well as fire the "ln" command to create the link. For some reason, the "ln" command always throws error with "<source-plugin-file>: No such file or directory".
I also printed the subcommand generated for this and when I try to execute the printed subcommand, the same one succeeds perfectly. So, I'm a bit confused as to what am I doing wrong here.
Here is the output from the build:
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗ bazelisk build -s //...
DEBUG: /home/kunal/work/hotstar/hotstar-x-stack/build-systems/bazel/hs-core-widget-binder-query/tools/hotstar/bazel/link_artefacts.bzl:23:10: destination path: binders
DEBUG: /home/kunal/work/hotstar/hotstar-x-stack/build-systems/bazel/hs-core-widget-binder-query/tools/hotstar/bazel/link_artefacts.bzl:30:10: Linking file binders/Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0
INFO: Analyzed 1036 targets (311 packages loaded, 1657 targets configured).
INFO: Found 1036 targets...
SUBCOMMAND: # //:link-something [action 'Linking binder VotingWidgetInstance/VotingWidget..', configuration: 2196e5683698aea1297cc7025e556276264b5abd3954e88e8320391192cc438e, execution platform: @local_config_platform//:host]
(cd /home/kunal/.cache/bazel/_bazel_kunal/cd15c8988ce3af495ee0ee5280a12808/execroot/hs-core-widget-binder-query && \
exec env - \
PATH=/home/kunal/.cache/bazelisk/downloads/bazelbuild/bazel-6.0.0-linux-x86_64/bin:/home/kunal/.nodenv/shims:/home/kunal/.nodenv/bin:/home/kunal/bin:/usr/local/bin:/home/kunal/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:./node_modules/.bin:/home/kunal/.local/bin:/home/kunal/go/bin:/home/kunal/.please/bin \
/bin/bash -c 'ln bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so bazel-out/k8-fastbuild/bin/binders/Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0')
# Configuration: 2196e5683698aea1297cc7025e556276264b5abd3954e88e8320391192cc438e
# Execution platform: @local_config_platform//:host
ERROR: /home/kunal/work/hotstar/hotstar-x-stack/build-systems/bazel/hs-core-widget-binder-query/BUILD.bazel:20:10: Linking binder VotingWidgetInstance/VotingWidget.. failed: (Exit 1): bash failed: error executing command (from target //:link-something) /bin/bash -c 'ln bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so bazel-out/k8-fastbuild/bin/binders/Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0'
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
ln: failed to access 'bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so': No such file or directory
INFO: Elapsed time: 145.057s, Critical Path: 7.00s
INFO: 2 processes: 2 internal.
FAILED: Build did NOT complete successfully
You can see that the mentioned file actually exists:
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗ ls -l "bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so"
-r-xr-xr-x 1 kunal kunal 28M Mar 8 15:53 bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so
Here is the code for the custom rule I wrote:
# some docstring
load("@aspect_bazel_lib//lib:base64.bzl", "base64")
def _link_file_impl(ctx):
src = ctx.attr.src
dep = src[DefaultInfo].files.to_list()[0]
# print("dep = {dep}, rel_path = {rel_path}, path = {path}, dir = {dir}".format(dep=dep,
# path=dep.path,
# rel_path=dep.short_path,
# dir=dep.dirname,
# ))
## Extract sub-path - only the name of the widget/space/page
pieces = dep.short_path.split("/")[1:-3]
artifact_rel_path = "/".join(pieces)
# print("artifact rel path = {artifact_rel_path}".format(artifact_rel_path=artifact_rel_path))
dest_path = ctx.attr.dest_path
artifact_type = ctx.attr.artifact_type
print("destination path: {dest_path}".format(dest_path=dest_path))
dst_b64 = base64.encode(artifact_rel_path)
dst = ctx.actions.declare_file("/".join([dest_path, dst_b64]))
src_path = dep.path
print("Linking file {dst}".format(dst=dst.short_path))
_cmd = "ln {src} {target}".format(src=src_path, target=dst.path)
# print(" --- Executing command: {_cmd}".format(_cmd=_cmd))
ctx.actions.run_shell(
mnemonic = "Link{artifact_type}".format(artifact_type=artifact_type.capitalize()),
progress_message = "Linking {artifact_type} {artifact_rel_path}..".format(artifact_type=artifact_type, artifact_rel_path=artifact_rel_path),
inputs = [],
outputs = [dst],
command = _cmd,
# command = "ln %s %s".format(src_path, dst.path),
# arguments = [src_path, dst.path],
use_default_shell_env = True,
)
return [
DefaultInfo(
files = depset([dst]),
runfiles = ctx.runfiles(files=[dst]),
)
]
_link_file = rule(
implementation = _link_file_impl,
provides = [DefaultInfo],
attrs = {
'src': attr.label(mandatory = True, allow_files = True),
'dest_path': attr.string(mandatory = True),
'artifact_type': attr.string(mandatory = True),
},
)
def link_file(name, src, dest_path, artifact_type, **kwargs):
_link_file(
name = name,
src = src,
dest_path = dest_path,
artifact_type = artifact_type,
**kwargs
)
Just for completion sake, here is what happens when I run the SUBCOMMAND manually:
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗ ls -l bazel-out/k8-fastbuild/bin/binders
total 0
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗ (cd /home/kunal/.cache/bazel/_bazel_kunal/cd15c8988ce3af495ee0ee5280a12808/execroot/hs-core-widget-binder-query && \
exec env - \
PATH=/home/kunal/.cache/bazelisk/downloads/bazelbuild/bazel-6.0.0-linux-x86_64/bin:/home/kunal/.nodenv/shims:/home/kunal/.nodenv/bin:/home/kunal/bin:/usr/local/bin:/home/kunal/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:./node_modules/.bin:/home/kunal/.local/bin:/home/kunal/go/bin:/home/kunal/.please/bin \
/bin/bash -c 'ln bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so bazel-out/k8-fastbuild/bin/binders/Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0')
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗ ls -l bazel-out/k8-fastbuild/bin/binders
total 28M
-r-xr-xr-x 2 kunal kunal 28M Mar 8 15:53 Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗
As you can see, the first "ls -l ..." output shows the binders/ as empty directory and the same "ls -l ..." command shows the hard-linked file with base64 encoded filename.
In fact, here you can also see that their inode nos. match - indicating the successful hard-link:
➜ kunal@hydrogen hs-core-widget-binder-query git:(feature/bazel/stage-1) ✗ ls -il "bazel-out/k8-fastbuild/bin/binders/Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0" "bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so"
95842297 -r-xr-xr-x 2 kunal kunal 29139855 Mar 8 15:53 bazel-out/k8-fastbuild/bin/binders/Vm90aW5nV2lkZ2V0SW5zdGFuY2UvVm90aW5nV2lkZ2V0
95842297 -r-xr-xr-x 2 kunal kunal 29139855 Mar 8 15:53 bazel-out/k8-fastbuild/bin/widgets/VotingWidgetInstance/VotingWidget/binder/binder_/binder.so
Please help me understand where am I going wrong.
TIA,
Kunal