Skip to content

Commit

Permalink
Use runfiles wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
fmeum committed Dec 5, 2024
1 parent 057800a commit 2e5ed5e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 9 deletions.
3 changes: 1 addition & 2 deletions sh/private/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ def mk_template_variable_info(name, sh_binaries_info):
},
))

def mk_default_info_with_files_to_run(ctx, name, files, runfiles):
def mk_default_info_with_files_to_run(ctx, executable, files, runfiles):
# Create a dummy executable to trigger the generation of a FilesToRun
# provider which can be used in custom rules depending on this bundle to
# input the needed runfiles into build actions.
# This is a workaround for https://github.com/bazelbuild/bazel/issues/15486
executable = ctx.actions.declare_file(name)
ctx.actions.write(executable, "", is_executable = True)
return DefaultInfo(
executable = executable,
Expand Down
54 changes: 47 additions & 7 deletions sh/sh.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,33 @@ ShBinariesInfo = provider(

_WINDOWS_EXE_EXTENSIONS = [".exe", ".cmd", ".bat", ".ps1"]

def _sh_binaries_from_srcs(ctx, srcs, is_windows):
_POSIX_WRAPPER_TEMPLATE = """\
#!/bin/sh
if [[ -f "{main_executable}.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="{main_executable}.runfiles_manifest"
elif [[ -d "{main_executable}.runfiles" ]]; then
export RUNFILES_DIR="{main_executable}.runfiles"
else
echo "ERROR: Runfiles not found for bundle {main_executable}" >&2
exit 1
fi
exec "{original_executable}" "$@"
"""

_WINDOWS_WRAPPER_TEMPLATE = """\
@echo off
if exist "{main_executable}.runfiles_manifest" (
set RUNFILES_MANIFEST_FILE={main_executable}.runfiles_manifest
) else if exist "{main_executable}.runfiles" (
set RUNFILES_DIR={main_executable}.runfiles
) else (
echo ERROR: Runfiles not found for bundle {main_executable} >&2
exit /b 1
)
"{original_executable}" %*
"""

def _sh_binaries_from_srcs(ctx, srcs, is_windows, main_executable):
executable_files = []
runfiles = ctx.runfiles()
executables_dict = dict()
Expand All @@ -27,10 +53,10 @@ def _sh_binaries_from_srcs(ctx, srcs, is_windows):
if src[DefaultInfo].files_to_run == None or src[DefaultInfo].files_to_run.executable == None:
fail("srcs must be executable, but '{}' is not.".format(src.label))

executable = src[DefaultInfo].files_to_run.executable
name = executable.basename
original_executable = src[DefaultInfo].files_to_run.executable
name = original_executable.basename
if is_windows:
(noext, ext) = paths.split_extension(executable.basename)
(noext, ext) = paths.split_extension(original_executable.basename)
if ext in _WINDOWS_EXE_EXTENSIONS:
name = noext

Expand All @@ -41,8 +67,21 @@ def _sh_binaries_from_srcs(ctx, srcs, is_windows):
src.label,
))

if src[DefaultInfo].default_runfiles:
executable = ctx.actions.declare_file(ctx.label.name + ".path/" + (name + ".bat" if is_windows else name))
ctx.actions.write(
executable,
(_WINDOWS_WRAPPER_TEMPLATE if is_windows else _POSIX_WRAPPER_TEMPLATE).format(
main_executable = main_executable.path,
original_executable = original_executable.path,
),
is_executable = True,
)
executable_files.append(original_executable)
runfiles = runfiles.merge(src[DefaultInfo].default_runfiles)
else:
executable = original_executable
executable_files.append(executable)
runfiles = runfiles.merge(src[DefaultInfo].default_runfiles)
executables_dict[name] = executable
executable_paths.append(executable.dirname)

Expand Down Expand Up @@ -101,15 +140,16 @@ def _mk_sh_binaries_info(direct, transitive):

def _sh_binaries_impl(ctx):
is_windows = ctx.attr._is_windows[ConstantInfo].value
direct = _sh_binaries_from_srcs(ctx, ctx.attr.srcs, is_windows)
executable = ctx.actions.declare_file(ctx.label.name)
direct = _sh_binaries_from_srcs(ctx, ctx.attr.srcs, is_windows, executable)
transitive = _sh_binaries_from_deps(ctx, ctx.attr.deps)
data_runfiles = _runfiles_from_data(ctx, ctx.attr.data)

sh_binaries_info = _mk_sh_binaries_info(direct, transitive)
template_variable_info = mk_template_variable_info(ctx.label.name, sh_binaries_info)
default_info = mk_default_info_with_files_to_run(
ctx,
ctx.label.name,
executable,
depset(direct = direct.executable_files, transitive = transitive.executable_files),
direct.runfiles.merge(transitive.runfiles).merge(data_runfiles),
)
Expand Down

0 comments on commit 2e5ed5e

Please sign in to comment.