Cabal 找不到本地来源(但已正确安装)的软件包

Gui*_*ont 6 haskell cabal cabal-install

我最近升级到 Cabal 3.2(和 GHC 8.10),我遇到了一些重大问题,使我的某些项目不再可构建......

问题的详细描述

这是一个每次都失败的最小(非)工作配置:

  1. 我从一个干净的 Cabal 配置开始(删除~/.cabal);原因将在后面的帖子中出现。我运行cabal update以重新创建.cabal目录并确保 Cabal 正常工作。

  2. test1使用cabal init. 这是一个库项目,带有一个公开的模块(方便地命名Test1),该模块导出一些虚拟函数foo。我跑cabal build,然后cabal install --lib; 一切都运行顺利,到目前为止一切顺利。

  3. 可以肯定的是,我离开了项目目录并启动了 GHCi。我输入:m Test1以加载我之前创建的模块,它工作正常!我可以输入foo ...并查看我的函数执行情况。此外,我列出了目录的内容~/.cabal/store/ghc-8.10.xxx并看到该test1-xxx目录在那里。

  4. 然后我创建了一个新项目test2,仍然使用cabal init. 这一次,我将其配置为可执行文件,并将其添加test1为依赖项(使用build-depends字段)。但是这次当我运行时cabal build,我遇到了一些问题:

~/projects/haskell/test2> cabal build
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] trying: test2-0.1.0.0 (user goal)
[__1] unknown package: test1 (dependency of test2)
[__1] fail (backjumping, conflict set: test1, test2)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: test2, test1
Run Code Online (Sandbox Code Playgroud)

在我看来,好像test1找不到包,但是我可以从 GHCi(和 GHC)访问它,并且它存在于~/.cabal/store...

但不幸的是还有更多。

  1. 我创建了第三个项目,test3. 这是一个库,它只依赖于base(所以特别是它依赖于test1)。该库公开了一个模块,Test3,导出了一个函数,bar。我跑了cabal build,这里没问题。但是当我想安装test3cabal install --lib遇到了一些错误:
~/projects/haskell/test3> cabal install --lib
Wrote tarball sdist to
/home/<user>/projects/haskell/test3/dist-newstyle/sdist/test3-0.1.0.0.tar.gz
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] unknown package: test1 (user goal)
[__0] fail (backjumping, conflict set: test1)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: test1
Run Code Online (Sandbox Code Playgroud)

好像是找不到test1,虽然已经正确安装了;可能这是失败构建的残余test2......

  1. 可以肯定的是,我启动 GHCi 并输入:m Test3,但 GHCi 告诉我它找不到模块Test3(甚至暗示这是一个错字,我的意思是Test1),表明test3确实没有安装,尽管它已成功构建。 ..

  2. 好吧,整个情况还有一个怪癖:我再次创建了一个cabal init名为的新项目test4,它是一个可执行文件,(再次)只依赖于base. 我保留默认值Main.hs(只打印“你好,Haskell!”)。我跑cabal build:没问题。然后我跑cabal install…… 也没问题吗?我test4在一个随机位置运行,它启动可执行文件,打印“你好,Haskell!” 在终端...

  3. 而且还有最后一两件事:我去一些随机位置,我跑cabal install xxx --lib哪里xxx是一个库包上Hackage用(例如xml)和:

~> cabal install xml --lib
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] unknown package: test1 (user goal)
[__0] fail (backjumping, conflict set: test1)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: test1
Run Code Online (Sandbox Code Playgroud)

这就是为什么我需要.cabal定期核弹的原因......现在我似乎处于某种陈旧状态,我无法再安装任何库。

技术配置及注意事项

我正在运行 Cabal 3.2.0.0 和 GHC 8.10.0.20200123。我从 hvr/ghc PPA 安装了它们,并确保我的计算机上没有这些工具的其他版本。

请注意,我正在运行 Ubuntu 18.04.4 LTS(使用 XFCE,确切地说是 XUbuntu)。其他一切(似乎是这样)都是最新的。

最后一件事,关于*.cabal我用于构建的文件,它们几乎是由 生成的文件cabal init,除了我在库的情况下切换executable xxxlibrary,并且我只是添加了一个exposed-modules用于公开库模块的字段(分别Test1为 fortest1Test3for test3)。我还使用build-dependsintest2使项目依赖于test1. 除此之外,它们几乎没有受到影响。

笔记和想法

我必须承认我是 Cabal 3 的新手;直到上周我一直在使用 Cabal 1(因为我从不费心更新它;是的,我知道这很糟糕)。使用 Cabal 1 我没有任何问题,我完全能够从本地源安装一个包并在其他项目中依赖它......

我觉得我做错了什么;也许我没有使用正确的 Cabal 命令?我在某处看到了关于cabal new-buildand 的东西,cabal new-install但它似乎除了cabal buildand之外没有做任何事情cabal install,至少在我的情况下。我也想研究沙箱,但似乎自 Cabal 版本 2 以来已经消失了。

也有一点可能是 Cabal 错误,但我在错误跟踪器上没有发现任何可能与我的问题有关的相关问题......

你怎么看待这件事?我究竟做错了什么?您是否看到任何替代方案或可能的解决方案?

非常感谢!

dan*_*iaz 5

GHC 环境文件

GHC 安装带有一定数量的开箱即用软件包base是其中之一,但还有其他的,例如text。如果你单独安装 GHC(没有 cabal 或 stack)并打开 ghci,它应该让你import Data.Text没有问题。

如果您希望 GHC 或 ghci 知道文件系统中存在的其他编译包怎么办?您可以使用命令行标志将GHC 指向其他包数据库,但也有包环境文件的概念。

环境是包含与包相关的 GHC 标志列表的纯文本文件。可能有一个全局环境~/.ghc/$ARCH-$OS-$GHCVER/environments/default,也可能存在只影响在同一文件夹内调用的 GHC 和 ghci 命令的本地环境。GHC 用户指南中描述了搜索确切规则

是什么惊天动地安装--lib实际上呢?

默认情况下,它会修改全局环境文件,以便 GHC 和 ghci 现在可以找到该库。这就是为什么第3)点起作用的原因。库的实际编译二进制文件仍然驻留在 cabal 存储中。

我们还可以创建本地环境文件。例如,cabal install sop-core --lib --package-env ..ghc.environment.xxx在当前文件夹中创建环境文件,当 ghc 和 ghci 在那里被调用时,该库将可供 ghc 和 ghci 使用。

为什么 test1 不可用于 test2?

现代 cabal 区分本地包和外部包

  • 本地包是您在项目中一起开发的一组包,这些包被反复编辑、重新编译和更改。它们是“就地”构建的,在项目之外看不到。他们可以相互依赖。
  • 外部包是从build-depends:包存储库下载其源代码的依赖项,编译后将其放入 cabal 存储中,以便其他 Cabal 项目无需重新编译即可使用它们。

本地包列表和其他项目级配置详细信息在cabal.project文件中指定。但是如果你处理一个单独的包,你就不需要它了;包的默认列表很简单./*.cabal

cabal 想要完全控制本地包的构建环境,会忽略全局环境文件。在您的情况下,您必须在同一个项目中制作 test1 和 test2 本地包(可能是最好的选择)或发布 test1 并将其视为外部包。

请注意,“cabal 项目”是一个仅在开发过程中相关的概念。包是独立发布的,在 Hackage 或其他存储库中没有“项目”,只有包。

如果我想将 test1 视为外部而不将其发布到 Hackage 怎么办?

您必须设置一个本地包存储库,基本上是一个非公开的 Hackage。

您可以在 Cabal 配置文件中告诉 Cabal 额外的包存储库,即配置 cabal 本身的文件。它的位置在 的最后一行给出cabal --help

但是如何设置存储库?该hackage回购工具可以与帮助。

为什么test3失败了?为什么进一步的库安装失败?

这很奇怪,我不知道为什么会这样。您是否偶然删除了~/.cabal步骤3)5)之间的文件夹?如果删除全局 GHC 环境文件并重试会发生什么?