frosch03.de/posts/2013-02-08-CabalFile

Was ist cabal

Hackage, oder auch hackageDB ist Haskells Packetdatenbank und enthält mittlerweile über 5000 Bibliotheken. Hat man Haskell auf seinem Rechner installiert, so wird man früher oder später an den Punkt kommen, neue Library's installieren zu wollen.

Das Problem ist nun, dass die Bibliotheken untereinander voneinander abhängen. Diese Abhängigkeiten können mitunter äußerst verzweigt und vielschichtig sein, so dass es einen enormen Aufwand bedarf, neue Bibliotheken zu installieren.

Damit dieser Aufwand nicht mehr von einem Menschen von Hand betrieben werden muss, haben sich Paketverwaltungs-Tools etabliert und das nicht nur bei Betriebssystems-Distributionen. Was pacman für Arch-Linux ist, ist cabal für Haskell.

Pakete mit cabal installieren

Um mit cabal arbeiten zu können muss dieses Tool auf dem System installiert sein. Unter Arch-Linux existiert cabal-install als installierbares Paket und würde mittels

{% highlight bash %} pacman -Suy cabal-install {% endhighlight %}

installiert werden. Auch die anderen Distributionen bieten Installationspakete für cabal an. Im Falle das es keine Installationspakete für cabal geben sollte, lässt sich cabal auch von Hand aus den Quellen übersetzen.

Cabal hält eine Liste der aktuell installierbaren Paketen bereit. Bevor in irgend einer Weise mit cabal gearbeitet wird, ist es ratsam diese Liste zu aktualisieren. So kann Fehler vorgebeugt werden, die unter Umständen aus veralteten Paketinformationen heraus enstehen.

{% highlight bash %} cabal update {% endhighlight %}

aktualisiert die Paketliste.

Ein Paket mithilfe von cabal zu installieren ist nicht besonders schwierig. Ist der Name des Paketes schon bekannt (z.B. arrows), so wird ein das Paket über folgenden Aufruf installiert:

{% highlight bash %} cabal install arrows {% endhighlight %}

Der exakte Name eines Paketes lässt sich herausfinden. Der Befehl:

{% highlight bash %} cabal list {% endhighlight %}

gibt sämtliche Pakete aus, die in der Liste der installierbaren Pakete stehen. Da dies natürlich viel zu viele Informationen sind, ist es sinnvoller, die Ergebnismenge einzuschränken:

{% highlight bash %} cabal list arrow {% endhighlight %}

Einzig anzeigen welche Pakete aktuell auf dem System installiert sind, lässt sich mittels cabal nicht. Hierzu kann das Tool ghc-pkg bemüht werden.

{% highlight bash %} ghc-pkg list {% endhighlight %}

liefert eine Liste all der Pakte die auf dem System installiert sind. Dabei wird auch angezeigt, wo das Paket installiert ist. Es wird hier unterschieden zwischen einer lokalen, also benutzerweiten, Installation, sowie einer systemweiten Installation.

Die Deinstallation eines Paketes erfolgt ebenso über ghc-pkg mittels:

{% highlight bash %} ghc-pkg unregister old-time-1.1.0.0 {% endhighlight %}

Eigene Pakete und .cabal

Um sich die Arbeit mit eigenen Paketen in Haskell zu erleichtern, ist es ebenso möglich, seine Pakete fit für cabal zu machen. Hierzu wird ein .cabal-File benötigt, dass im Verzeichnis des Paketes liegt.

Diese Datei beschreibt das Paket für den Paketverwalter. Enthalten sind Informationen zu:

  • Autor
  • Version
  • Beschreibung
  • Lizenz
  • Abhängigkeiten

Paketinformationen wie der Name des Paketes, die Version in der sich die Software befindet, eine kurze textuelle Beschreibung, eine Kategorie in die das Paket gehört, sowie die Lizenz unter die Software vertrieben wird:

{% highlight yaml %} name: VHDL version: 0.0 description: Using Arrows to describe Hardware and to generate VHDL code license: BSD3 category: Testing {% endhighlight %}

Autorinformationen sind der Name des Autor, die Email-Adresse des Paketverwalters sowie die URL zu einer Webseite über die Software:

{% highlight yaml %} author: Matthias Brettschneider maintainer: frosch03@gmail.com homepage: http://github.com/frosch03 {% endhighlight %}

Übersetzungsinformationen wie der Typ des Paketes und die benötigte cabal-version:

{% highlight yaml %} cabal-version: >=1.2 build-type: Simple {% endhighlight %}

Library-Abschnitt: Dieser legt fest, ob und wie Paketabschnitte behandelt werden. exposed-modules: wird gefolgt von einer Liste mit Modulen, die im Paket verwendet werden und die nach Außen bekannt gegeben werden sollen. build-depends legt fest, von welchen Paketen dieses Paket abhängt. Diese Information kann nur das Paket enthalten, oder einen mindest Version mit angeben:

{% highlight yaml %} Library build-depends: base 3 exposed-modules: Circuit Circuit.Arrow Circuit.Auxillary Circuit.Descriptor Circuit.Defaults {% endhighlight %}

Executable-Abschnitt: Hier wird wenn nötig beschrieben, ob und woraus ein executable-File erzeugt wird. Hinter main-is: wird die Datei angegeben, welche das Main-Modul enthält. Die Liste hinter other-modules: legt eine Liste von Modulen fest, die nach Außen hin nicht sichtbar sind, aber vom Main-Modul verwendet werden.

{% highlight yaml %} Executable Beispiel main-is: Beispiel.hs other-modules: Circuit Circuit.Arrow Circuit.Auxillary Circuit.Descriptor Circuit.Defaults {% endhighlight %}

die Details zum .cabal-File lassen sich in der Dokumentation zu cabal nachlesen.

Zusätzlich zum .cabal-File wird noch eine Setup.hs benötigt. Dieses File sieht so aus:

{% highlight haskell %} import Distribution.Simple main = defaultMain {% endhighlight %}

Mithilfe dieser beiden Files ist es nun Möglich, die Software zu übersetzten. Hierzu wird auf der Konsole mittels

{% highlight bash %} cabal configure {% endhighlight %}

das Paket konfiguriert. Kompilieren lässt es sich dann mit:

{% highlight bash %} cabal build {% endhighlight %}

Auch lassen sich jetzt mittels cabal alle weiteren Optionen verwenden wie zum Beispiel das erzeugen von Dokumentationen aus dem Quelltext:

{% highlight bash %} cabal haddock {% endhighlight %}

Abschließend

Das arbeiten mit Cabal habe ich selber lange Zeit überhaupt nicht in Betracht gezogen. Erst seit dem ich gerne aus meinen Sourcen die .html-Dokumentation haben wollte, musste ich mir Gedanken zu cabal machen. Allerdings bereue ich hier nichts, denn letztlich handelt es sich hier um enorm wenig Aufwand, der mit einem ganzen Sack voll toller neuer Kleinigkeiten belohnt wird.

Ich denke in Zukunft werde ich alle weiteren Haskell-Projekte immer direkt mit .cabal Files ausstatten, um so von Anfang an mit Cabal zu arbeiten.

Das Repository indem sich das weiter oben genannte .cabal File befindet findet man hier.