diff --git a/repro/BUILD.bazel b/repro/BUILD.bazel new file mode 100644 index 000000000000..ff1ece6c97ea --- /dev/null +++ b/repro/BUILD.bazel @@ -0,0 +1,64 @@ +load(":sh.bzl", "sh_inline_test") + +sh_binary( + name = "script", + srcs = ["script.sh"], +) + +sh_binary( + name = "wrapper", + # ERROR: ... in srcs attribute of sh_binary rule //repro:wrapper: you must specify exactly one file in 'srcs' + srcs = [":script"], +) + +genrule( + name = "genrule", + srcs = [":script"], + outs = ["genrule.txt"], + # ERROR: ... in cmd attribute of genrule rule //repro:genrule: label '//repro:script' in $(location) expression expands to more than one file, please use $(locations //repro:script) instead. Files (at most 5 shown) are: [repro/script, repro/script.sh] + # cmd = "echo $(rootpath :script) > $(OUTS)", + # LINUX - NO ERROR + # repro/script repro/script.sh + # WINDOWS - NO ERROR + # repro/script repro/script.exe repro/script.sh + cmd = "echo $(rootpaths :script) > $(OUTS)", +) + +# LINUX - NO ERROR +# ARG repro/script +# LOC .../execroot/com_github_digital_asset_daml/bazel-out/k8-opt/bin/repro/test.runfiles/com_github_digital_asset_daml/repro/script +# WINDOWS - NO ERROR +# ARG repro/script.exe +# LOC .../execroot/com_github_digital_asset_daml/bazel-out/x64_windows-opt/bin/repro/script.exe +sh_test( + name = "test", + srcs = ["test.sh"], + deps = ["@bazel_tools//tools/bash/runfiles"], + data = [":script"], + args = ["$(rootpath :script)"], +) + +cc_binary( + name = "runner", + srcs = ["runner.c"], +) + +sh_inline_test( + name = "inline-test", + # ERROR: ... in _sh_inline_script rule //repro:inline-test_script: label '//repro:script' in $(location) expression expands to more than one file, please use $(locations //repro:script) instead. Files (at most 5 shown) are: [repro/script, repro/script.sh] + # cmd = "$$(rlocation $$TEST_WORKSPACE/$(rootpath :script))", + # LINUX - NO ERROR + # runner rootpath repro/runner + # script rootpaths repro/script repro/script.sh + # Hello from script.sh + # WINDOWS - ERROR + # runner rootpath repro/runner.exe + # script rootpaths repro/script repro/script.exe repro/script.sh + # ERROR: %1 is not a valid Win32 application. + cmd = """\ +echo runner rootpath $(rootpath :runner) +echo script rootpaths $(rootpaths :script) +$$(rlocation $$TEST_WORKSPACE/$(rootpath :runner)) $$(rlocation $$TEST_WORKSPACE/$(rootpaths :script)) +""", + data = [":runner", ":script"], +) diff --git a/repro/runner.c b/repro/runner.c new file mode 100644 index 000000000000..318a07ca1ce9 --- /dev/null +++ b/repro/runner.c @@ -0,0 +1,46 @@ +#ifdef _WIN32 +#include +#include +#else +#define _GNU_SOURCE +#include +#include +#include +#endif + +#ifdef _WIN32 +VOID exec(LPCTSTR lpApplicationName) { + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + BOOL r = CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, 0, NULL, + NULL, &si, &pi); + if (!r) { + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, 0, NULL); + printf("ERROR %s: %s\n", lpApplicationName, lpMsgBuf); + exit(EXIT_FAILURE); + } + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); +} +#else +void exec(char *const prog) { + char *const argv[] = {prog, NULL}; + execve(prog, argv, environ); + perror("ERROR"); + exit(EXIT_FAILURE); +} +#endif + +int main(int argc, char **argv) { exec(argv[1]); } diff --git a/repro/script.sh b/repro/script.sh new file mode 100755 index 000000000000..3901b1cdd72a --- /dev/null +++ b/repro/script.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +echo Hello from script.sh diff --git a/repro/sh.bzl b/repro/sh.bzl new file mode 100644 index 000000000000..678483ac5b3d --- /dev/null +++ b/repro/sh.bzl @@ -0,0 +1,62 @@ +def _sh_inline_script_impl(ctx): + cmd = ctx.attr.cmd + cmd = ctx.expand_location(cmd, ctx.attr.data) + cmd = ctx.expand_make_variables("cmd", cmd, {}) + ctx.actions.expand_template( + template = ctx.file._template, + output = ctx.outputs.output, + is_executable = True, + substitutions = { + "%cmd%": cmd, + }, + ) + + runfiles = ctx.runfiles(files = [ctx.outputs.output] + ctx.files.data) + for data_dep in ctx.attr.data: + runfiles = runfiles.merge(data_dep[DefaultInfo].default_runfiles) + + return DefaultInfo( + files = depset([ctx.outputs.output]), + runfiles = runfiles, + ) + +_sh_inline_script = rule( + _sh_inline_script_impl, + attrs = { + "cmd": attr.string( + mandatory = True, + ), + "data": attr.label_list( + allow_files = True, + ), + "output": attr.output( + mandatory = True, + ), + "_template": attr.label( + allow_single_file = True, + default = "//repro:sh.tpl", + ), + }, +) + +def sh_inline_test( + name, + cmd, + data = [], + **kwargs): + testonly = kwargs.pop("testonly", True) + _sh_inline_script( + name = name + "_script", + cmd = cmd, + output = name + ".sh", + data = data, + testonly = testonly, + ) + native.sh_test( + name = name, + data = data, + deps = ["@bazel_tools//tools/bash/runfiles"], + srcs = [name + ".sh"], + testonly = testonly, + **kwargs + ) diff --git a/repro/sh.tpl b/repro/sh.tpl new file mode 100755 index 000000000000..695889a779c0 --- /dev/null +++ b/repro/sh.tpl @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set +e +# Copy-pasted from the Bazel Bash runfiles library v2. +set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e +# --- end runfiles.bash initialization v2 --- +set -e +%cmd% +# vim: ft=sh diff --git a/repro/test.sh b/repro/test.sh new file mode 100755 index 000000000000..1b5f9c619af9 --- /dev/null +++ b/repro/test.sh @@ -0,0 +1,14 @@ +# Copy-pasted from the Bazel Bash runfiles library v2. +set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e +# --- end runfiles.bash initialization v2 --- + +for arg in "$@"; do + echo ARG "$arg" + echo LOC "$(rlocation "$TEST_WORKSPACE/$arg")" +done