@@ -39,6 +39,8 @@ header-includes:
40Вы можете прекратить слушать после любой секции, и я надеюсь, что вы унесете какую-то полезную для себя информацию.
40Вы можете прекратить слушать после любой секции, и я надеюсь, что вы унесете какую-то полезную для себя информацию.
42+Исходники, собранный pdf и заметки докладчика для этой презентации находятся на <https://github.com/typeable/nix-pills-ru>
44Как вы все скорее всего знаете, мы используем Nix для сборки и тестирования нашего кода. Я, Александр Бантьев (@balsoft) отвечаю за инфраструктуру сборки пакетов (Hydra, NixOps), а также за поддержание инструкций сборки в актуальном состоянии. Я бы хотел рассказать вам про nix с помощью вольного пересказа отличной серии статей ["Nix pills"](https://nixos.org/nixos/nix-pills)
46Как вы все скорее всего знаете, мы используем Nix для сборки и тестирования нашего кода. Я, Александр Бантьев (@balsoft) отвечаю за инфраструктуру сборки пакетов (Hydra, NixOps), а также за поддержание инструкций сборки в актуальном состоянии. Я бы хотел рассказать вам про nix с помощью вольного пересказа отличной серии статей ["Nix pills"](https://nixos.org/nixos/nix-pills)
@@ -352,7 +354,7 @@ nix-repl> s."123"
352nix-repl> s.${toString (122 + 1)}
354nix-repl> s.${toString (122 + 1)}
355−***
357+## Множества аттрибутов
357nix-repl> s ? "123"
359nix-repl> s ? "123"
@@ -821,20 +823,20 @@ in
822## Сборка с библиотеками: `NIX_CFLAGS_COMPILE`, `NIX_LDFLAGS`
824## Сборка с библиотеками: `NIX_CFLAGS_COMPILE`, `NIX_LDFLAGS`
824−Если мы хотим собирать пакеты, которые зависят от сторонних библиотек, нам понадобится ещё немного магии: нужно указать GCC и ld, где искать заголовочные и объектные файлы библиотек. Для этого существуют переменные `NIX_CFLAGS_COMPILE` и `NIX_LDFLAGS_`
826+Если мы хотим собирать пакеты, которые зависят от сторонних библиотек, нам понадобится ещё немного магии: нужно указать GCC и ld, где искать заголовочные и объектные файлы библиотек. Для этого существуют переменные `NIX CFLAGS COMPILE` и `NIX LDFLAGS`
826### `generic-builder.sh`
828### `generic-builder.sh`
829for p in $baseInputs $buildInputs; do
831for p in $baseInputs $buildInputs; do
830− if [ -d $p/bin ]; then
832+ [...]
831− export PATH="$p/bin${PATH:+:}$PATH"
833 if [ -d $p/include ]; then
833 if [ -d $p/include ]; then
834− export NIX_CFLAGS_COMPILE="-I $p/include${NIX_CFLAGS_COMPILE:+ }$NIX_CFLAGS_COMPILE"
834+ export NIX_CFLAGS_COMPILE="-I $p/include${NIX_CFLAGS_COMPILE:+ }\
836 if [ -d $p/lib ]; then
837 if [ -d $p/lib ]; then
837− export NIX_LDFLAGS="-rpath $p/lib -L $p/lib${NIX_LDFLAGS:+ }$NIX_LDFLAGS"
838+ export NIX_LDFLAGS="-rpath $p/lib -L \
839+$p/lib${NIX_LDFLAGS:+ }$NIX_LDFLAGS"
@@ -847,7 +849,9 @@ done
847mkDerivation {
849mkDerivation {
848 name = "graphviz";
850 name = "graphviz";
849 src = ./graphviz-2.38.0.tar.gz;
851 src = ./graphviz-2.38.0.tar.gz;
852+ buildInputs = if gdSupport
850− buildInputs = if gdSupport then [ gd fontconfig libjpeg bzip2 ] else [];
853+ then [ gd fontconfig libjpeg bzip2 ]
@@ -874,11 +878,14 @@ in
875### `default.nix`
879### `default.nix`
882+ pkgs = import <nixpkgs> {};
883+ mkDerivation = import ./generic-builder.nix pkgs;
878 hello = callPackage ./hello.nix { };
886 hello = callPackage ./hello.nix { };
879 graphviz = callPackage ./graphviz.nix { };
887 graphviz = callPackage ./graphviz.nix { };
880− graphvizCore = callPackage ./graphviz.nix
888+ graphvizCore = callPackage ./graphviz.nix { gdSupport = false; };
881− { gdSupport = false; };
@@ -907,7 +914,8 @@ nix-repl> builtins.intersectAttrs (builtins.functionArgs add) values
908nix-repl> callPackage = set: f:
915nix-repl> callPackage = set: f:
909 f (builtins.intersectAttrs
916 f (builtins.intersectAttrs
910− (builtins.functionArgs f) set)
917+ (builtins.functionArgs f)
911nix-repl> callPackage values add
919nix-repl> callPackage values add
913nix-repl> with values; add { inherit a b; }
921nix-repl> with values; add { inherit a b; }
@@ -920,7 +928,9 @@ nix-repl> with values; add { inherit a b; }
921nix-repl> callPackage = set: f: overrides:
929nix-repl> callPackage = set: f: overrides:
922 f ((builtins.intersectAttrs
930 f ((builtins.intersectAttrs
923− (builtins.functionArgs f) set) // overrides)
931+ (builtins.functionArgs f)
924nix-repl> callPackage values add { }
934nix-repl> callPackage values add { }
926nix-repl> callPackage values add { b = 12; }
936nix-repl> callPackage values add { b = 12; }
@@ -933,7 +943,10 @@ let
933 allPkgs = nixpkgs // pkgs;
943 allPkgs = nixpkgs // pkgs;
934 callPackage = path: overrides:
944 callPackage = path: overrides:
935 let f = import path;
945 let f = import path;
936− in f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
946+ in f ((builtins.intersectAttrs
947+ (builtins.functionArgs f)
937 pkgs = with nixpkgs; {
950 pkgs = with nixpkgs; {
938 mkDerivation = import ./generic-builder.nix nixpkgs;
951 mkDerivation = import ./generic-builder.nix nixpkgs;
939 hello = callPackage ./hello.nix { };
952 hello = callPackage ./hello.nix { };
@@ -953,7 +966,7 @@ VS.
954mygraphviz = pkgs.graphviz.override { gd = customgd }
967mygraphviz = pkgs.graphviz.override { gd = customgd }
956−***
969+## Паттерн `override`: `makeOverridable`
958Для реализации нашей затеи напишем функцию `mkOverridable`, которая будет принимать функцию, возвращающую attrset, и attrset (который будет являться "дефолтными" аргументами для данной функции). Вернет `makeOverridable` тот же attrset, что вернула бы данная функция, с добавлением аттрибута `override`, который является функцией, позволяющей нам "перегружать" стандартные аргументы.
971Для реализации нашей затеи напишем функцию `mkOverridable`, которая будет принимать функцию, возвращающую attrset, и attrset (который будет являться "дефолтными" аргументами для данной функции). Вернет `makeOverridable` тот же attrset, что вернула бы данная функция, с добавлением аттрибута `override`, который является функцией, позволяющей нам "перегружать" стандартные аргументы.
@@ -970,8 +983,7 @@ rec {
973−***
986+## Паттерн `override`: потестируем!
974−### Протестируем в `nix repl`
976Работает! Теперь мы можем легко "перегружать" аргументы пакетов (которые, напомню, просто функции) в нашем репозитории. Нужно только не забыть вызывать все эти пакеты с makeOverridable.
988Работает! Теперь мы можем легко "перегружать" аргументы пакетов (которые, напомню, просто функции) в нашем репозитории. Нужно только не забыть вызывать все эти пакеты с makeOverridable.
@@ -986,7 +998,7 @@ nix-repl> res2
986nix-repl> res2.override { b = 20; }
998nix-repl> res2.override { b = 20; }
987{ override = «lambda»; result = 30; }
999{ override = «lambda»; result = 30; }
989−***
1001+## Паттерн `override`: объединяем с `callPackage`
990### `lib.nix`
1002### `lib.nix`
@@ -995,10 +1007,12 @@ rec {
995 let f = import path;
1007 let f = import path;
996 in makeOverridable
1008 in makeOverridable
997 f ((builtins.intersectAttrs
1009 f ((builtins.intersectAttrs
998− (builtins.functionArgs f) pkgs) // overrides);
1010+ (builtins.functionArgs f)
1001−***
1015+## Паттерн `override`: репозиторий
1002### `default.nix`
1016### `default.nix`
@@ -1014,9 +1028,51 @@ let
1017−## nixpkgs
1031+## nixpkgs: краткая справка
1033+### Общая конфигурация для всех пакетов
1035+* `import <nixpkgs> { config = {...}; }`
1037+* `~/.config/nixpkgs/config.nix`
1040+### Перегрузка пакетов
1043+config.packageOverrides = oldPkgs: {
1044+ graphviz = oldPkgs.graphviz.override { gd = customgd; };
1050+nixpkgs.overlays = [ (self: super: {
1051+ graphviz = super.graphviz.override { gd = customgd; };
1055+## `stdenv.mkDerivation`: прокачиваем наш `mkDerivation`
1019−Изначально я планировал вкратце рассказать про остальные паттерны nixpkgs, но в итоге получился просто объяснение, что же происходит в каждом файле, которое к тому же растянуло бы презентацию ещё на несколько десятков слайдов. На самом деле, на данный момент ваших знаний nix вполне достаточно для чтения исходников nixpkgs.
1057+Наша функция `mkDerivation`, без сомнения, прекарасна, но можно лучше! `stdenv.mkDerivation` из nixpkgs предоставляет интерфейс (т.е принимаемые и возвращаемые значения) очень похожие на наш `mkDerivation`, с несколькими отличиями:
1021−> Изучение nixpkgs остается в качестве упражнения для слушателя.
1059+`stdenv.mkDerivation` может...
1061+* Изменять поведение фаз, например `{ buildPhase = "make"; }`
1062+* Изменять список фаз `{ phases = [ "buildPhase" ]; }`
1063+* Перегружать аргументы с помощью `overrideAttrs`
1064+* Автоматически добавлять хуки на проброс зависимостей с помощью `propogatedBuildInputs`
1067+## Что осталось за кадром в этом разделе
1070+Нельзя объять необъятное -- а nixpkgs действительно необъятен, более 100МБ кода на данный момент -- и поэтому я оставлю изучение частностей на совести слушателя.
1077+<https://nixos.org/nixos/nix-pills> и <https://nixos.org/nixpkgs/manual> -- для тех, кому надо или интересно!