获取基地到stackage.org

161 阅读6分钟

不知情者的序言

当你在你的机器上安装一个特定版本的GHC时,它带有一个 "引导 "库的集合。成为一个 "引导 "库意味着什么?很简单,一个库必须用于实现GHC和其他核心组件。两个值得注意的库是baseghc.所有匹配的包名和它们在特定的GHC版本中的版本可以在这个表中找到

一个库与GHC连在一起的事实意味着永远不需要从Hackage或其他地方下载特定版本的源代码。事实上,即使是为了构建每个单独的包的Haddock,也真的不需要在Hackage上上传源代码,因为那些源代码都方便地托管在haskell.org上。

也就是说,Hackage一直是发布Haskell包的中心场所,历史上Hackage的托管人会在Hackage上上传几乎所有 "启动 "包的准确版本。这就是为什么,比如说,我们有bytestring-0.10.8.2在Hackage上可用,尽管它带有GHC的版本,从ghc-8.2.1ghc-8.6.5

这样的上传是完全有意义的。任何在cabal文件中使用核心包作为自己的包的依赖的Haskeller都有一个中心位置来寻找可用的版本和这些版本的文档。事实上,有些人已经习惯了这个过程,以至于在Haskell-Cafe和其他一些地方,当这种包从未被上传时,它已经被讨论。

标准库在Hackage上不可用,这是个危机...

问题所在

半年多前,ghc-8.8.1 ,目前最新的是ghc-8.8.3 。如果你仔细检查核心包的表格,并试图与Hackage上这些库的可用版本相匹配,你会很快注意到其中有几个库是缺失的。我个人不知道这背后的确切原因是什么,但据我所知,这与ghc-8.8.1 现在依赖于Cabal-3.0 这一事实有关系。

对我们来说,问题是它也影响到Stackage的网络界面。让我们来看看如何和为什么。

怎么做

方法 "非常简单。直到最近,如果一个软件包从Hackage上消失了,它也不会被列在Stackage上。base-4.13.0.0 这意味着,如果你试图在去年9月开始的夜间快照中跟踪任何软件包的依赖关系,你将找不到它。正如我之前指出的,不仅是base ,还有其他一些软件包也不见了。

这个问题还表现在Stackage上一个看起来很有趣的错误。 对于依赖列表中的每一个软件包,与列表中的实际链接相比,计数总是至少偏离1(例如primtive)。这让我起初很不解。后来我意识到,base ,因为几乎每个软件包都依赖它,所以它被计算在内,但没有列出,导致不匹配。

为什么

Stackage的结构是这样的,它总是使用Hackage作为可用软件包的真正来源,除了核心软件包,因为这些软件包总是与GHC捆绑在一起。例如,如果你看一下最新的LTS-15.3快照的说明,你不会发现任何核心包列在那里,因为它们是由GHC的版本决定的,而GHC的版本又是在快照中指定的。

要实现Stackage快照,有几个阶段、工具和实际参与的人。以下是管道中的一些步骤。

  • 策划的软件包列表,包括软件包维护者,有时也包括Stackage策展人。

  • 一个策展人工具,用于构建实际的快照、构建软件包、运行测试套件和生成 Haddocks。

  • 一个stackage-server-cron工具,它以一定的间隔运行,并更新stackage.org数据库,以反映上述所有工作的软件包关系和它们各自的文档。

最后一步是我们最感兴趣的,因为stackage.org是我们有东西丢失的地方。让我们看看该工具需要的一些信息,以便stackage-server ,为一个包创建一个页面。

  • 包的名字,它的版本和Pantry密钥(唯一识别源发布内容的加密密钥)。
  • 之前为每个软件包生成的haddocks和hoogle文件
  • Cabal文件,因此我们可以提取关于软件包的有用信息,如描述、许可证、维护者、模块名称等。
  • 可选的是,源码发行中的Readme和Changelog文件也可以在软件包页面上提供。

后面两个要点的信息只在源码发布的压缩包中提供。在快照中定义的软件包对我们来说不构成问题,因为根据定义,它们的源代码可以从Hackage或任何镜像中获得。另一方面,核心软件包则不同,从某种意义上说,它们在构建环境中总是可用的,所以当我们构建一个软件包时,关于它们的信息是存在的。

$ stack --resolver lts-15.0 exec -- ghc-pkg describe base
name:                 base
version:              4.13.0.0
visibility:           public
...

问题是,stackage-server-cron 工具只是一个在云端某处运行的可执行文件,它没有这样的环境。因此,直到最近,除了在Hackage上查看,我们没有办法获得核心包的cabal文件。随着越来越多的核心软件包从Hackage上丢失,特别是像basebytestring 这样的关键软件包,我们不得不想出解决办法。

解决办法

解决这个问题应该很简单,因为我们真正需要的是cabal文件。丢失的软件包的阿道克已经生成,而且一直都是可用的,只是需要额外的一点元信息,以便生成适当的链接和软件包主页。

寻找cabal文件的第一个地方是GHC的git仓库。虽然整个GHC包与我们通常使用的所有其他包有很大不同。

  • GHC依赖的库不是来自Hackage,正如我们已经知道的,相反,它们被钉在git子模块上。
  • 大多数定义在GHC仓库的包都没有cabal文件。相反,它们有模板,用于在构建过程中为特定的架构生成cabal文件。

这意味着仓库不是一个抓取cabal文件的好来源。从源代码构建 GHC 是一个耗时的过程,我们不希望每个版本都这样做,只是为了获得我们需要的 cabal 文件。一个更好的选择是,简单地下载一个常见操作系统的发行包,然后从那里提取缺少的cabal文件。我们使用Linux x86_64的Debian,但操作系统的选择其实并不重要,因为我们只需要那些cabal文件的高级信息。

就这样了。为了在Stackage上获得缺失的核心文件,我们真正需要做的是收集所有缺失的cabal文件,并将它们提供给stackage-server-cron

结论

回到Stackage的起源,事实证明,有不少这样的核心包丢失了,其中最常见和最引人注目的是ghc 本身。只有少数几个正式发布的版本被上传到Hackage。

从现在开始,我们有一个特殊的仓库commercialhaskell/core-cabal-files,我们可以在那里放置丢失的核心包的cabal文件,stackage-server-cron工具会自动拾取。就像通常的公共资源库一样,我们鼓励社区中的任何人提交拉动请求,只要他们发现某个核心包没有被列入Stackage的新创建的快照中。

在过去的几个星期里,Hackage的第一个这样的缺失的核心包base-4.13.0.0的第一个缺失的核心包正在Stackage上被收录。最近值得注意的是bytestring-0.10.9.0ghc-8.8.xCabal-3.0.1.0