Как я могу получить доступ к выводу правила базеля из другого правила без использования относительного пути? - PullRequest
1 голос
/ 10 апреля 2020

Я пытаюсь использовать Bazel для компиляции программы dhall на основе dhall-kubernetes для создания файла YAML Kubernetes.

basi c dhall compile без dhall-kubernetes, используя простой макрос bazel работает хорошо.

Я сделал пример использования разрешения зависимостей dhall для загрузки dhall-kubernetes - см. здесь . Это также работает, но очень медленно (я думаю, потому что dhall загружает каждый удаленный файл отдельно) и вводит сетевую зависимость при выполнении правила bazel, чего я бы предпочел избегать.

Мой предпочтительный подход заключается в использовании Bazel чтобы загрузить версию архива dhall-kubernetes, а затем получить доступ к ней локально (см. здесь ). Мое решение требует относительный путь в Prelude.dhall и package.dhall для пакета examples / k8s для ссылки на dhall-kubernetes. Хотя это работает, я обеспокоен тем, что это подрывает песочницу Bazel, требуя специальных знаний о структуре папок, используемых внутри Bazel. Есть ли лучший способ?

Prelude.dhall:

../../external/dhall-kubernetes/1.17/Prelude.dhall 

РАБОЧЕЕ МЕСТО:

workspace(name = "dhall")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

DHALL_KUBERNETES_VERSION = "4.0.0"

http_archive(
    name = "dhall-kubernetes",
    sha256 = "0bc2b5d2735ca60ae26d388640a4790bd945abf326da52f7f28a66159e56220d",
    url = "https://github.com/dhall-lang/dhall-kubernetes/archive/v%s.zip" % DHALL_KUBERNETES_VERSION,
    strip_prefix = "dhall-kubernetes-4.0.0",
    build_file = "@//:BUILD.dhall-kubernetes",
)

BUILD.dhall-kubernetes:

package(default_visibility=['//visibility:public'])

filegroup(
    name = "dhall-k8s-1.17",
    srcs = glob([
        "1.17/**/*",
    ]),
)

examples / k8s / BUILD:

package(default_visibility = ["//visibility:public"])

genrule(
    name = "special_ingress",
    srcs = ["ingress.dhall",
            "Prelude.dhall",
            "package.dhall",
        "@dhall-kubernetes//:dhall-k8s-1.17"
    ],
    outs = ["ingress.yaml"],
    cmd = "dhall-to-yaml --file $(location ingress.dhall) > $@",
    visibility = [
        "//visibility:public"
    ]
)

1 Ответ

1 голос
/ 11 апреля 2020

Существует способ, позволяющий dhall создавать "автономные" сборки, что означает, что менеджер пакетов выбирает все зависимости Dhall, а не извлекает их из Dhall.

Фактически, я реализовал кое-что именно для Nixpkgs , который вы можете перевести на Bazel:

Объяснение высокого уровня

Основной трюк c состоит в том, чтобы воспользоваться преимуществом системы импорта Dhall, которая заключается в том, что если кешируется пакет, защищенный проверкой целостности semanti c (т.е. "semanti c ha sh"), то Dhall будет использовать кеш вместо загрузки пакета. Вы можете использовать этот трюк, чтобы менеджер пакетов обходил удаленный импорт Dhall, внедряя зависимости таким образом.

Здесь вы можете найти логику, связанную с Nix c, для этого здесь:

... но я постараюсь объяснить, как это работает независимо от менеджера пакетов.

Структура пакета

Во-первых, конечным продуктом "пакета" Dhall, созданного с использованием Nix, является каталог со следующей структурой:

$ nix-build --attr 'dhallPackages.Prelude."13.0.0"'
…

$ tree result

Содержимое этого каталога:

  • ./cache/dhall/1220XXX…XXX

    Действительный каталог кэша для Dhall, содержащий один продукт сборки: двоичное кодирование интерпретированного выражения Dhall.

    Вы можете создать такой двоичный файл, используя dhall encode, и вы можете вычислить имя файла, заменив XXX…XXX выше кодировкой выражения sha256, которую можно получить с помощью команды dhall hash.

  • ./binary.dhall

    A удобный файл Dhall, содержащий выражение missing sha256:XXX…XXX. Интерпретация этого выражения будет успешной только в том случае, если созданное нами выражение, совпадающее с ha sh sha256:XXX…XXX, уже кэшировано.

    Файл называется binary.dhall, поскольку это эквивалент Dhall "двоичного" распределения пакетов, Это означает, что импорт может быть получен только из двоичного кэша и не может быть выбран и интерпретирован из источника.

  • Необязательно: ./source.dhall

    Это файл, содержащий полностью αβ-нормализованное выражение, эквивалентное выражению, которое было кэшировано. По умолчанию это должно быть пропущено для всех пакетов, кроме, возможно, пакета верхнего уровня, поскольку оно содержит то же выражение, которое хранится в ./cache/1220XXX…XXX, хотя и менее эффективно (поскольку двоичная кодировка более компактна)

    Этот файл называется ./source.dhall, потому что это эквивалент Dhall «исходного» дистрибутива пакета, который содержит действительный исходный код для получения того же результата.

Пользовательский интерфейс

Функция для сборки пакета принимает четыре аргумента:

  • Имя пакета

    Это не материал для сборки. Это просто название, так как каждый пакет Nix должен иметь удобочитаемое имя.

  • Зависимости для сборки

    Каждая из этих зависимостей является продуктом сборки, который создает дерево каталогов точно так же, как я описал выше (то есть каталог ./cache, файл ./binary.dhall и необязательный файл ./source.dhall)

  • выражение Dhall

    Это может быть произвольный исходный код Dhall только с одним предупреждением: все удаленные импорты, на которые ссылается выражение, должны быть защищены проверками целостности, и эти импорты должны соответствовать одной из зависимостей этого пакета Dhall (так, чтобы импорт может быть выполнено через кеш вместо времени выполнения Dhall, извлекающего URL)

  • Логическая опция, указывающая, сохранять ли файл ./source.dhall, который по умолчанию False

Реализация

Способ работы сборщика пакетов Dhall:

  • Сначала создайте пакет Haskell Dhall с флагом -f-with-http

    Этот флаг компилирует поддержку удаленного импорта HTTP, таким образом, если пользователь забудет предоставить зависимость для удаленного импорта, он получит сообщение об ошибке, говорящее Import resolution is disabled

    Мы будем использовать этот исполняемый файл для всех последующих шагов

  • Создайте каталог кэша в текущем рабочем каталоге с именем .cache/dhall

    ... и заполните каталог кэша сохраненными двоичными файлами внутри каталога ./cache/ каждой зависимости

  • Сконфигурируйте интерпретатор для использования каталога кэша, который мы создали

    ..., установив XDG_CACHE_HOME для указания на .cache каталог, который мы только что создали в нашем текущем рабочем каталоге

  • Интерпретировать и α-нормализовать исходный код Dhall для нашего пакета

    ... с помощью команды dhall --alpha. Сохраните результат в $out/source.dhall, где $out - это каталог, в котором будет храниться конечный продукт сборки

  • Получите выражение ha sh

    ... используя команда dhall hash. Нам понадобится это ha sh для следующих двух шагов.

  • Создайте соответствующий двоичный файл кэша

    ... с помощью команды dhall encode и сохраните файл в $out/cache/dhall/1220${HASH}

  • Создайте файл ./binary.dhall

    ..., просто записав текстовый файл в $out/binary.dhall, содержащий missing sha256:${HASH}

  • Необязательно: Удалите файл ./source.dhall

    ..., если пользователь не запросил сохранить файл. Пропуск этого файла по умолчанию помогает сэкономить место в хранилище пакетов, не сохраняя одно и то же выражение дважды (как двоичный файл и исходный код).

Соглашения об упаковке

Если у вас есть эта функция, есть пара соглашений, которые могут помочь упростить выполнение «в целом»

  • По умолчанию пакет должен создавать файл ./package.dhall проекта

  • Упрощение переопределения версии пакета

  • Упрощение переопределения файла, встроенного в пакет

    Другими словами Если пользователь предпочитает импортировать отдельные файлы, такие как https://prelude.dhall-lang.org/List/map, вместо файла ./package.dhall верхнего уровня, у них должен быть способ указать зависимость, такую ​​как Prelude.override { file = "./List/map"; }, для получения пакета, который создает и кэширует этот отдельный файл.

Заключение

Надеюсь, это поможет! Если у вас есть дополнительные вопросы о том, как это сделать, вы можете задать их здесь или обсудить больше на нашем форуме, особенно в теме, где впервые возникла эта идиома:

...