Cabal安装沙盒无法重新安装base或任何其他依赖项。

6

未来遇到此类问题的人请注意:

复制下面任何一个命令都是不明智的,请不要执行它们。只需查看Zeta的答案,了解为什么我错误地处理了这个问题。

原始问题

我的沙盒似乎被一些全局版本的软件包卡住了,而不是使用沙盒版本。我在SO上寻找答案,许多问题都没有具体的解决方法,或者略有不同,所以我无法让我的设置运行起来。这是我的情况:

1. Version of cabal is old:

$ cabal --v
cabal-install version 1.16.0.2
using version 1.16.0 of the Cabal library 

哦,糟糕,这是旧版本的代码,无法在沙盒中运行。

2. Install cabal with cabal
$ cabal install cabal
Resolving dependencies...
Downloading Cabal-1.22.6.0...

...lots of stuf...

Registering Cabal-1.22.6.0...
Installed Cabal-1.22.6.0

看起来不错。

3. Try it out:
$ cabal sandbox init
cabal: unrecognised command: sandbox (try --help)

嗯。
$ which cabal
/usr/bin/cabal

啊。
$ ${HOME}/.cabal/bin/cabal --version
cabal-install version 1.22.2.0
using version 1.22.2.0 of the Cabal library 

啊哈。

$ export PATH="${HOME}/.cabal/bin/:$PATH"
$ export PATH="${HOME}/.cabal/libs/:$PATH"

$ cabal --v
cabal-install version 1.22.2.0

太好了。
4. Try it out again:
$ cabal sandbox init
Writing a default package environment file to
.../cabal.sandbox.config
Creating a new sandbox at .../.cabal-sandbox

$ cabal install Frames
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: Frames-0.1.2.1 (user goal)
next goal: base (dependency of Frames-0.1.2.1)
rejecting: base-4.6.0.1/installed-8aa... (conflict: Frames => base>=4.7 &&
<4.9)
rejecting: base-4.8.2.0, 4.8.1.0, 4.8.0.0, 4.7.0.2, 4.7.0.1, 4.7.0.0, 4.6.0.1,
4.6.0.0, 4.5.1.0, 4.5.0.0, 4.4.1.0, 4.4.0.0, 4.3.1.0, 4.3.0.0, 4.2.0.2,
4.2.0.1, 4.2.0.0, 4.1.0.0, 4.0.0.0, 3.0.3.2, 3.0.3.1 (global constraint
requires installed instance)
Dependency tree exhaustively searched.

Note: when using a sandbox, all packages are required to have consistent
dependencies. Try reinstalling/unregistering the offending packages or
recreating the sandbox.

哦,所以base不兼容,好的。
$ cabal install base --reinstall
Resolving dependencies...
cabal: Could not resolve dependencies:
next goal: base (user goal)
rejecting: base-4.8.2.0, 4.8.1.0, 4.8.0.0, 4.7.0.2, 4.7.0.1, 4.7.0.0, 4.6.0.1,
4.6.0.0, 4.5.1.0, 4.5.0.0, 4.4.1.0, 4.4.0.0, 4.3.1.0, 4.3.0.0, 4.2.0.2,
4.2.0.1, 4.2.0.0, 4.1.0.0, 4.0.0.0 (only already installed instances can be
used)
rejecting: base-3.0.3.2 (conflict: base => base>=4.0 && <4.3)
rejecting: base-3.0.3.1 (conflict: base => base>=4.0 && <4.2)
Dependency tree exhaustively searched.

Note: when using a sandbox, all packages are required to have consistent
dependencies. Try reinstalling/unregistering the offending packages or
recreating the sandbox.

哎呀,那么所有的依赖关系怎么办?

$ cabal install --upgrade-dependencies
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: Frames-0.1.2.1 (user goal)
next goal: base (dependency of Frames-0.1.2.1)
rejecting: base-4.8.2.0, 4.8.1.0, 4.8.0.0, 4.7.0.2, 4.7.0.1, 4.7.0.0 (global
constraint requires installed instance)
rejecting: base-4.6.0.1/installed-8aa... (conflict: Frames => base>=4.7 &&
<4.9)
rejecting: base-4.6.0.1, 4.6.0.0, 4.5.1.0, 4.5.0.0, 4.4.1.0, 4.4.0.0, 4.3.1.0,
4.3.0.0, 4.2.0.2, 4.2.0.1, 4.2.0.0, 4.1.0.0, 4.0.0.0, 3.0.3.2, 3.0.3.1 (global
constraint requires installed instance)
Dependency tree exhaustively searched.

Note: when using a sandbox, all packages are required to have consistent
dependencies. Try reinstalling/unregistering the offending packages or
recreating the sandbox.

看起来我无法重新安装/注销有问题的软件包。我希望错误信息能够给我更多关于如何做到这一点的提示,因为"--reinstall"标志是我最好的选择。

好吧,它提供了两个解决方案,那么让我们尝试另一个方法,重新创建沙盒。

$ cabal sandbox delete
Deleting the sandbox located at .../.cabal-sandbox

$ cabal sandbox init
Writing a default package environment file to
.../cabal.sandbox.config
Creating a new sandbox at .../.cabal-sandbox

$ cabal install --upgrade-dependencies
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: Frames-0.1.2.1 (user goal)
next goal: base (dependency of Frames-0.1.2.1)
rejecting: base-4.8.2.0, 4.8.1.0, 4.8.0.0, 4.7.0.2, 4.7.0.1, 4.7.0.0 (global
constraint requires installed instance)
rejecting: base-4.6.0.1/installed-8aa... (conflict: Frames => base>=4.7 &&
<4.9)
rejecting: base-4.6.0.1, 4.6.0.0, 4.5.1.0, 4.5.0.0, 4.4.1.0, 4.4.0.0, 4.3.1.0,
4.3.0.0, 4.2.0.2, 4.2.0.1, 4.2.0.0, 4.1.0.0, 4.0.0.0, 3.0.3.2, 3.0.3.1 (global
constraint requires installed instance)
Dependency tree exhaustively searched.

Note: when using a sandbox, all packages are required to have consistent
dependencies. Try reinstalling/unregistering the offending packages or
recreating the sandbox.

这也没什么帮助。我已经没有思路了。我应该如何使用沙盒?我的理解是有一个全局变量导致了问题。按照沙盒的设计,全局变量不应该对它造成影响,对吧?

如果需要上下文,请注意,我只是尝试运行“Frames”的演示:

https://github.com/acowley/Frames

……它是:

$ cabal sandbox init
$ cabal install --dependencies-only -f demos # <-- here

我看到这一步有一个已关闭的问题,但那似乎是另一个问题。


3
base 与 GHC 的版本密切相关。由于您的 Cabal 是 1.16,我猜您正在使用 GHC 7.6.x,这在旧版 Linux LTS 发行版(如 Ubuntu 14.04)中很常见。请尝试使用 hvr 的 ghc-x.y.z 包(在 launchpad 上),或者改用 stack,或者获取更新的版本。如果你不想切换 GHC 版本,则至少需要 GHC 7.8.x 才能运行 Frames。 - Zeta
是的,我肯定在使用14.04版本。您建议我如何升级呢?例如,当我访问此链接:https://www.haskell.org/platform/#linux-ubuntu并按照其说明操作时,它告诉我“haskell-platform已经是最新版本”。 - Mittenchops
或者换句话说?如果这样不行,我应该卸载哪些东西才能让Haskell正常工作?我不明白为什么Cabal会让我升级到一个如此不一致的状态,以至于我什么都做不了。而且这是怎么在安装沙盒的过程中发生的,以至于这种事情不会发生呢? :) - Mittenchops
1
您可以使用二进制发行版安装更新的 GHC,例如这里。这些版本将干净地安装在一起,并与您的 haskell-platform debs 并存(只有 ghc 的符号链接等会被覆盖),您可以在 cabal 中使用 -w 标志来使用不同版本的 GHC(因此在 cabal 项目中使用 base)。但是,正如 zeta 建议的那样,您应该使用 stack;它听起来更加用户友好,并且可以处理安装 ghc。 - jberryman
1个回答

12

幕后一览(或:什么使得base如此特殊)

base 的版本与 GHC 版本紧密耦合。例如,base-4.6.0.1 与 GHC 7.6.3一起发布。您不能使用与不兼容的 GHC 版本的另一个 base 版本。要使用 base-4.7.0.x,您需要 GHC 7.8.x。

因此,您不能为 base 使用局部沙盒,它是(极少数)无法获得沙盒化的软件包之一。

沙盒需要强大的基础

如果我们将“沙盒”的概念比喻为字面上的含义,很快就会发现沙盒需要某种基础。而这正是 base 所提供的。其他任何东西都可以存在于沙盒中,并且应该正常工作:

我该如何使用沙盒?

您正确地使用了沙盒,但您没有安装正确的编译器/基础库。

我不明白为什么 cabal 让我升级到一个状态如此不协调,无法做任何事情。

再次强调,Cabal 没有处于不协调的状态。 Frames将最小基础库版本限制为4.7,这通常意味着它使用了在 GHC 7.8 中引入的 GHC 特性。即使您能够安装 base-4.7.x.y,您仍将缺少这些 GHC 特性。

但是,不建议使用旧版 GHC 与较新版本的 Cabal。

尝试其他下限

然而,有时候一个库的下限设定过于严格。也许 Frames 可以与 GHC 7.6 兼容。您可以在本地检查一下:

$ cabal unpack Frames
$ cd Frames-*
$ vim Frames.cabal # change the min base to something lower
$ cabal sandbox init
$ cabal build
如果这个方法有效,那么Frames中base的下限实际上过高了,您可以在库上提交拉取请求。
将新内容添加到旧发行版有四种方法,依难度递减排序:
1.从GHC下载页手动安装GHC和Cabal(不建议,仅适用于有经验的用户)。 2.安装最小版本的GHC和Cabal,请查看MinGHC. 3.手动安装最新版本的Haskell平台(不要忘记先摆脱旧版本;使用shell脚本,而不是LTS发行版上的apt-get包)。 4.安装stack并使用stack setup(最简单的方法)。
我将重点介绍MinGHC和Stack,因为它们提供了一些易于安装多个GHC版本的简单方法。
MinGHC安装(仅适用于Linux)
基本上按照此网站上的说明操作。在Ubuntu中,您必须将第三方源添加到apt源中,并安装特定版本的Cabal和GHC。请注意,这将在/opt/中安装GHC和Cabal,因此您必须将一些目录添加到路径中:
sudo apt-get update
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y ppa:hvr/ghc
sudo apt-get update
sudo apt-get install -y cabal-install-1.22 ghc-7.10.3
cat >> ~/.bashrc <<EOF
export PATH="\$HOME/.cabal/bin:/opt/cabal/1.20/bin:/opt/ghc/7.10.3/bin:\$PATH"
EOF
export PATH=~/.cabal/bin:/opt/cabal/1.22/bin:/opt/ghc/7.10.3/bin:$PATH

这使您能够轻松安装其他版本的Cabal和GHC

sudo apt-get install -y cabal-install-1.xx ghc-7.yy.z

然后更改您的PATH变量。之后,您可以使用cabal sandbox *命令。

我还建议您阅读Stephen Diel关于Cabal的笔记。它们提供了一些常用功能的很好见解。

使用stack

同样,按照此站点上的说明操作。基本上是相同的:添加外部源并告诉您的分发系统信任这些源:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 575159689BEFB442
echo 'deb http://download.fpcomplete.com/ubuntu trusty main' | sudo tee /etc/apt/sources.list.d/fpco.list
sudo apt-get update && sudo apt-get install stack -y

接下来,在已存在的Cabal项目中使用stack init,或者使用stack new安装一个新项目,然后运行stack setup,这将安装一个相当新的GHC版本:

$ stack new my-project
$ cd my-project
$ stack setup
# Loooooooooooooooooooooooong log, installs GHC in background
注意,stack 以“合理”的方式安装所有依赖项。它使用一个内部LTS系统,您不必使用cabal沙箱。但是,您不能再使用Cabal命令,而是必须使用 stack buildstack ghc
如果您不使用某个包,类似于
stack ghc --package Frames -- -O2 --make -rtsopts File1.hs File2.hs

这是可能的。但是,记录stack的每个功能会超出这个答案的范围并很快过时,因此请查看文档


谢谢,这太有帮助了。虽然我才刚开始,但真的很有帮助能够了解到我所遇到的错误远非我预期的原因(仅需要升级以解决不兼容问题),而是存在许多源头,包括在之前(Frames 本身有一个看起来像 Cabal 要求的基本要求!)和在我认为需要解决的问题之后。 - Mittenchops
在安装新版本的ghc之前,是否需要卸载已安装的版本? - Stéphane Laurent
2
@StéphaneLaurent 不用,但你需要调整你的路径。通常最好将 GHC 和其他应用程序/库放在 /opt/ghc-<VERSION> 中,这样您可以安装多个版本。请注意,stack 将处理外部包,如果没有 stack 将会很棘手。 - Zeta
@Zeta 谢谢。我迷失了方向,因为我仍然拥有 ~/.cabal 中的旧版本 cabal。当我安装一个包时,它会被安装在这个目录中,但 GHC 找不到它。 - Stéphane Laurent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接