Как вызывать bash-скрипты внутри sh_binary?

#bash #bazel

#bash #bazel

Вопрос:

У меня есть два сценария оболочки. Один (a) печатает "Hello" , а другой (b) печатает "World" . Я хочу иметь цель Bazel (c), которая вызывает оба сценария и выдает мне "Hello World" .

Моя попытка:

 mkdir BashScriptDemo
cd BashScriptDemo
touch WORKSPACE.bazel # empty WORKSPACE file
touch BUILD.bazel # empty BUILD file
mkdir my_package
cd my_package
echo '3.5.0' > .bazelversion # use Bazel 3.5.0
echo 'echo -n "Hello"' > a.sh # echo Hello
echo 'echo " World!"' > b.sh # echo World! 
echo './a.shn./b.sh' > c.sh # script c that calls a and b 
chmod  x a.sh b.sh c.sh
echo 'sh_binary(name="a",srcs=["a.sh"])' > BUILD.bazel
echo 'sh_binary(name="b",srcs=["b.sh"])' >> BUILD.bazel
echo 'sh_binary(name="c",srcs=["c.sh"],data=[":a", ":b"])' >> BUILD.bazel
buildifier BUILD.bazel # optional in the case you have buildifier installed
bazel run //my_package:c # Bazel is an alias to bazelisk
  

Когда я пытаюсь запустить скрипт, я получаю эту ошибку:

 /home/user/.cache/bazel/_bazel_user/2e3943447179c1e4f0f547d49ba1444f/execroot/__main__/bazel-out/k8-fastbuild/bin/my_package/c: line 1: ./a.sh: No such file or directory
/home/user/.cache/bazel/_bazel_user/2e3943447179c1e4f0f547d49ba1444f/execroot/__main__/bazel-out/k8-fastbuild/bin/my_package/c: line 2: ./b.sh: No such file or directory
  

Как мне нужно изменить BUILD.bazel файл (или любой другой файл), чтобы получить желаемый результат?

Комментарии:

1. может быть, использовать абсолютный путь? или добавьте cd my_package в скрипт

2. Рабочий каталог скрипта (на который ссылается ./ в скрипте) не имеет ничего общего с расположением скрипта; он наследуется от того, что запускает скрипт. Смотрите BashFAQ # 28 для некоторых опций о том, как найти местоположение скрипта (и, следовательно, другие файлы в том же каталоге).

3. Это хороший краткий пример того, как воссоздать вашу настройку. Я приветствую вас за ваши усилия и вопрос. Однако было бы легче читать, если бы он просто показывал различные файлы в контексте.

4. @GordonDavisson проблема не в скрипте. Проблема с bazel в том, что он не может найти bash-скрипт для запуска.

Ответ №1:

runfiles.bash — предпочтительный способ поиска путей к runfiles из сценария оболочки. Документация находится в комментариях в верхней части связанного файла.

Для вашего примера это должно сделать это:

 # --- begin runfiles.bash initialization v2 ---
# 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>amp;2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

"$(rlocation my_workspace/a)"
"$(rlocation my_workspace/b)"
  

Вам также необходимо добавить зависимость от сценария оболочки, заменив строку в вашем BUILD.bazel на:

 sh_binary(
  name = "c",
  srcs = ["c.sh"],
  data = [
    ":a",
    ":b",
  ]),
  deps = ["@bazel_tools//tools/bash/runfiles"],
)
  

И назовите свое рабочее пространство, добавив это в свой WORKSPACE :

 workspace(name = "my_workspace")