什么是nix-instantiate有用?什么是商店推导?

jhe*_*dus 12 nixos nix

手册中写道:

命令nix-instantiate从(高级)Nix表达式生成存储派生.

但什么是商店派生?

手册中说明了以下关于商店派生的内容:

构建操作的描述.派生的结果是商店对象.通常使用派生原语在Nix表达式中指定派生.这些被转换为低级存储派生(由nix-env和nix-build隐式,或由nix-instantiate显式)

这对于nix-newbee来说有点难以理解,我发现通过谷歌搜索没有更多关于nix-instantiate和store派生的启发.我也问#nixos,我没有回答.

有人可以在一个简单的例子中解释一下商店派生是什么,它用于什么?

为什么要使用nix-instantiate生成商店派生?你能给出一个超级简单易懂的例子吗?

小智 30

什么是nix-instantiate有用?

命令nix-instantiate唯一的目的是评估Nix表达式.Nix语言的主要目的是生成派生.

什么是商店推导?

派生(参见示例)是用于构建(实现)包的构建配方的计算机友好表示.它们是具有扩展名的文件.drv,通常在商店目录中列出/nix/store.

Nix守护程序可以理解这些构建配方,并用于确保在之前构建所有依赖项并将其存储在预先计算的路径中.一旦成功编译了所有依赖项,Nix守护程序就可以查找替换,或者在本地实现派生.所有详细的解释都可以在Eelco Dolstra博士论文中找到.

nix-instantiate除非derivation提供命令行选项,否则每次nix-instantiate命令评估Nix语言的功能时都会创建这些文件.

为什么要使用nix-instantiate生成商店派生?

如果你对构建输出感兴趣,你应该更喜欢--eval,这相当于:

nix-instantiate

在某些情况下,您对构建结果不感兴趣,但在查看编译时依赖性时.例如,如果您希望调查hello的构建时依赖性.然后使用nix-store命令,如下所示,您可以请求构建配方的所有依赖项:

nix-build


tor*_*tte 5

所有引用均来自Eelco Dolstra 的博士论文

存储派生

商店推导Nix的表达 被移除并且所有的变异翻译 成另一种格式。这种中间表示“描述了一个单一的、静态的、恒定的构建动作”,它可以被构建到软件组件中。

Nix 表达式通常转化为商店派生图。

换个说法,

*------------------------------------------------------*
|                                                      |
| NIX EXPRESSION == function                           |
|                                                      |
| ( Describes how to build a component. That is, how ) |
| ( to  compose  its  input parameters, which can be ) |
| ( other components as well.                        ) |
|                                                      |
| STORE DERIVATION == function application             |
|                                                      |
| ( Result of a Nix expression called with concrete arguments. ) |
| ( Corollary: a single Nix  expression  can produce ) |
| ( different derivations depending on the inputs.   ) |
|                                                      |
*------------------------------------------------------*
Run Code Online (Sandbox Code Playgroud)

对于上下文:

Nix 表达式的两阶段构建。 nix-instantiate 将 Nix 表达式转换为 store 派生,而 nix-store --realize 将派生构建到软件组件中。 图片取自“2.4 Store derivations”部分。


论文将 Nix 表达式描述为“构建操作系列”,与“完全是一个构建操作”的派生相反。

                              ARG_1, ..., ARG_N

                        | ---(aaa, ...)---> DERIVATION_1
        NIX EXPRESSION  | ---(bbb, ...)---> DERIVATION_2
                        |       :
           function(    |       :
             param_1,   |       :
             ...,       |       :
             param_N    |       :
             )          |       :
                        | ---(zzz, ...)---> DERIVATION_N
Run Code Online (Sandbox Code Playgroud)

上面的派生可能会生成相同的应用程序,但会使用不同的配置选项来构建它,例如。(见APT包vim-noxvim-gtkvim-gtk3vim-tiny,等)

为什么叫“推导”?

它的名字来自“ 2.2 Nix 表达式”:

函数的结果 [即 Nix 表达式] 是一个 推导。这是组件构建操作的Nix-speak ,它 从其输入派生组件。

为什么需要“商店派生”?

2.4 Store derivations ”部分包含所有详细信息,但要点如下:

Nix 表达式不是直接构建的;相反,它们被翻译成更原始的商店派生语言,它对单个组件构建操作进行编码。这类似于编译器通常在被编译代码的更简单的中间表示上完成大部分工作的方式,而不是在具有所有复杂性的成熟语言上。

商店派生的格式

来自“5.4. 翻译 Nix 表达式以存储派生”部分:

存储派生的抽象语法如图 5.5 所示,采用类似 Haskell 的 [135] 语法(参见第 1.7 节)。图 2.13 所示的商店派生示例是这种数据类型的值。

图 5.5.:商店派生的抽象语法

 data StoreDrv = StoreDrv {    
   output : Path,              
   outputHash : String,        
   outputHashAlgo : String,    
   inputDrvs : [Path],         
   inputSrcs : [Path],         
   system : String,            
   builder : Path,             
   args : [String],            
   envVars : [(String,String)] 
 }                             
Run Code Online (Sandbox Code Playgroud)

例子

例如,构建Hello 图 2.6 中的包的 Nix 表达式,

图 2.6

*------------------------------------------------------*
|                                                      |
| NIX EXPRESSION == function                           |
|                                                      |
| ( Describes how to build a component. That is, how ) |
| ( to  compose  its  input parameters, which can be ) |
| ( other components as well.                        ) |
|                                                      |
| STORE DERIVATION == function application             |
|                                                      |
| ( Result of a Nix expression called with concrete arguments. ) |
| ( Corollary: a single Nix  expression  can produce ) |
| ( different derivations depending on the inputs.   ) |
|                                                      |
*------------------------------------------------------*
Run Code Online (Sandbox Code Playgroud)

将产生类似于图 2.13 的中间表示:

图 2.13 Store 派生

{ output = "/nix/store/bwacc7a5c5n3...-hello-2.1.1" 25
, inputDrvs = { 26
    "/nix/store/7mwh9alhscz7...-bash-3.0.drv",
    "/nix/store/fi8m2vldnrxq...-hello-2.1.1.tar.gz.drv",
    "/nix/store/khllx1q519r3...-stdenv-linux.drv",
    "/nix/store/mjdfbi6dcyz7...-perl-5.8.6.drv" 27 }
  }
, inputSrcs = {"/nix/store/d74lr8jfsvdh...-builder.sh"} 28
, system = "i686-linux" 29
, builder = "/nix/store/3nca8lmpr8gg...-bash-3.0/bin/sh" 30
, args = ["-e","/nix/store/d74lr8jfsvdh...-builder.sh"] 31
, envVars = { 32
    ("builder","/nix/store/3nca8lmpr8gg...-bash-3.0/bin/sh"),
    ("name","hello-2.1.1"),
    ("out","/nix/store/bwacc7a5c5n3...-hello-2.1.1"),
    ("perl","/nix/store/h87pfv8klr4p...-perl-5.8.6"), 33
    ("src","/nix/store/h6gq0lmj9lkg...-hello-2.1.1.tar.gz"),
    ("stdenv","/nix/store/hhxbaln5n11c...-stdenv-linux"),
    ("system","i686-linux"),
    ("gtk","/store/8yzprq56x5fa...-gtk+-2.6.6"),
  }
}
Run Code Online (Sandbox Code Playgroud)

存储派生的抽象语法如图 5.5 所示,采用类似 Haskell 的 [135] 语法(参见第 1.7 节)。图 2.13 所示的商店派生示例是这种数据类型的值。

图 5.5.:商店派生的抽象语法

 data StoreDrv = StoreDrv {    
   output : Path,              
   outputHash : String,        
   outputHashAlgo : String,    
   inputDrvs : [Path],         
   inputSrcs : [Path],         
   system : String,            
   builder : Path,             
   args : [String],            
   envVars : [(String,String)] 
 }                             
Run Code Online (Sandbox Code Playgroud)