Hier, j'ai découvert un nouvel outil Haskell appelé Stack . À première vue, il semble que cela fasse à peu près le même travail que Cabal. Alors, quelle est la différence entre eux? Est-ce que stack est un remplacement pour Cabal? Dans quels cas devrais-je utiliser Stack au lieu de Cabal? Que peut faire Stack que Cabal ne peut pas?
Est-ce que stack est un remplacement pour Cabal?
Oui et non.
Dans quels cas devrais-je utiliser Stack au lieu de Cabal? Que peut faire Stack que Cabal ne peut pas?
Puisque Stack
utilise les packages de pile organisés par default, il est connu que les packages sont construits ensemble. Dans Cabal, il y a une chance que vous soyez touché par l'enfer de la cabale. Stack met également en cache votre package localement, de sorte que vous ne compilez pas tout à partir de zéro lorsque vous utilisez ce package (ou sa dépendance transitive) la prochaine fois. Notez qu'il est également possible d'utiliser des packages non empilés, de sorte que vous pouvez continuer, même si aucun package n'est présent dans l'instantané d'empilement.
Personnellement, j'aime Stack et je recommanderais à tous les développeurs Haskell de l'utiliser. Leur développement est rapide. Ils ne s'inquiètent pas (trop) de la compatibilité ascendante. Et il a un beaucoup meilleur UX. Et il y a des choses que stack
fait que Cabal
ne fournit pas encore:
stack build --fast --file-watch
. Cela reconstruira automatiquement si vous modifiez les fichiers locaux présents. Utilisation avec --pedantic
L'option est un deal-breaker pour moi.Il existe un article dans le blog de Nice expliquant la différence: Pourquoi Stack not Cabal?
Dans ce qui suit, je ferai référence aux deux outils comparés en tant que cabal-install et stack . En particulier, je vais utiliser cabal-install pour éviter toute confusion avec le Cabal bibliothèque, qui est l'infrastructure commune utilisée par les deux outils. D'une manière générale, nous pouvons dire cabal-install et pile sont des interfaces pour Cabal , et leurs principales différences se résument à ce que sont les flux de travail par défaut:
Par défaut, cabal-install examinera les dépendances spécifiées dans ses .cabal
fichier et utilisez un résolveur de dépendances pour déterminer (si possible) un ensemble de packages et de versions de packages qui le satisfont. Cet ensemble est tiré de Hackage dans son ensemble - tous les packages et toutes les versions, passées et présentes. Une fois qu'un plan de construction réalisable est trouvé, la version choisie des dépendances sera, par défaut, installée et enregistrée dans une base de données unique des paquets installés quelque part dans ~/.cabal
.
stack , en revanche, examinera d'abord le champ resolver
de stack.yaml
. Ce champ spécifie généralement un Stackage) instantané , qui est un sous-ensemble des packages Hackage avec versions fixes connues pour être compatibles entre elles. stack tentera alors, par défaut, de satisfaire les dépendances en utilisant exclusivement ce qui est fourni par l'instantané. Les packages installés à partir d'un instantané sont enregistrés dans des bases de données différentes et isolées, et des installations distinctes de GHC sont gérées pour prendre en compte les besoins des instantanés. Cette approche échange un peu de flexibilité en garantissant qu’il n’y aura aucune incompatibilité de version entre les packages installés (un problème courant lorsqu’on utilise une base de données de packages avec cabal-install , pour les raisons évoquées dans cet article ), ainsi qu’il est toujours possible de déterminer les versions exactes de dépendances à utiliser pour construire un projet (ce qui est utile à la fois pour garantir des constructions reproductibles de projets complets et pour spécifier facilement des dépendances de .hs
scripts sans compagnon .cabal
fichier).
N'oubliez pas que la description ci-dessus couvre les flux de travail par défaut pour chaque outil. La plupart des possibilités de pile sont réalisables de manière (peut-être moins pratique) avec cabal-install en sortant des valeurs par défaut, et inversement. En particulier:
cabal-install supporte les bases de données de paquetages isolés pour chaque projet via le cabal sandbox
_ commande, bien que contrairement aux instantanés stack et Stackage, il n’est pas possible de partager les packages installés entre les projets. Correction des versions des dépendances à utiliser pour les constructions indépendamment du .cabal
est également possible, via cabal freeze
. (Une fonctionnalité liée de pile avec aucun analogique cabal-install est la gestion de installations séparées de GHC, à savoir stack setup
.)
pile les projets peuvent utiliser des packages non disponibles dans l'instantané Stackage utilisé en définissant les champs appropriés dans stack.yaml
(extra-deps
pour les packages disponibles à partir de Hackage mais pas à partir de Stackage, et packages
avec un paramètre personnalisé location
pour les packages ne figurant pas dans Hackage). Ces packages non empilés sont installés projet par projet, avec une isolation par rapport aux instantanés. Il y a aussi stack solver
commande, qui effectue la résolution automatique des dépendances pour les dépendances Hackage (c'est-à-dire non empilées).
Pour terminer, notons que la prise en charge de versions locales de style Nix est ajoutée à cabal-install en tant que un moyen alternatif d’atténuer les conflits de version qui est potentiellement plus pratique que cabal sandbox
. Cette fonctionnalité est disponible, en version de prévisualisation, à partir de cabal-install 1.24.
D'après ce que je peux tirer de la FAQ, il semble que Stack utilise la bibliothèque Cabal, mais pas le cabal.exe
binary (plus précisément appelé cabal-install). Il semble que le but du projet soit le sandboxing automatique et l’évitement de la dépendance.
En d'autres termes, il utilise la même structure de paquetage Cabal, il fournit simplement une interface différente pour la gestion de ce genre de choses. (Je pense!)