2012-02-15 9 views
15

Después de la limpieza de todos mis cabal install paquetes ed, me encontré con este período de sesiones siguiente:Haskell Cabal: "paquete depende indirectamente de varias versiones del mismo paquete"

$ cabal update 
Downloading the latest package list from hackage.haskell.org 
[email protected]:~/.cabal/packages$ cabal install cabal-dev 
Resolving dependencies... 
Downloading cabal-dev-0.9.1... 
[1 of 1] Compiling Main    (/tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/Setup.hs, /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/dist/setup/Main.o) 
Linking /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/dist/setup/setup ... 
Configuring cabal-dev-0.9.1... 
Warning: This package indirectly depends on multiple versions of the same 
package. This is highly likely to cause a compile failure. 
package containers-0.4.2.1 requires array-0.4.0.0 
package Cabal-1.14.0 requires array-0.4.0.0 
package text-0.11.1.13 requires array-0.4.0.0 
package deepseq-1.3.0.0 requires array-0.4.0.0 
package containers-0.4.2.1 requires array-0.4.0.0 
package HTTP-4000.2.2 requires array-0.4.0.0 
package cabal-dev-0.9.1 requires containers-0.4.2.1 
package Cabal-1.14.0 requires containers-0.4.2.1 
package template-haskell-2.7.0.0 requires containers-0.4.2.1 
Building cabal-dev-0.9.1... 
Preprocessing executable 'ghc-pkg-6_8-compat' for cabal-dev-0.9.1... 
<command line>: cannot satisfy -package-id Cabal-1.14.0-4af45d3c8d10dc27db38ae0e7e5a952b: 
    Cabal-1.14.0-4af45d3c8d10dc27db38ae0e7e5a952b is unusable due to missing or recursive dependencies: 
     array-0.4.0.0-46f61f5fd9543ebf309552ef84dccc86 containers-0.4.2.1-98f9aa15f9c08b13673dc9d89385f449 
    (use -v for more information) 
cabal: Error: some packages failed to install: 
cabal-dev-0.9.1 failed during the building phase. The exception was: 
ExitFailure 1 
$ 

Así que la razón por la que no puedo instalar cabal-dev aparentemente, o bien

  • "depende indirectamente de varias versiones del mismo paquete". Sin embargo, cabal no nombra el paquete que afirma que cabal-dev requiere versiones múltiples de.
  • Cabal-1.14.0 tiene "dependencias faltantes o recursivas", específicamente involucrando de alguna manera array-0.4.0.0 y containers-0.4.2.1.

Un gráfico de las dependencias que enumera confirma que ninguna de estas afirmaciones son verdaderas (o las dependencias que las listas son falsas o incompletas):

claimed dependency graph of cabal-dev-0.9.1

Por lo tanto: ¿Qué me falta? ¿Quién o qué es incorrecto: yo, cabal, o uno o más paquetes?

Me postulo:

$ cabal --version 
cabal-install version 0.10.2 
using version 1.10.1.0 of the Cabal library 
$ ghc --version 
The Glorious Glasgow Haskell Compilation System, version 7.4.1 
$ 
+0

Parece que algo ha reconstruido la matriz y los contenedores. ¿Qué hashes describe el informe 'ghc-pkg describe' para estos? –

+1

@eegg ¿cómo generó ese gráfico? – jberryman

Respuesta

10

El problema surge cuando tenemos el paquete B y C ya instalado, pero construimos contra diferentes versiones de D y luego tratamos de utilizar tanto los paquetes B y C juntos en el paquete A : Problema de dependencia de diamante Esto puede funcionar bien, pero solo si los paquetes B y C no exponen tipos definidos en D en sus interfaces. Si lo hacen, el paquete A no podrá usar funciones de B y C juntas porque no funcionarán con el mismo tipo. Es decir, obtendrás un error de tipo.

Para elegir un ejemplo concreto, supongamos que el paquete D es una cadena de bytes y tenemos tanto bytestring-0.9.0.1 como 0.9.0.4 instalados. Digamos que B es utf8-string y C es regex-base. Digamos que el paquete A es el programa editor de Yi. Entonces, el punto es que en algún lugar del código en Yi queremos pasar una cadena de bytes producida como resultado de la decodificación UTF-8 como entrada a una de las funciones de expresiones regulares. Pero esto no funciona porque las funciones en el paquete utf8-string están usando el tipo ByteString desde bytestring-0.9.0.1 mientras que las funciones regex en el paquete regex usan el tipo ByteString desde bytestring-0.9.0.4. Así se obtiene un error de tipo cuando tratamos de recopilar Yi:

Podría no coincide con el esperado tipo bytestring-0.9.0.4:Data.ByteString.ByteString' against inferred type cadena de bytes-0.9.0.1: Data.ByteString.ByteString'

Por lo que sabe GHC, estos dos tipos son totalmente sin relación!

Esto es obviamente extremadamente molesto. Tampoco hay una solución fácil. En este ejemplo, asumimos que los paquetes B y C ya se han creado, por lo que realmente no hay forma de usar los dos paquetes de forma sensata sin reconstruir ninguno de ellos con una versión diferente del paquete D. En este caso, la solución obvia es para reconstruir B para usar el D-1.1 en lugar de D-1.0. El problema con la reconstrucción de un paquete, por supuesto, es que rompe todos los demás paquetes que ya se han creado en su contra. No está claro si desea que un administrador de paquetes vaya automáticamente a reconstruir muchos paquetes aparentemente no relacionados.

A largo plazo, la mejor solución parece ser hacer lo que hace Nix.En el ejemplo anterior, en lugar de reemplazar el paquete B construido contra D-1.0 con B construido contra D-1.1, Nix agregaría otra instancia de B construida contra D-1.1. Entonces la instancia original de B permanecería sin cambios y nada se rompería. Es el enfoque funcional: nunca cambiamos los valores (paquetes instalados) sino que creamos otros nuevos y la basura recoge los viejos cuando ya no son necesarios.

En la práctica, significa que tenemos que identificar los paquetes instalados utilizando algunos hash del paquete y los valores hash de todos los paquetes dependientes. jhc ya hace esto y hay movimientos en marcha para hacer algo similar para GHC, aunque apunta más a rastrear cambios de API/ABI. Para una administración de paquetes basada en la fuente, creo que es la dirección correcta para tomar.

Debo notar que este no es un problema nuevo. Usted ha podido construir este problema desde que ghc comenzó a permitir que se instalen varias versiones del mismo paquete a la vez. Ahora lo estamos notando con mucha más frecuencia porque dividimos el paquete base y permitimos que esos paquetes divididos se actualicen.

La situación actual es que Cabal advierte de este problema, pero realmente no lo ayuda a resolverlo. Para el ejemplo anterior obtendríamos:

$ cabal configure 
Configuring A-1.0... 
Warning: This package indirectly depends on multiple versions of 
the same package. This is highly likely to cause a compile failure. 
package B-1.0 requires D-1.0 
package C-1.0 requires D-1.1 
Cuestiones relacionadas