Rez中文文档08 Variants

概述

rez的包可以包含不同的变体(variant),可以把它看作同一个包版本的不同变种。
每个变体都有一个或多个相对于当前包不同的依赖关系。

假定一个场景来说明变体的使用:

有一个maya插件my_maya_plugin,公司有两个maya版本分别为2016-sp2和2017。
如果你的插件已经编译,而你需要在每个不同的maya版本中构建它。(即使源代码是相同的)
这个时候就可以使用变体来创建插件版本,像这样来定义插件的package文件:

1
2
3
4
5
6
7
8
9
10
11
12
name = "my_maya_plugin"

version = "1.0.0"

requires = [
"openexr-2.2"
]

variants = [
["maya-2016.sp2"],
["maya-2017"]
]

当构建这个插件的时候,会根据当前maya版本选择相应的变体。(在给定的配置环境中,只会使用包的一种变体)
每个变体条目都有一个依赖列表,与requires列表里的没有什么不同。
第一个变体需要openexr-2.2和maya-2016sp2,第二个变体需要openexr-2.2和maya-2017。

结构

程序包变体存储在程序包符合变体要求的子目录下。例如刚刚示例中的my_maya_plugin软件包:

1
2
/rez/packages/my_maya_plugin/1.0.0/maya-2016.sp2/<PAYLOAD>
/maya-2017/<PAYLOAD>

下图展示了一个包含各种变体的包:


包的根目录是它当前变体的根目录(当前环境配置使用的那个)

哈希

如上所示变体路径有两个问题:

  • 如果需求有很多,则变体安装路径会很长
  • 如果一些变体的需求里包含类似!< 的字符,它们可能会导致系统构建的泄漏问题。
    对于不同的系统平台来说,可能不是有效的文件系统路径

你可以通过哈希命名来避免这些问题,将变体的路径设置为其需求的哈希值。

1
/rez/packages/my_maya_plugin/1.0.0/83e0c415db1b602f9d59cee028da6ac785e9bacc

这里可以通过变体的短链接来访问相同的路径,需要在已解析的环境中使用。

短链接是指向每个变体的符号链接,默认是_v

1
/rez/packages/my_maya_plugin/1.0.0/_v/a

必须为包的定义设置中启用哈希变体:
hashed_variants = True

不同系统平台的变体

在软件包定义中看到针对不同系统平台,架构而配置的变体并不少见。如下:

1
2
3
4
5
# in package.py
variants = [
["platform-linux", "arch-x86_64", "os-Ubuntu-12.04"],
["platform-linux", "arch-x86_64", "os-Ubuntu-16.04"]
]

这表明了可以针对多个系统平台创建。

单一变体

通常我们只会看到一种变体的程序包,因为:

  • 比如一个编译过的python包,暂时只支持python2.7,这个时候就只存在一种变体。不过可以在以后编译包更新了在添加变体,从而不需要迁移到新版本。
  • 安装路径。人们希望可以从安装包路径中看到一些相关信息,譬如平台,架构,操作系统等。通过将这些依赖项放到变体中,使它们出现在程序包的安装路径中。

变体的选择

如之前所说的,rez会根据解析的环境自动选择正确的变体。例如:

1
2
3
4
]$ rez-env my_maya_plugin maya-2017 -- echo '$REZ_MY_MAYA_PLUGIN_ROOT'
/rez/packages/my_maya_plugin/1.0.0/maya-2017
]$ rez-env my_maya_plugin maya-2016 -- echo '$REZ_MY_MAYA_PLUGIN_ROOT'
/rez/packages/my_maya_plugin/1.0.0/maya-2016.sp2

如果两种变体给定的请求都有效且满足,如下操作(这里maya不在请求中):

1
2
]$ rez-env my_maya_plugin -- echo '$REZ_MY_MAYA_PLUGIN_ROOT'
/rez/packages/my_maya_plugin/1.0.0/maya-2017

my_maya_plugin的任何一种变体都可以满足要求,因为我们没有指定实际需要哪个版本的maya。
默认情况下,rez会选择更高的程序包版本,这也是为什么上述例子中选择了maya-2017的原因。

如果给定选择,则优先选择给定的变体。如果没有则优先选择列表中前面列出的变体,
看下面这个例子:

1
2
3
4
5
6
name = "foo"

variants = [
["python-2.6", "maya-2017"],
["python-2.7", "maya-2016"]
]

如果运行rez-env foo ,它将选择第二种变体,因为这个时候python具有优先级(变体中列出的第一个包),
且第二个变体的python版本更高。

但如果运行rez-env foo maya这个命令的话,将得到第一个变体,因为在命令中把优先级给了maya,
第一个变体的maya版本更高。

rez的配置设置”variant_select_mode”影响选择方式。刚刚描述的是”version_priority”的方式,
还有另外一种方式”intersection_priority”,这种模式下,请求中包数量最多的变体是优先,然后再是版本。

排他性

在上述的例子中,变体都是相互排斥的,例如不能在同一个环境拥有python-2.6和python-2.7。
所以当我们请求”foo python-2.6”的时候,可以确定得到的是哪个变体。
然而,变体并不总会相互排斥,比如下面这个例子:

1
2
3
4
5
6
name = "geocache"

variants = [
["maya-2016"],
["houdini-14"]
]

如果我们运行rez-env geocache,我们会得到哪一个变体?这里肯定不能直接用版本进行比较,
那如果我们这样进行选择rez-env geocache maya,也许会得到第一个变体?

这里的关键字”maya”是选择偏好,但因为变体不是互斥的,所以我们不能保证上述的解决方案是确定的。
再看下面这个例子:

1
]$ rez-env geocache maya animtools-1.4

我们请求geocache时,期望获得maya-2016的变体。但animtools需要maya-2017该怎么办?
这将导致rez无法选择geocache中的第一个变体maya,而去选择第二个houdini,这是错误的。

Notes:rez计划添加一个新的包请求语法,能够显式的选择包变体,避免这样的歧义。

为什么使用变体

变体是rez中的一种强大的机制。

它们避免了为支持不同的依赖关系而维护大量独立包的繁琐需求。