【问题标题】:What is the purpose of nix-instantiate? What is a store-derivation?nix-instantiate 的目的是什么?什么是商店派生?
【发布时间】:2015-10-08 00:39:04
【问题描述】:

manual 中写着:

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

但是什么是商店派生?

手册中关于store derivations 的内容如下:

构建操作的描述。一个派生的结果是一个 store 目的。推导通常在 Nix 表达式中使用 推导原语。这些被翻译成低级存储 推导(通过nix-envnix-build 隐含,或通过 nix-instantiate)

对于 nix-newbee 来说,这有点难以理解,我发现没有什么比 nix-instantiate 更有启发性了,并通过谷歌搜索存储派生。我也在#nixos 上问过,但我没有得到答案。

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

为什么要使用nix-instantiate 生成存储派生?你能举一个超级简单易懂的例子吗?

【问题讨论】:

标签: nixos nix


【解决方案1】:

nix-instantiate 有什么用?

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

什么是存储派生?

派生 (see example) 是用于构建(实现)包的构建配方的计算机友好表示。它们是存储目录中列出的扩展名为.drv 的文件,通常为/nix/store

这些构建配方被 Nix 守护进程理解,并用于确保所有依赖项都在之前构建,并存储在预先计算的路径中。一旦成功编译所有依赖项,Nix 守护进程就可以寻找替代,或者在本地实现派生。所有详细的解释都在Eelco Dolstra PhD Thesis

这些文件是在每次nix-instantiate 命令评估 Nix 语言的 derivation 函数时创建的,除非提供了 --eval 命令行选项。

为什么要使用nix-instantiate 生成存储派生?

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

$ nix-store -r $(nix-instantiate '<nixpkgs>' -A hello)

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

$ nix-store --tree -q $(nix-instantiate '<nixpkgs>' -A hello)

【讨论】:

  • @jhegedus:如果此答案回答了您的疑问,请接受。这是Many thanks 的一种stackoverflow 方式。
【解决方案2】:

所有引用均来自Eelco Dolstra's PhD thesis

存储派生

商店派生Nix expression,所有 可变性被移除并翻译成另一种格式。 这个中间表示“描述了一个 单个、静态、恒定的构建操作”,可以构建到软件组件中。

"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.   ) |
|                                                      |
*------------------------------------------------------*

对于上下文:

图片取自“2.4 Store derivations”部分。


thesis 将 Nix 表达式描述为 “构建操作系列”,与 “正是一个构建操作”的派生。

                              ARG_1, ..., ARG_N

                        | ---(aaa, ...)---> DERIVATION_1
        NIX EXPRESSION  | ---(bbb, ...)---> DERIVATION_2
                        |       :
           function(    |       :
             param_1,   |       :
             ...,       |       :
             param_N    |       :
             )          |       :
                        | ---(zzz, ...)---> DERIVATION_N

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

为什么叫“派生”?

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

函数的结果[即Nix表达式] 是一个派生。这是尼克斯的代言人 组件构建操作派生 来自其输入的组件。

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

2.4 存储派生”部分包含所有 细节,但这是要点:

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)] 
 }                             

示例

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

图 2.6

{stdenv, fetchurl, perl}:

stdenv.mkDerivation {
  name = "hello-2.1.1";
  builder = ./builder.sh;
  src = fetchurl {
    url = http://ftp.gnu.org/pub/gnu/hello/hello-2.1.1.tar.gz;
    md5 = "70c9ccf9fac07f762c24f2df2290784d";
  };
  inherit perl;
}

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

图 2.13 存储推导

{ 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"),
  }
}

存储派生的抽象语法如图 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)] 
 }                             

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    相关资源
    最近更新 更多