Flakes 是 Nix 生态系统中的一项新功能。 Flakes 取代了有状态的通道(这在新手中会引起很多困惑)并引入了更直观和一致的 CLI 界面,使它们成为开始使用 Nix 的绝佳机会。

这篇文章是对 Nix 本身和特别是 flakes 功能的快速介绍。它包含有关在实际用例中使用 flakes 的示例和建议:以各种语言构建应用程序。

Nix 是什么?

简单地说,Nix 是一个包管理器和一个构建系统。它最重要的方面是允许为可重现的软件构建编写声明性脚本。它还有助于在使用函数式编程范例的同时测试和部署软件系统。 Nix 有一个庞大的软件包存储库,称为nixpkgs,还有一个将 Nix 的想法扩展到操作系统级别的 GNU/Linux 发行版,称为NixOS。

Nix 构建指令称为“派生”,是用编程语言 Nix 编写的。可以为包甚至整个系统编写派生。之后,它们可以通过包管理器 Nix 确定性地“实现”(构建)。推导只能依赖于一组预定义的输入,因此它们在某种程度上是可重现的。

您可以在我关于 Nix](https://serokell.io/blog/what-is-nix)的博客文章[中阅读更多关于 Nix 的好处。

什么是 Nix 薄片?

Flakes 是独立的单元,具有输入(依赖项)和输出(包、部署说明、用于其他 flakes 的 Nix 函数)。您可以将它们视为 Rust crates 或 Go 模块,但与语言无关。 Flakes 具有很好的可重复性,因为它们只允许依赖于它们的输入,并且它们将所述输入的确切版本固定在锁定文件中。

如果您已经熟悉 Nix,那么对于 Nix 表达式来说,flakes 就是构建指令的派生。

Nix 入门

为了用 flakes 做任何事情,你首先必须让“不稳定”的 Nix 在你的机器上运行。不要介意它被称为不稳定:在您的机器上运行通常并不危险,它只是比“稳定”更频繁地变化。最简单的方法是使用官方安装程序,它适用于任何 Linux 发行版、macOS 或适用于 Linux 的 Windows 子系统:

curl -L https://nixos.org/nix/install | sh

进入全屏模式 退出全屏模式

按照说明进行操作,直到 Nix 在您的机器上运行,然后使用以下命令更新到不稳定:

nix-env -f '<nixpkgs>' -iA nixUnstable

进入全屏模式 退出全屏模式

并通过以下方式启用实验性功能:

mkdir -p ~/.config/nix
echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf

进入全屏模式 退出全屏模式

如果您正在使用 NixOS 或在安装时遇到问题,请查阅 NixOS wiki:https://nixos.wiki/wiki/flakes#Installing_flakes

感受薄片

现在您已经安装了一个“不稳定”的 Nix,是时候使用它了!

nix shell

首先,让我们进入一个 shell,其中包含来自 nixpkgs 分支nixpkgs-unstable的 GNU Hello:

nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello

进入全屏模式 退出全屏模式

请注意,这将启动与您正在运行的相同的 shell,但是将包含hello可执行文件的目录添加到您的$PATH。shell 看起来应该与nix shell之外的样子没有任何不同,所以如果它看起来像什么都没有发生!可执行文件本身并没有安装在任何地方,它会被下载并解压缩到您可以考虑的缓存目录中。

现在,在那个 shell 中,尝试运行hello

让我们看看这个命令的作用。nix shell是一个 nix 子命令,用于运行带有$PATH中可用的一些包的 shell。这些包可以指定为“可安装”格式的参数。每个可安装文件包含两部分:URL(本例中为github:nixos/nixpkgs/master)和“属性路径”(此处为hello)。

支持一些 URL 方案:

  • github:owner/repo/ 100042 revision or branch]gitlab:owner/repo/[revision or branch](用于 github.com和gitlab.com上的公共存储库;请注意,分支名称不能包含斜杠)。

  • https://example.com/path/to/tarball.tar.gz用于压缩包。

  • git+https://example.com/path/to/repo.gitgit+ssh://example.com/path/to/repo.git用于普通 git 存储库(当然,您可以将其用于 GitHub 和 GitLab)。您可以通过添加?ref=<branch name here>来指定分支或修订。

  • file:///path/to/directory/path/to/directory./path/to/relative/directory用于本地目录。

  • flake-registry-value表示来自 flake 注册表的值(我不会在本文中讨论 flake 注册表)。

因此,还有一些其他方法可以获得相同的 shell:

nix shell https://github.com/nixos/nixpkgs/archive/nixpkgs-unstable.tar.gz#hello
nix shell 'git+https://github.com/nixos/nixpkgs?ref=nixpkgs-unstable#hello'
nix shell nixpkgs#hello # nixpkgs is specified in the default registry to be github:nixos/nixpkgs

进入全屏模式 退出全屏模式

至于属性路径,就目前而言,只要知道它是一个以句点分隔的 Nix “属性名称”列表,它根据一些简单的逻辑选择一个薄片输出。

请注意,在这种情况下,Nix 不必构建任何东西,因为它可以从二进制缓存中获取 GNU Hello 及其依赖项。为了实现这一点,Nix 从表达式中求值一个 derivation,对其内容进行哈希处理,并查询它知道的所有缓存,看看是否有人缓存了这个哈希的派生。 Nix 使用所有依赖项和所有指令作为此哈希的输入!如果某些二进制缓存已准备好版本,则可以_替换_(下载)。否则,Nix 将通过首先实现(替换或构建)所有依赖项然后执行构建指令来构建派生。

您可能想知道可执行文件到底安装在哪里。好吧,尝试command -v hello看看它位于/nix/store的子目录中。事实上,所有 Nix _派生_都有“存储路径”(位于/nix/store中的路径)作为输入和输出。

nix build

如果您只是想构建一些东西而不是使用它进入 shell,请尝试nix build:

$ nix build nixpkgs#hello

进入全屏模式 退出全屏模式

这将构建 Hello(或从二进制缓存中获取它,如果可用),然后将其符号链接到当前目录中的result。然后您可以探索result,例如

$ ./result/bin/hello
Hello, world!

进入全屏模式 退出全屏模式

nix develop

尽管使用了二进制缓存,但 Nix 是一个源代码优先的包管理器。这意味着它有能力为其派生提供构建环境。因此,您可以使用 Nix 为您管理构建环境!要进入具有 GNU Hello 的所有运行时和构建时依赖项的 shell,请使用:

$ nix develop nixpkgs#hello

进入全屏模式 退出全屏模式

在该 shell 中,您可以调用unpackPhase将 GNU Hello 源代码放置在当前目录中,然后调用configurePhase以使用正确的参数运行configure脚本,最后调用buildPhase来构建。

nix profile

Nix 实现了有状态的“配置文件”以允许用户“永久”安装东西。

例如:

nix profile install nixpkgs#hello
nix profile list
nix profile update hello
nix profile remove hello

进入全屏模式 退出全屏模式

如果您已经熟悉 Nix,这是nix-env的替代品。

nix flake

nix flake组子命令用于观察和操作薄片本身,而不是它们的输出。

nix flake show

此命令采用 flake URI 并将 flake 的所有输出打印为一个漂亮的树结构,将属性路径映射到值的类型。

例如:

$ nix flake show github:nixos/nixpkgs
github:nixos/nixpkgs/d1183f3dc44b9ee5134fcbcd45555c48aa678e93
├───checks
│ └───x86_64-linux
│ └───tarball: derivation 'nixpkgs-tarball-21.05pre20210407.d1183f3'
├───htmlDocs: unknown
├───legacyPackages
│ ├───aarch64-linux: omitted (use '--legacy' to show)
│ ├───armv6l-linux: omitted (use '--legacy' to show)
│ ├───armv7l-linux: omitted (use '--legacy' to show)
│ ├───i686-linux: omitted (use '--legacy' to show)
│ ├───x86_64-darwin: omitted (use '--legacy' to show)
│ └───x86_64-linux: omitted (use '--legacy' to show)
├───lib: unknown
└───nixosModules
    └───notDetected: NixOS module

进入全屏模式 退出全屏模式

nix flake clone

nix flake clone将 flake 源克隆到本地目录,类似于git clone

让我们克隆一些简单的 flake 并在其上使用其他一些nix flake子命令:

nix flake clone git+https://github.com/balsoft/hello-flake/ -f hello-flake
cd hello-flake

进入全屏模式 退出全屏模式

nix flake lock(以前是nix flake update)

每次您在本地目录中的某个薄片上调用 Nix 命令时,Nix 都会确保flake.lock的内容满足flake.nix中的inputs。如果您只想这样做,而无需实际构建(甚至评估)任何输出,请使用nix flake lock

还有一些用于 flake 输入操作的参数可以传递给大多数 Nix 命令:

  • --override-input采用您在flake.nixinputs中指定的输入名称和作为此输入提供的片状 URI; ---update-input将采用输入名称并将该输入更新为满足来自flake.nix的片状 URI 的最新版本。

自己写

现在您知道如何与 flakes 交互,是时候写一个了。

Nix 语言进修

Nix 中广泛使用的数据类型是属性集:一种用于存储键值对的数据类型。它类似于许多语言中的 JSON 对象或 hashmap。它的语法类似于 C 语言中的语句列表,令人困惑:

{
  hello = "world";
  foo = "bar";
}

进入全屏模式 退出全屏模式

上面的集合等价于这个 JSON 对象:

{
    "hello": "world",
    "foo": "bar"
}

进入全屏模式 退出全屏模式

hellobar通常称为“属性”或“属性名称”;"world""bar"是“属性值”。

要从属性集中获取属性值,请使用.。例如:

let
  my_attrset = { foo = "bar"; };
in my_attrset.foo

进入全屏模式 退出全屏模式

(let ... in是一种创建绑定的方法;其中的语法与属性集的语法相同)

您还可以通过使用.设置特定属性来缩写您的属性集,而不是定义整个集:

{
  foo.bar = "baz";
}

进入全屏模式 退出全屏模式

相当于

{
  foo = { bar = "baz"; };
}

进入全屏模式 退出全屏模式

其他类型包括字符串 ("foo")、数字 (1, 3.1415)、异构列表 ([1 2 "foo"]) 和 - 非常重要的 - 函数 (x: x + 1)。

函数支持属性集的模式匹配。例如,这个函数:

{ a, b }: a + b

进入全屏模式 退出全屏模式

使用{ a = 10; b = 20; }调用时将返回 30。

函数应用以 ML 风格完成:

let
  f = { a, b }: a + b;
in f { a = 10; b = 20; }

进入全屏模式 退出全屏模式

功能本身是第一位的。然后是一个以空格分隔的参数列表。

如果你想要一个有多个参数的函数,使用currying:

let
  f = a: b: a + b;
in f 10 20

进入全屏模式 退出全屏模式

在此示例中,f 10计算为b: 10 + b,然后f 10 20计算为30

如果您想了解有关 Nix 的更多信息,请查看相应的手册部分和Nix Pills。

基本薄片结构

您在上面得到的语言描述远非完整或正式,但它应该可以帮助您理解,更重要的是,编写一些简单的 Nix 表达式,更重要的是,一个薄片。

Nix flake 是一个包含flake.nix文件的目录。该文件必须包含一个具有一个必需属性的属性集 -outputs- 以及可选的descriptioninputs

outputs是一个接受一组输入属性集的函数(总是至少有一个输入——self——指的是 Nix 当前正在评估的薄片;这可能是由于懒惰)。所以,最简单的薄片可能是这样的:

{
  outputs = { self }: { };
}

进入全屏模式 退出全屏模式

这是一个没有外部输入和输出的薄片。不太好用吧?

好吧,我们可以向它添加一个任意输出并用nix eval对其进行评估以查看它是否有效:

{
  outputs = { self }: {
    foo = "bar";
  };
}


$ nix eval .#foo
"bar"

进入全屏模式 退出全屏模式

不过,仍然不是很有用。

让我们做一个有用的薄片!为此,我们很可能需要一些输入:

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
  };

  outputs = { self, nixpkgs }: { };
}

进入全屏模式 退出全屏模式

仍然不是很有用;我们没有任何输出!但是,现在有一个外部nixpkgs输入。

虽然outputs返回的属性集可能包含任意属性,但各种nix实用程序可以理解一些标准输出。例如,有一个包含包的packages输出。它适用于Getting a feel for flakes中描述的命令。让我们添加它!

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
  };

  outputs = { self, nixpkgs }: {
    packages.x86_64-linux.hello = /* something here */;
  };
}

进入全屏模式 退出全屏模式

首先,让我们了解一下为什么这里需要x86_64-linux。 Flakes 向我们承诺_hermetic evaluation_,这意味着无论评估者的环境如何,一个flakes 的输出都应该是相同的。与构建系统非常相关的评估环境的一个特殊属性是_platform_(架构和操作系统的组合)。因此,所有与包有关的 flake 输出都必须以某种方式明确指定平台。标准方法是使输出成为一个属性集,名称是平台,值是输出语义上表示的任何内容,但专门为该平台构建。在packages的情况下,每个平台值都是一组属性。

您现在可能会想:那么,我们如何在不明确指定平台的情况下只写nix build nixpkgs#hello并获得一个包?嗯,那是因为 Nix 实际上是在幕后为你做的。对于nix shellnix buildnix profilenix develop(以及其他一些命令),Nix 试图通过按特定顺序尝试多个来找出您想要的输出。假设您在运行 Linux 的 x86_64 机器上执行nix build nixpkgs#hello。然后 Nix 会尝试:

  • hello

  • packages.x86_64-linux.hello

  • legacyPackages.x86_64-linux.hello

我们已经熟悉packages输出;legacyPackages是专门为 nixpkgs 设计的。 nixpkgs 存储库比 flake 旧得多,因此不可能将其任意属性格式转换为整洁的packageslegacyPackages旨在容纳遗留的混乱。特别是,legacyPackages允许每个平台的包集是任意属性集,而不是结构化包。

所以,让我们在我们自己的 flake 中从 nixpkgs 重新导出hello:

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
  };

  outputs = { self, nixpkgs }: {
    packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
  };
}

进入全屏模式 退出全屏模式

现在我们可以构建重新导出的包:

$ nix build .#hello

进入全屏模式 退出全屏模式

或者运行它:

$ nix run .#hello
Hello, world!

进入全屏模式 退出全屏模式

(默认情况下,nix run会执行与包的属性名同名的二进制文件。)

万岁!现在我们有一个 flake 可以输出我们可以使用或构建的包。

我们可以添加的另一件事是“开发”外壳,其中包含一些在处理我们的薄片时可能有用的实用程序。在这个例子中,也许我们希望在$PATH中有hellocowsay来打印友好的问候语,然后让牛说出来。此类开发 shell 有一个特殊的输出,称为devShell。还有一个用于在 nixpkgs 中构建此类 shell 的函数。为了防止多次写入笨拙的nixpkgs.legacyPackages.x86_64-linux,让我们通过let ... in绑定来提取它:

{
  inputs = { nixpkgs.url = "github:nixos/nixpkgs"; };

  outputs = { self, nixpkgs }:
    let pkgs = nixpkgs.legacyPackages.x86_64-linux.hello;
    in {
      packages.x86_64-linux.hello = pkgs.hello;

      devShell.x86_64-linux =
        pkgs.mkShell { buildInputs = [self.packages.x86_64-linux.hello pkgs.cowsay]; };
   };
}

进入全屏模式 退出全屏模式

现在我们可以使用nix develop进入开发环境。如果要在该环境中运行 Bash 以外的 shell,可以使用nix shell -c $SHELL

$ nix develop -c $SHELL
$ hello | cowsay
 _______________
< Hello, world! >
 ---------------
        \ ^__^
         \ (oo)\ _______
            (__)\ )\/\
                ||----w |
                || ||

进入全屏模式 退出全屏模式

让我们使用nix flake show检查我们的薄片:

$ nix flake show
path:/path/to/flake
├───devShell
│ └───x86_64-linux: development environment 'nix-shell'
└───packages
      └───x86_64-linux
            └───hello: package 'hello-2.10'

进入全屏模式 退出全屏模式

现在我们已经编写了稍微有用的“hello”薄片,是时候开始实际应用了!

一些提示和技巧

您可以使用direnv和nix-direnv当您将目录更改为打包在薄片中的项目时自动输入devShell。在这种情况下,.envrc文件非常简单:

use flake

进入全屏模式 退出全屏模式

薄片实用程序

有一个库可以帮助您提取无聊的每个平台的属性:flake-utils。如果我们在示例 flake 中使用 flake-utils,我们可以让它支持所有 nixpkgs 平台,几乎不需要额外的代码:

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let pkgs = nixpkgs.legacyPackages.${system};
      in {
        packages.hello = pkgs.hello;

        devShell = pkgs.mkShell { buildInputs = [pkgs.hello pkgs.cowsay]; };
      });
}

进入全屏模式 退出全屏模式

请注意,现在nix flake show的输出中有更多平台:

path:/path/to/flake
├───devShell
│ ├───aarch64-linux: development environment 'nix-shell'
│ ├───i686-linux: development environment 'nix-shell'
│ ├───x86_64-darwin: development environment 'nix-shell'
│ └───x86_64-linux: development environment 'nix-shell'
└───packages
      ├───aarch64-linux
      │ └───hello: package 'hello-2.10'
      ├───i686-linux
      │ └───hello: package 'hello-2.10'
      ├───x86_64-darwin
      │ └───hello: package 'hello-2.10'
      └───x86_64-linux
             └───hello: package 'hello-2.10'

进入全屏模式 退出全屏模式

所有平台属性都由 flake-utils 自动插入。

打包现有应用程序

薄片最明显的用例是打包现有应用程序以获得 Nix 生态系统的好处。为此,我编写了一个模板库,您可以将其与nix flake init -t一起使用。本节主要介绍如何调整模板以正确构建您的应用程序。

Haskell (阴谋集团)

Haskell 在 Nix 生态系统中普遍存在。 Nixpkgs 包含一个完整的 Hackage 镜像,并且有多种工具可以帮助使用 Nix 构建 Haskell 应用程序。

使用 Nix 构建 Haskell 应用程序最流行的方法是cabal2nix。它从项目的 cabal 文件中提取依赖信息,并使用 nixpkgshaskellPackages集合来解决这些依赖关系。

要将其添加到您现有的 Haskell 应用程序中,请执行以下操作:

nix flake init -t github:serokell/templates#haskell-cabal2nix

进入全屏模式 退出全屏模式

它将创建一个与此类似的flake.nix(注意throw <...>替换名称;在那里写下您的项目名称)。

{
  description = "My haskell application";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};

        haskellPackages = pkgs.haskellPackages;

        jailbreakUnbreak = pkg:
          pkgs.haskell.lib.doJailbreak (pkg.overrideAttrs (_: { meta = { }; }));

        packageName = throw "put your package name here!";
      in {
        packages.${packageName} = # (ref:haskell-package-def)
          haskellPackages.callCabal2nix packageName self rec {
            # Dependency overrides go here
          };

        defaultPackage = self.packages.${system}.${packageName};

        devShell = pkgs.mkShell {
          buildInputs = with haskellPackages; [
            haskell-language-server
            ghcid
            cabal-install
          ];
          inputsFrom = builtins.attrValues self.packages.${system};
        };
      });
}

进入全屏模式 退出全屏模式

使用薄片

您可以使用nix build构建defaultPackage,并执行所有其他常规操作:nix shellnix develop等。

潜在的修改和故障排除

除非您需要devShell中提供的一些开发工具(例如语言服务器或 ghcid),否则只需将它们删除即可。

如果您需要不同版本的 GHC,请在haskellPackages定义中选择它,例如,要使用 GHC 9.0.1,请执行以下操作:

haskellPackages = pkgs.haskell.packages.ghc901;

进入全屏模式 退出全屏模式

如果某些依赖项无法构建,您需要在包定义中覆盖它(准确地说是callCabal2nix的最后一个参数)。例如,如果您的项目依赖于gi-gtk-declarative,并且由于某些版本约束不匹配而在当前版本的 nixpkgs 中被破坏,请执行以下操作(将失败的包名称替换为gi-gtk-declarative):

# <...>
packages.${packageName} =
  haskellPackages.callCabal2nix packageName self rec {
    gi-gtk-declarative =
      jailbreakUnbreak haskellPackages.gi-gtk-declarative;
  };
# <...>

进入全屏模式 退出全屏模式

注意:jailbreakUnbreak仅删除 cabal 版本约束。如果某些依赖项中存在实际的重大更改,则构建仍然会失败。在这种情况下,您只能尝试解决软件包的实际问题,这需要对overrideAttrs的工作原理有所了解,这超出了本教程的范围。不要害怕阅读 nixpkgs 手册或在你能找到的任何 Nix 社区寻求帮助!

如果某些依赖项由于测试失败而无法构建(这可能是测试需要网络访问或 Nix 构建中不可用的本地资源的情况),您可以像这样禁用它们:

# <...>
packages.${packageName} =
  haskellPackages.callCabal2nix packageName self rec {
    gi-gtk-declarative =
      pkgs.haskell.lib.dontCheck haskellPackages.gi-gtk-declarative;
  };
# <...>

进入全屏模式 退出全屏模式

其他构建选项

使用 Nix 构建 Haskell 应用程序和库的其他一些选项:

  • haskell.nix

锈(货物)

Rust 在 Nix 社区中也很受欢迎,尽管由于年龄相对较小,目前集成还没有那么好。有多种竞争方式来构建板条箱。我更喜欢crate2nix的工作方式:它在操作上与 cabal2nix 非常相似,但由于某些 Cargo 特性,它有点复杂。

要获得通过 crate2nix 构建单个 Cargo crate 的模板,请运行nix flake init -t github:serokell/templates#rust-crate2nixflake.nix将类似于此文件:

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
    crate2nix = {
      url = "github:kolloch/crate2nix";
      flake = false;
    };
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, crate2nix, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        crateName = throw "Put your crate name here";

        inherit (import "${crate2nix}/tools.nix" { inherit pkgs; })
          generatedCargoNix;

        project = pkgs.callPackage (generatedCargoNix {
          name = crateName;
          src = ./.;
        }) {
          defaultCrateOverrides = pkgs.defaultCrateOverrides // {
            # Crate dependency overrides go here
          };
        };

      in {
        packages.${crateName} = project.rootCrate.build;

        defaultPackage = self.packages.${system}.${crateName};

        devShell = pkgs.mkShell {
          inputsFrom = builtins.attrValues self.packages.${system};
          buildInputs = [pkgs.cargo pkgs.rust-analyzer pkgs.clippy];
        };
      });
}

进入全屏模式 退出全屏模式

故障排除和改进

假设你的包需要一些“本机”(非 Rust)库,要么是自身的,要么是通过依赖传递的。在这种情况下,您必须手动将它们指定为defaultCrateOverrides,除非它们已经在 nixpkgs 的defaultCrateOverrides中指定。例如,如果您的应用程序调用my-music-player需要libpulseaudio,

# <...>
defaultCrateOverrides = pkgs.defaultCrateOverrides // {
  my-music-player = _: {
    buildInputs = [pkgs.libpulseaudio];
  };
}
#<...>

进入全屏模式 退出全屏模式

替代品

  • 手动使用来自 nixpkgs 的buildRustCrate

  • 挪威语

Python(诗)

通过python3Packages在 nixpkgs 中某种程度上支持 Python 生态系统,但支持不如 Haskell 完整。但是,如果您的项目是用诗歌打包的,那么您很幸运,因为有poetry2nix可以让您轻松构建应用程序。

初始化模板,nix flake init -t github:serokell/templates#python-poetry2nix。它看起来像这样:

{
  description = "My Python application";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};

        customOverrides = self: super: {
          # Overrides go here
        };

        app = pkgs.poetry2nix.mkPoetryApplication {
          projectDir = ./.;
          overrides =
            [pkgs.poetry2nix.defaultPoetryOverrides customOverrides];
        };

        packageName = throw "put your package name here";
      in {
        packages.${packageName} = app;

        defaultPackage = self.packages.${system}.${packageName};

        devShell = pkgs.mkShell {
          buildInputs = with pkgs; [poetry];
          inputsFrom = builtins.attrValues self.packages.${system};
        };
      });
}

进入全屏模式 退出全屏模式

故障排除

如果某些依赖项无法构建,您需要通过在customOverrides中覆盖它来修复它。有关各种示例覆盖,请参阅https://github.com/nix-community/poetry2nix/blob/master/overrides.nix。

下一个

在即将发表的文章中,我将解释如何使用 Flakes 来构建和运行容器以及设置基础设施部署。为了确保您听到它,您可以在Twitter上关注 Serokell。敬请关注!

Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐