174 lines
4.7 KiB
Python
174 lines
4.7 KiB
Python
"""Shared launcher spec and OS-native wrapper helpers for runtime rules."""
|
|
|
|
_RUNTIME_LAUNCHER = Label("//internal:runtime_launcher.js")
|
|
_WINDOWS_CONSTRAINT = Label("@platforms//os:windows")
|
|
|
|
_POSIX_WRAPPER_TEMPLATE = """#!/bin/sh
|
|
set -eu
|
|
|
|
self="$0"
|
|
runfiles_dir="${RUNFILES_DIR:-}"
|
|
manifest="${RUNFILES_MANIFEST_FILE:-}"
|
|
|
|
if [ -n "${runfiles_dir}" ] && [ -d "${runfiles_dir}" ]; then
|
|
:
|
|
elif [ -n "${manifest}" ] && [ -f "${manifest}" ]; then
|
|
:
|
|
elif [ -d "${self}.runfiles" ]; then
|
|
runfiles_dir="${self}.runfiles"
|
|
elif [ -f "${self}.runfiles_manifest" ]; then
|
|
manifest="${self}.runfiles_manifest"
|
|
elif [ -f "${self}.exe.runfiles_manifest" ]; then
|
|
manifest="${self}.exe.runfiles_manifest"
|
|
else
|
|
echo "rules_bun: unable to locate runfiles for ${self}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
rlocation() {
|
|
path="$1"
|
|
if [ -n "${runfiles_dir}" ]; then
|
|
printf '%s\\n' "${runfiles_dir}/${path}"
|
|
return 0
|
|
fi
|
|
|
|
result=""
|
|
while IFS= read -r line; do
|
|
case "${line}" in
|
|
"${path} "*)
|
|
result="${line#${path} }"
|
|
break
|
|
;;
|
|
esac
|
|
done < "${manifest}"
|
|
if [ -z "${result}" ]; then
|
|
echo "rules_bun: missing runfile ${path}" >&2
|
|
exit 1
|
|
fi
|
|
printf '%s\\n' "${result}"
|
|
}
|
|
|
|
bun_bin="$(rlocation "__BUN_RUNFILES_PATH__")"
|
|
runner="$(rlocation "__RUNNER_RUNFILES_PATH__")"
|
|
spec="$(rlocation "__SPEC_RUNFILES_PATH__")"
|
|
|
|
export RULES_BUN_LAUNCHER_PATH="${self}"
|
|
if [ -n "${runfiles_dir}" ]; then
|
|
export RULES_BUN_RUNFILES_DIR="${runfiles_dir}"
|
|
fi
|
|
if [ -n "${manifest}" ]; then
|
|
export RULES_BUN_RUNFILES_MANIFEST="${manifest}"
|
|
fi
|
|
|
|
exec "${bun_bin}" --bun "${runner}" "${spec}" "$@"
|
|
"""
|
|
|
|
_CMD_WRAPPER_TEMPLATE = """@echo off
|
|
setlocal
|
|
|
|
set "SELF=%~f0"
|
|
set "RUNFILES_DIR_VALUE=%RUNFILES_DIR%"
|
|
set "RUNFILES_MANIFEST_VALUE=%RUNFILES_MANIFEST_FILE%"
|
|
|
|
if defined RUNFILES_DIR_VALUE if exist "%RUNFILES_DIR_VALUE%" goto have_runfiles
|
|
if defined RUNFILES_MANIFEST_VALUE if exist "%RUNFILES_MANIFEST_VALUE%" goto have_runfiles
|
|
if exist "%SELF%.runfiles" (
|
|
set "RUNFILES_DIR_VALUE=%SELF%.runfiles"
|
|
goto have_runfiles
|
|
)
|
|
if exist "%SELF%.runfiles_manifest" (
|
|
set "RUNFILES_MANIFEST_VALUE=%SELF%.runfiles_manifest"
|
|
goto have_runfiles
|
|
)
|
|
if exist "%~dpn0.runfiles_manifest" (
|
|
set "RUNFILES_MANIFEST_VALUE=%~dpn0.runfiles_manifest"
|
|
goto have_runfiles
|
|
)
|
|
|
|
echo rules_bun: unable to locate runfiles for "%SELF%" 1>&2
|
|
exit /b 1
|
|
|
|
:have_runfiles
|
|
call :rlocation "__BUN_RUNFILES_PATH__" BUN_BIN || exit /b 1
|
|
call :rlocation "__RUNNER_RUNFILES_PATH__" RUNNER || exit /b 1
|
|
call :rlocation "__SPEC_RUNFILES_PATH__" SPEC || exit /b 1
|
|
|
|
set "RULES_BUN_LAUNCHER_PATH=%SELF%"
|
|
if defined RUNFILES_DIR_VALUE (
|
|
set "RULES_BUN_RUNFILES_DIR=%RUNFILES_DIR_VALUE%"
|
|
) else (
|
|
set "RULES_BUN_RUNFILES_DIR="
|
|
)
|
|
if defined RUNFILES_MANIFEST_VALUE (
|
|
set "RULES_BUN_RUNFILES_MANIFEST=%RUNFILES_MANIFEST_VALUE%"
|
|
) else (
|
|
set "RULES_BUN_RUNFILES_MANIFEST="
|
|
)
|
|
|
|
"%BUN_BIN%" --bun "%RUNNER%" "%SPEC%" %*
|
|
exit /b %ERRORLEVEL%
|
|
|
|
:rlocation
|
|
set "LOOKUP=%~1"
|
|
set "OUTPUT_VAR=%~2"
|
|
if defined RUNFILES_DIR_VALUE (
|
|
set "%OUTPUT_VAR%=%RUNFILES_DIR_VALUE%\\%LOOKUP:/=\\%"
|
|
exit /b 0
|
|
)
|
|
for /f "tokens=1,* delims= " %%A in ('findstr /b /c:"%LOOKUP% " "%RUNFILES_MANIFEST_VALUE%"') do (
|
|
set "%OUTPUT_VAR%=%%B"
|
|
exit /b 0
|
|
)
|
|
echo rules_bun: missing runfile %LOOKUP% 1>&2
|
|
exit /b 1
|
|
"""
|
|
|
|
def runfiles_path(file):
|
|
workspace_name = file.owner.workspace_name
|
|
if workspace_name:
|
|
return "{}/{}".format(workspace_name, file.short_path)
|
|
return "_main/{}".format(file.short_path)
|
|
|
|
def runtime_launcher_attrs():
|
|
return {
|
|
"_runtime_launcher": attr.label(
|
|
default = _RUNTIME_LAUNCHER,
|
|
allow_single_file = True,
|
|
),
|
|
"_windows_constraint": attr.label(
|
|
default = _WINDOWS_CONSTRAINT,
|
|
),
|
|
}
|
|
|
|
def is_windows_target(ctx):
|
|
return ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
|
|
|
|
def write_launcher_spec(ctx, spec):
|
|
spec_file = ctx.actions.declare_file(ctx.label.name + ".launcher.json")
|
|
ctx.actions.write(
|
|
output = spec_file,
|
|
content = json.encode(spec) + "\n",
|
|
)
|
|
return spec_file
|
|
|
|
def declare_runtime_wrapper(ctx, bun_bin, spec_file):
|
|
runner = ctx.file._runtime_launcher
|
|
wrapper = ctx.actions.declare_file(ctx.label.name + (".cmd" if is_windows_target(ctx) else ""))
|
|
content = _CMD_WRAPPER_TEMPLATE if is_windows_target(ctx) else _POSIX_WRAPPER_TEMPLATE
|
|
content = content.replace("__BUN_RUNFILES_PATH__", runfiles_path(bun_bin)).replace(
|
|
"__RUNNER_RUNFILES_PATH__",
|
|
runfiles_path(runner),
|
|
).replace(
|
|
"__SPEC_RUNFILES_PATH__",
|
|
runfiles_path(spec_file),
|
|
)
|
|
ctx.actions.write(
|
|
output = wrapper,
|
|
content = content,
|
|
is_executable = True,
|
|
)
|
|
return struct(
|
|
executable = wrapper,
|
|
runner = runner,
|
|
)
|