Как написать правила Bazel, которые работают с внешними репозиториями? - PullRequest
0 голосов
/ 22 апреля 2019

API Bazel Starlark делает странные вещи с файлами во внешних репозиториях. У меня есть следующий фрагмент Starlark:

    print(ctx.genfiles_dir)
    print(ctx.genfiles_dir.path)
    print(output_filename)
    ret = ctx.new_file(ctx.genfiles_dir, output_filename)
    print(ret.path)

Создает следующий вывод:

DEBUG: build_defs.bzl:292:5: <derived root>
DEBUG: build_defs.bzl:293:5: bazel-out/k8-fastbuild/genfiles
DEBUG: build_defs.bzl:294:5: google/protobuf/descriptor.upb.c
DEBUG: build_defs.bzl:296:5: bazel-out/k8-fastbuild/genfiles/external/com_google_protobuf/google/protobuf/descriptor.upb.c

Эта дополнительная external/com_google_protobuf появляется, казалось бы, из ниоткуда, и это делает мое правило провальным:

  • Я приказываю protoc генерировать в ctx.genfiles_dir.path (что является bazel-out/k8-fastbuild/genfiles).
  • Таким образом, протокол генерирует bazel-out/k8-fastbuild/genfiles/google/protobuf/descriptor.upb.c
  • Сбой Базеля, потому что я не генерировал bazel-out/k8-fastbuild/genfiles/external/com_google_protobuf/google/protobuf/descriptor.upb.c

Аналогично, когда я пытаюсь вызвать file.short_path для исходного файла из внешнего репозитория, я получаю результат, подобный ../com_google_protobuf/google/protobuf/descriptor.proto. Это кажется совершенно бесполезным, поэтому я просто написал некоторый ручной код, чтобы убрать ведущие ../com_google_protobuf/.

Я что-то упустил? Как я могу написать это правило так, чтобы я не сражался с Базелем все время?

1 Ответ

1 голос
/ 24 апреля 2019

Я что-то упустил?

Основная проблема, как вы уже поняли, состоит в том, что у вас есть два "пространства имен" пути: одно, которое видит протокол (т.е. пути импорта), и то, которое видит Базель (то есть путь, который вы передаете declare_file().

2 вещи на заметку:

1) Все пути, объявленные с declare_file(), получают путь <bin dir>/<package path incl. workspace>/<path you passed to declare_file()>

2) Все действия выполняются с <bin dir> (если только output_to_genfils=True, в этом случае это переключается на <gen dir>, как в вашем примере.

Пытаясь решить ту же самую проблему, с которой вы столкнулись, я прибег к удалению известного пути из пути выходного файла, чтобы определить, какой каталог передать как p:

# This code is run from the context of the external protobuf dependency
proto_path = "google/a/b.proto"
output_file = ctx.actions.declare_file(proto_path)

# output_file.path would be `<gen_dir>/external/protobuf/google/a/b.proto`
# Strip the known proto_path from output_file.path
protoc_prefix = output_file.path[:-len(proto_path)]

print(protoc_prefix) # Prints: <gen_dir>/external/protobuf

command = "{protoc} {proto_paths} {cpp_out} {plugin} {plugin_options} {proto_file}".format(
        ...
        cpp_out = "--cpp_out=" + protoc_prefix,
        ...
)

Альтернативы

Вы также можете создать тот же путь с ctx.bin_dir, ctx.label.workspace_name, ctx.label.package и ctx.label.name.

Разное.

proto_library недавно получил атрибут strip_import_prefix. При использовании вышеприведенное неверно, так как все зависимые файлы являются символическими ссылками в новый каталог, из которого они имеют относительные пути, объявленные с strip_import_prefix.

Формат пути:

<bin dir>/<repo>/<package>/_virtual_base/<label name>/<path `import`ed in .proto files>
i.e.
<bin dir>/external/protobuf/_virtual_base/b_proto/google/a/b.proto

Предполагается, что вы создаете внешний репозиторий с именем protobuf, который содержит в своем корне файл BUILD с целью с именем b_proto, которая, в свою очередь, опирается на proto_library оболочку google/a/b.proto И использует strip_import_prefix атрибут.

...