Подтвердить что ты не робот

Как заставить cabal и nix работать вместе

Насколько я понял, Nix является альтернативой для cabal sandbox. Наконец, мне удалось установить Nix, но я до сих пор не понимаю, как он может заменить песочницу.

Я понимаю, что вам не нужны кабалы, используя Nix и завернутую версию GHC; однако, если вы хотите для публикации пакета, который вам понадобится в какой-то момент, чтобы упаковать его с помощью cabal. Поэтому вы должны иметь возможность писать и тестировать свою конфигурацию кэша в NIX. Как вы это делаете?

В идеале, я бы хотел, чтобы среда, похожая на песочницу cabal, но содержалась в NIX, это возможно? Фактически, то, что я действительно хотел бы, это эквивалент вложенных песочниц - поскольку я обычно работаю над проектами из нескольких пакетов.

Обновление моего текущего рабочего процесса

В настоящий момент я работаю над 2 или 3 независимыми проектами (P1, P2, P3), каждый из которых состоит из 2 или 3 модулей/пакетов cabal, допустим, для P1: L11, L12 (библиотеки)  и E11 (исполняемые файлы). E11 зависит от L12, который зависит от L11. Я в основном разделял исполняемые файлы из библиотеки, потому что они являются частными и хранятся в частном репозитории git.

В теории каждый проект может иметь свою собственную песочницу (разделяемую между ее подмодулями). Я попробовал это (имея общую песочницу для L11 L12 и E11), но это очень раздражает, потому что, если вы изменяете L11, вы не можете его перестроить, потому что E11 зависит от него, поэтому мне сначала нужно удалить E11, чтобы перекомпилировать L11. Это может быть не совсем так, но я сталкиваюсь с подобной проблемой. Это было бы хорошо, если бы я иногда менял L11, но на практике я изменил его больше, чем E11.

Поскольку совместная песочница не работает, я вернулся к одной песочнице для каждого пакетного решения. Он работает, но не идеален. Основная проблема заключается в том, что если я изменяю L11, мне нужно скомпилировать его дважды (один раз в L11, а затем снова в E11). Кроме того, каждый раз, когда я начинаю новую песочницу, как все знают, мне нужно подождать некоторое время, чтобы загрузить и перекомпилировать пакет.

Таким образом, используя Nix, я надеюсь, что вы сможете настроить отдельные "среды" для каждого проекта, которые решают все проблемы.

Надеюсь, что это яснее.

4b9b3361

Ответ 1

В наши дни я делаю все свое развитие, используя Nix и cabal, и я могу с радостью сказать, что они работают в гармонии очень хорошо. Мой текущий рабочий процесс очень новый, поскольку он полагается на функции в nixpkgs, которые только что достигли главной ветки. Таким образом, первое, что вам нужно сделать, это clone nixpkgs от Github:

cd ~
git clone git://github.com/nixos/nixpkgs

(В будущем это не понадобится, но прямо сейчас).

Использование одного проекта

Теперь, когда у нас есть клон nixpkgs, мы можем начать использовать набор пакетов haskellng. haskellng - это переписывание того, как мы упаковываем вещи в Nix, и представляет интерес для нас, чтобы быть более предсказуемым (имена пакетов соответствуют именам пакетов Hackage) и более настраиваемыми. Сначала мы установим инструмент cabal2nix, который может автоматизировать некоторые вещи для нас, и мы также установим cabal-install для обеспечения исполняемого файла cabal:

nix-env -f ~/nixpkgs -i -A haskellngPackages.cabal2nix -A haskellngPackages.cabal-install

С этого момента все это довольно ясно проплывает.

Если вы начинаете новый проект, вы можете просто вызвать cabal init в новом каталоге, как обычно. Когда вы будете готовы к созданию, вы можете превратить этот файл .cabal в среду разработки:

cabal init
# answer the questions
cabal2nix --shell my-project.cabal > shell.nix

Это дает вам файл shell.nix, который можно использовать с nix-shell. Вам не нужно использовать это очень часто, но - единственный раз, когда вы обычно используете его с помощью cabal configure:

nix-shell -I ~ --command 'cabal configure'

cabal configure кэширует абсолютные пути ко всему, поэтому теперь, когда вы хотите построить, вы просто используете cabal build как обычно:

cabal build

Всякий раз, когда ваш файл .cabal изменяется, вам необходимо восстановить shell.nix - просто запустите команду выше, а затем cabal configure после.

Использование нескольких проектов

Подход хорошо подходит для нескольких проектов, но для этого требуется немного более ручная работа, чтобы "склеить" все вместе. Чтобы продемонстрировать, как это работает, рассмотрим мою библиотеку socket-io. Эта библиотека зависит от engine-io, и я обычно разрабатываю оба одновременно.

Первым шагом для Nix-ifying этого проекта является генерация выражений default.nix вдоль каждого отдельного файла .cabal:

cabal2nix engine-io/engine-io.cabal > engine-io/default.nix
cabal2nix socket-io/socket-io.cabal > socket-io/default.nix

Эти выражения default.nix являются функциями, поэтому мы не можем делать многое прямо сейчас. Чтобы вызвать функции, мы пишем наш собственный файл shell.nix, в котором объясняется, как объединить все. Для engine-io/shell.nix нам не нужно делать ничего особенно умного:

with (import <nixpkgs> {}).pkgs;
(haskellngPackages.callPackage ./. {}).env

Для socket-io нам нужно зависеть от engine-io:

with (import <nixpkgs> {}).pkgs;
let modifiedHaskellPackages = haskellngPackages.override {
      overrides = self: super: {
        engine-io = self.callPackage ../engine-io {};
        socket-io = self.callPackage ./. {};
      };
    };
in modifiedHaskellPackages.socket-io.env

Теперь у нас есть shell.nix в каждой среде, поэтому мы можем использовать cabal configure, как и раньше.

Основное замечание здесь состоит в том, что всякий раз, когда engine-io изменяется, нам нужно перенастроить socket-io, чтобы обнаружить эти изменения. Это так же просто, как запуск

cd socket-io; nix-shell -I ~ --command 'cabal configure'

Nix заметит, что ../engine-io изменился и перестроит его перед запуском cabal configure.