Что интересного в Никсе

В Rust новую среду разработки обычно легко настроить — просто используйте rustup, и все готово. Но при использовании такого инструмента сборки, как язык

Ничего

Вы можете достичь гораздо большего, приложив немного усилий. Ведь Никс позволяет:

  • Указывать в коде зависимости от проектов, написанных не на ржавчине;
  • Автоматически добавляйте все инструменты/зависимости ваших проектов в путь с помощью дирв;
  • Легко собирайте тонкие контейнеры Docker.

Начать использовать Nix стоит при работе в репозитории — и не хочется «как раньше». Дополнительные файлы README со списком команд Homebrew, apt, pacman и т. д. которые нужно выполнить. Создание тонких контейнеров Docker — это несложно, без необходимости вручную обрабатывать множество слоев, из которых нужно копировать артефакты сборки.

Эта статья представляет собой спартанский путеводитель по быстрому началу работы с nix, поэтому я не буду вдаваться в подробности о том, как nix работает под капотом, и о синтаксисе nix. Если вам нужна помощь синтаксиса сердитого дешевого nix, я рекомендую пост

выучить X в Y

. Если у вас есть некоторый опыт функционального программирования, вы сразу поймете большинство основ.

Среда разработки

использовать

ничего не отслаивается

настроить nix для нашего проекта. Снежинки (далее «снежинки») — это инновационный инструмент для улучшения воспроизводимости построения; для этого в проект добавляется «файл блокировки». Каждая снежинка может иметь записи

inputs

которые являются другими файлами snowflakes/nix и многими

заключение

. Здесь следует отметить, что все файлы, на которые ссылаются ваши снежинки (включая саму снежинку), должны быть добавлены в git. Если вы получаете ошибки «файл не найден», обязательно добавьте все необходимое с помощью команды

git add

.

Чтобы начать с корня вашего проекта, запустите:

$ nix flake init

В результате у вас получится снежинка flake.nix — файл, который будет выглядеть так:

Flake.nix

{
  description = "A very basic flake";
  outputs = { self, nixpkgs }: {
	packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
	defaultPackage.x86_64-linux = self.packages.x86_64-linux.hello;
  };
}

Эта стартовая снежинка создаст для вас двоичный файл hello world с

nix build .#hello

который вызывает первую строку, или просто с

nix build

вызов цепочки

defaultPackage

. Недостатком этого выпуска является то, что полученный пакет применим только к Linux x86/64. Поэтому давайте расширим запись, чтобы ассортимент подходящих систем тоже увеличился.

Flake.nix

{
  inputs = {
	nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
	flake-utils.url = "github:numtide/flake-utils";
  };
  outputs = { self, nixpkgs, flake-utils, ... }:
	flake-utils.lib.eachDefaultSystem (system:
  	let pkgs = import nixpkgs { inherit system; };
  	in {
    	packages.hello = pkgs.hello;
    	defaultPackage = pkgs.hello;
  	});
}

Мы добавили еще две записи. Прежде всего —

nixpkgs

, который позволяет указать используемую версию nixpkgs. В репозитории nixpkg есть

несколько тысяч упаковок

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

снежинка-утилиты

что позволяет обеспечить поддержку Snowflake сразу во многих системах, а не только в Linux.

Теперь в Linux и Mac пакет hello будет собран. В ходе выполнения nix buildвы должны увидеть каталог resultкоторый содержит пакет helloи это можно сделать с ./result/bin/hello. Каталог результатов представляет собой символическую ссылку на выходные данные сборки в репозитории nix (где nix хранит все выходные файлы). Это не обязательно должен быть каталог, результат зависит только от сборки.

Ржавчина против Никса

Чтобы переключиться с «hello world» на rust, добавим дополнительную запись:

Flake.nix

inputs = {
	nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
	flake-utils.url = "github:numtide/flake-utils";
	rust-overlay.url = "github:oxalica/rust-overlay";
  };
outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }:
  flake-utils.lib.eachDefaultSystem (system:
	let
  	overlays = [ (import rust-overlay) ];
  	pkgs = import nixpkgs { inherit system overlays; };
  	rustVersion = pkgs.rust-bin.stable.latest.default;
	in {
  	devShell = pkgs.mkShell {
    	buildInputs =
      	[ (rustVersion.override { extensions = [ "rust-src" ]; }) ];
  	};
	});

Мы добавили

наложение ржавчины

что позволяет нам легко указывать разные версии ржавчины — и не полагаться на

nixpkgs

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

Мы также изменились outputs работаю только с devShellи этот вывод связан с nix develop. Запустив его, вы получите новую оболочку в песочнице со стабильной версией rust.

Если вы хотите использовать определенную версию / ночную версию, попробуйте rustVersion = (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml); чтобы прочитать инструментальный файл ржавчины. Работайте с указанной здесь версией.

Вы также можете заметить, что мы добавили .override { extensions = [ "rust-src" ]; }). Анализатору ржавчины нужен этот код, чтобы получить исходный код ржавчины.

Автоматическая загрузка среды Nix

Теперь, когда у нас есть интересующая нас версия rust, давайте автоматизируем этот шаг.

nix develop

.

Установить дирв И Никс-диренв. Второй компонент является необязательным, но помогает с кэшированием, поэтому я рекомендую вам использовать и его.

Direnv добавит квадратные скобки в вашу оболочку, поэтому, когда вы входите в свой проект через cdпроект автоматически загрузит для вас среду nix, без необходимости запуска nix develop.

В корне вашего проекта запустите:

$ echo "use flake" >> .envrc

$ direnv allow

В файл .envrc direnv будет загружен, а вывод снежинки будет использован для украшения вашего окружения. devShell. При изменении направления вашей снежинки загружайте только то, что изменилось.

Если вы работаете с VS Code, используйте селектор окружения nix, чтобы VS Code «знал» о снежинке. Без него можно обойтись, если открыть VS Code из командной строки, но настроить его несложно.

Собрать проект на Rust

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

$ cargo init

Затем вы можете запустить/создать проект, как обычно, с помощью cargo run/cargo build. Во время разработки все работает нормально, но давайте попробуем собрать проект с помощью nix. Это нам пригодится позже, на этапе сборки docker-образа.
Обновим результаты.

Flake.nix

outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }:
	flake-utils.lib.eachDefaultSystem (system:
  	let
    	overlays = [ (import rust-overlay) ];
    	pkgs = import nixpkgs { inherit system overlays; };
    	rustVersion = pkgs.rust-bin.stable.latest.default;
    	rustPlatform = pkgs.makeRustPlatform {
      	cargo = rustVersion;
      	rustc = rustVersion;
    	};
    	myRustBuild = rustPlatform.buildRustPackage {
      	pname =
        	"rust_nix_blog"; # make this what ever your cargo.toml package.name is
      	version = "0.1.0";
      	src = ./.; # the folder with the cargo.toml
      	cargoLock.lockFile = ./Cargo.lock;
    	};
  	in {
    	defaultPackage = myRustBuild;
    	devShell = pkgs.mkShell {
      	buildInputs =
        	[ (rustVersion.override { extensions = [ "rust-src" ]; }) ];
    	};
  	});

Сначала мы должны сделать

rustPlatform

с нашей версией ржавчины. На этой платформе можно собрать пакет ржавчины с

rustPlatform.buildRustPackage

. на никсе тоже самое

cargo build

. Нам понадобится

cargoLock.lockFile

так что nix может кэшировать все зависимости вашего проекта в зависимости от того, какой файл блокировки у вас есть.

Теперь вы можете сделать nix buildто ваш проект вернется в каталог result. В моем случае я могу сделать ./result/bin/rust_nix_blog.

Создайте образ Docker

Теперь, когда мы научили nix собирать проект rust, легко создать контейнер докеров.

Flake.nix

outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }:
	flake-utils.lib.eachDefaultSystem (system:
  	let
    	overlays = [ (import rust-overlay) ];
    	pkgs = import nixpkgs { inherit system overlays; };
    	rustVersion = pkgs.rust-bin.stable.latest.default;
    	rustPlatform = pkgs.makeRustPlatform {
      	cargo = rustVersion;
      	rustc = rustVersion;
    	};
    	myRustBuild = rustPlatform.buildRustPackage {
      	pname =
        	"rust_nix_blog"; # make this what ever your cargo.toml package.name is
      	version = "0.1.0";
      	src = ./.; # the folder with the cargo.toml
      	cargoLock.lockFile = ./Cargo.lock;
    	};
    	dockerImage = pkgs.dockerTools.buildImage {
      	name = "rust-nix-blog";
      	config = { Cmd = [ "${myRustBuild}/bin/rust_nix_blog" ]; };
    	};
  	in {
    	packages = {
      	rustPackage = myRustBuild;
      	docker = dockerImage;
    	};
    	defaultPackage = dockerImage;
    	devShell = pkgs.mkShell {
      	buildInputs =
        	[ (rustVersion.override { extensions = [ "rust-src" ]; }) ];
    	};
  	});

СЕЙЧАС

nix build

Или

nix build .#docker

создаст образ докера. После сборки

result

просто станет символической ссылкой на tar-файл с образом; в архиве, как и прежде, будет директория. Поскольку nix является декларативным, он не загружает этот файл в докер за вас. Вы можете скачать его самостоятельно с помощью:

$ docker load < result

На выходе вы должны получить rust-nix-blog:yyc9gd4nkydrikzpsvlp3gmwnpxhh1ik это изображение, загруженное с тегом.

Теперь давайте запустим образ с:

$ docker run rust-nix-blog:yyc9gd4nkydrikzpsvlp3gmwnpxhh1ik

Этот процесс можно несколько автоматизировать с помощью скрипта. (приведен немного измененный пример Здесь).

#!/usr/bin/env bash
set -e; set -o pipefail;
nix build '.#docker'
image=$((docker load < result) | sed -n '$s/^Loaded image: //p')
docker image tag "$image" rust-nix-blog:latest

использовать

окунать

чтобы увидеть картину. Подходит для временного использования

nix shell nixpkgs#dive

.

33 MB  └── nix
33 MB  	└── store
374 kB      	├─⊕ h4isr1pyv1fjdrxj2g80vsa4hp2hp76s-rust_nix_blog-0.1.0
1.8 MB      	├─⊕ ik4qlj53grwmg7avzrfrn34bjf6a30ch-libunistring-1.0
246 kB      	├─⊕ w3zngkrag7vnm7v1q8vnqb71q6a1w8gn-libidn2-2.3.2
30 MB      	└─⊕ ybkkrhdwdj227kr20vk8qnzqnmj7a06x-glibc-2.34-115

Глядя на вывод, мы видим, что это однослойный образ, который содержит только самый минимум для запуска бинарного файла (в нашем случае только libc и код ржавчины).

Распространенные проблемы с устранением неполадок

Нержавеющие строительные постройки

Как только сборка nix настроена, и это здорово, она больше никогда не выйдет из строя. Но доведение его до рабочего состояния – процесс порой болезненный. Если ваш код rust зависит от системных пакетов (например, OpenSSL), не забудьте включить их, например, в.

buildInputs

.

rustPlatform.buildRustPackage {
  pname =
	"rust_nix_blog"; # make this what ever your cargo.toml package.name is
  version = "0.1.0";
  src = ./.; # the folder with the cargo.toml
  nativeBuildInputs = [pkgs.pkg-config ]; # just for the host building the package
  buildInputs = [pkgs.openssl]; # packages needed by the consumer
  cargoLock.lockFile = ./Cargo.lock;
};

Специально для OpenSSL я бы рекомендовал по возможности использовать rustls. Сборка с ним проще, да и написано на ржавчине.

Нет документации

Документация Nix не самая лучшая. Да, некоторую информацию можно найти в

вики

И

руководства

, я думаю, что лучший материал находится в различных блогах nix. Вот несколько хороших ссылок:

  • Машина написан в основном на nixos, дистрибутиве Linux на основе nix. Но по его статьям удобно учить язык и его общие закономерности.
  • Блог Яна Генри по обучению nix — цикл статей о том, как сам автор обучал nix. Это не столько документация, сколько избранные заметки о прогрессе при использовании nix.
  • Введение в снежинки nix. Отличный сборник из трех частей о том, что такое снежинки и как с ними работать.
  • Создание контейнеров Docker с помощью nix. Я ссылался на этот источник раньше, но я упомяну его снова, потому что это хороший справочник по дополнительным параметрам, используемым при создании контейнеров.

Я также настоятельно рекомендую покопаться в nix самостоятельно после того, как вы освоите Nixos как работающий дистрибутив Linux. Так вам будет легче освоить язык и быстро перейти к его использованию, когда у вас будет полная картина.

Source

ЧИТАТЬ   Управление состоянием Vue: Pinia или составные хранилища с глобальными ссылками?

От admin