为什么我们在 XenServer 开发中使用 OPAM

这是一篇来自 OPAM 用户的客座文章,讲述了他们如何使用它。如果您想发布关于您自己使用情况的文章,请告知我们

XenServer 使用了 Xen 项目的 "Xapi 工具栈": 一套主要用 OCaml 编写的工具,它

Xapi 工具栈由大量独立开发和单独版本化的库和组件构建而成。我们可以轻松地与其他开源项目(如 Mirage)共享代码,但是这种灵活性也带来了一定的成本:当一个二进制文件(例如“xapi”(集群管理器))依赖于 45 个独立的库时,我们如何快速设置构建环境?我们需要哪些库?我们如何应用更新?如果我们更改了其中一个库(例如进行错误修复),我们应该重建哪些部分?这就是 OPAM(源代码包管理器)让一切变得简单的地方。

使用 OPAM 安装构建环境特别容易。例如,在 CentOS 6.5 虚拟机中,首先安装 OPAM

然后

$ opam init --comp=4.01.0
$ eval `opam config env`

接下来,使用类似以下的命令安装 xapi 需要的 C 库和开发工具

$ sudo yum install `opam install xapi -e centos`

最后,构建 xapi 本身

$ opam install xapi
  ∗  install obuild                 0.1.1          [required by cdrom, nbd]
  ∗  install base-no-ppx            base           [required by lwt]
  ∗  install cmdliner               0.9.7          [required by nbd, tar-format]
  ∗  install camlp4                 4.01.0         [required by nbd]
  ∗  install ocamlfind              1.5.5          [required by xapi]
  ∗  install xmlm                   1.2.0          [required by xapi-libs-transitional, rpc, xen-api-client]
  ∗  install uuidm                  0.9.5          [required by xapi-forkexecd]
  ∗  install type_conv              111.13.00      [required by rpc]
  ∗  install syslog                 1.4            [required by xapi-forkexecd]
  ∗  install ssl                    0.4.7          [required by xapi]
  ∗  install ounit                  2.0.0          [required by xapi]
  ∗  install omake                  0.9.8.6-0.rc1  [required by xapi]
  ∗  install oclock                 0.4.0          [required by xapi]
  ∗  install libvhd                 0.9.0          [required by xapi]
  ∗  install fd-send-recv           1.0.1          [required by xapi]
  ∗  install cppo                   1.1.2          [required by ocplib-endian]
  ∗  install cdrom                  0.9.1          [required by xapi]
  ∗  install base-bytes             legacy         [required by ctypes, re]
  ∗  install sexplib                111.17.00      [required by cstruct]
  ∗  install fieldslib              109.20.03      [required by cohttp]
  ∗  install lwt                    2.4.7          [required by tar-format, nbd, rpc, xen-api-client]
  ∗  install xapi-stdext            0.12.0         [required by xapi]
  ∗  install stringext              1.2.0          [required by uri]
  ∗  install re                     1.3.0          [required by xapi-forkexecd, tar-format, xen-api-client]
  ∗  install ocplib-endian          0.8            [required by cstruct]
  ∗  install ctypes                 0.3.4          [required by opasswd]
  ∗  install xenctrl                0.9.26         [required by xapi]
  ∗  install rpc                    1.5.1          [required by xapi]
  ∗  install xapi-inventory         0.9.1          [required by xapi]
  ∗  install uri                    1.7.2          [required by xen-api-client]
  ∗  install cstruct                1.5.0          [required by tar-format, nbd, xen-api-client]
  ∗  install opasswd                0.9.3          [required by xapi]
  ∗  install xapi-rrd               0.9.1          [required by xapi-idl, xapi-rrd-transport]
  ∗  install cohttp                 0.10.1         [required by xen-api-client]
  ∗  install xenstore               1.2.5          [required by xapi]
  ∗  install tar-format             0.2.1          [required by xapi]
  ∗  install nbd                    1.0.2          [required by xapi]
  ∗  install io-page                1.2.0          [required by xapi-rrd-transport]
  ∗  install crc                    0.9.0          [required by xapi-rrd-transport]
  ∗  install xen-api-client         0.9.7          [required by xapi]
  ∗  install message-switch         0.10.4         [required by xapi-idl]
  ∗  install xenstore_transport     0.9.4          [required by xapi-libs-transitional]
  ∗  install mirage-profile         0.4            [required by xen-gnt]
  ∗  install xapi-idl               0.9.19         [required by xapi]
  ∗  install xen-gnt                2.2.0          [required by xapi-rrd-transport]
  ∗  install xapi-forkexecd         0.9.2          [required by xapi]
  ∗  install xapi-rrd-transport     0.7.2          [required by xapi-rrdd-plugin]
  ∗  install xapi-tapctl            0.9.2          [required by xapi]
  ∗  install xapi-netdev            0.9.1          [required by xapi]
  ∗  install xapi-libs-transitional 0.9.6          [required by xapi]
  ∗  install xapi-rrdd-plugin       0.6.0          [required by xapi]
  ∗  install xapi                   1.9.56
===== ∗  52 =====
Do you want to continue ? [Y/n] y

显然,手动完成所有这些操作非常繁琐!

OPAM 也使得迭代开发变得非常容易。考虑一个需要更改 公共接口 的场景。如果没有 OPAM,我们必须手动找出需要重建哪些组件——这既费时又容易出错。当我们想要进行一些本地更改时,我们只需克隆仓库并告诉 OPAM 将包“固定”到本地检出。OPAM 将负责仅重建依赖的包

$ git clone git://github.com/xapi-project/xcp-idl
... make some local changes ...
$ opam pin add xapi-idl ./xcp-idl
$ opam install xapi
...
xapi-idl needs to be reinstalled.
The following actions will be performed:
  ↻  recompile xapi-idl               0.9.19*
  ↻  recompile xapi-rrd-transport     0.7.2    [uses xapi-idl]
  ↻  recompile xapi-forkexecd         0.9.2    [uses xapi-idl]
  ↻  recompile xapi-tapctl            0.9.2    [uses xapi-forkexecd]
  ↻  recompile xapi-netdev            0.9.1    [uses xapi-forkexecd]
  ↻  recompile xapi-libs-transitional 0.9.6    [uses xapi-forkexecd]
  ↻  recompile xapi-rrdd-plugin       0.6.0    [uses xapi-idl]
  ↻  recompile xapi                   1.9.56   [uses xapi-idl]
===== ↻  8 =====
Do you want to continue ? [Y/n] 

如果您只想固定到某个分支(例如 master),则会更容易

$ opam pin add xapi-idl git://github.com/xapi-project/xcp-idl

在测试错误修复时能够快速迭代非常重要——OPAM 也使得这一点变得容易。在对“固定”的仓库进行更改后,用户只需键入

$ opam update -u

并且只有受影响的组件将被重建。

OPAM 允许我们创建自己的“开发远程”,其中包含我们库的最新、最前沿版本。要安装这些不稳定的版本,我们只需键入

$ opam remote add xapi-project git://github.com/xapi-project/opam-repo-dev
$ opam update -u

=-=- Updating package repositories =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[xapi-project] git://github.com/xapi-project/opam-repo-dev already up-to-date
[default] /home/djs/ocaml/opam-repository synchronized

Updates available for 4.01.0, apply them with 'opam upgrade':
=== ∗  1   ↻  6   ↗  6 ===
The following actions will be performed:
  ∗  install   xapi-backtrace         0.2               [required by xapi-idl, xapi-stdext]
  ↗  upgrade   xenctrl                0.9.26 to 0.9.28
  ↗  upgrade   xapi-stdext            0.12.0 to 0.13.0
  ↻  recompile xapi-rrd               0.9.1             [uses xapi-stdext]
  ↻  recompile xapi-inventory         0.9.1             [uses xapi-stdext]
  ↗  upgrade   xapi-idl               0.9.19 to 0.9.21
  ↻  recompile xapi-rrd-transport     0.7.2             [uses xapi-idl]
  ↻  recompile xapi-forkexecd         0.9.2             [uses xapi-idl, xapi-stdext]
  ↗  upgrade   xapi-libs-transitional 0.9.6 to 0.9.7
  ↻  recompile xapi-tapctl            0.9.2             [uses xapi-stdext]
  ↻  recompile xapi-netdev            0.9.1             [uses xapi-stdext]
  ↗  upgrade   xapi-rrdd-plugin       0.6.0 to 0.6.1
  ↗  upgrade   xapi                   1.9.56 to 1.9.58
===== ∗  1   ↻  6   ↗  6 =====
Do you want to continue ? [Y/n]

当一组链接的更改准备推送到远程时,我们可以进行单个拉取请求来更新一组组件,这将触发 travis 集成测试。

总结

Xapi 工具栈由大量独立版本化和发布的库构建而成,其中许多库与其他项目(如 Mirage)共享。这些库易于单独构建和测试,但依赖项的数量庞大使得构建整个项目变得困难——这就是 opam 真正闪光的地方。Opam 通过以下方式简化了我们的日常工作:

  • 当依赖项更改时自动重建依赖软件
  • 允许我们在开发团队之间共享包含最新软件的“开发远程”
  • 允许我们使用 git push “发布”一组协调的版本,然后通过 travis 触发集成测试

如果您有很多 OCaml 代码需要构建,请尝试使用 OPAM!