Using alex/happy with Cabal - haskell

I'm writing a compiler for a class I'm taking. The class isn't specifically Haskell but I'm using Haskell to write my compiler and interpreter. I have a cabal package setup to hopefully make it easy for my prof to run/compile. I have happy and alex in the build-tools field for both executables but Cabal ignores that and then complains that it cannot find the modules that Happy and Alex should be generating. If I manually run:
alex LimpScanner.x
happy LimpParser.y
then cabal runs perfectly.
I thought I had cabal automatically running them earlier but perhaps I remember imperfectly.
limp.cabal:
-- limp.cabal auto-generated by cabal init. For additional options,
-- see
-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.
-- The name of the package.
Name: limp
-- The package version. See the Haskell package versioning policy
-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
-- standards guiding when and how versions should be incremented.
Version: 0.1
-- A short (one-line) description of the package.
Synopsis: LIMP Compiler (Compiler Construction course project)
-- A longer description of the package.
-- Description:
-- URL for the project homepage or repository.
Homepage: http://www.cs.rit.edu/~eca7215/limp/
-- The license under which the package is released.
License: AllRightsReserved
-- The file containing the license text.
License-file: LICENSE
-- The package author(s).
Author: Edward Amsden
-- An email address to which users can send suggestions, bug reports,
-- and patches.
Maintainer: eca7215#cs.rit.edu
-- A copyright notice.
-- Copyright:
Category: Language
Build-type: Simple
-- Extra files to be distributed with the package, such as examples or
-- a README.
-- Extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
Cabal-version: >=1.2
Executable limp
-- .hs or .lhs file containing the Main module.
Main-is: Limp.hs
hs-source-dirs: src
-- Packages needed in order to build this package.
Build-depends: base, array, haskell98
-- Modules not exported by this package.
-- Other-modules:
-- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
Build-tools: alex, happy
Executable limpi
Main-is: LimpInterpreter.hs
hs-source-dirs: src
Build-depends: base, array, haskell98
Build-tools: alex, happy
Directory layout:
limp/
├── Setup.hs
├── limp.cabal
└── src/
├── Limp.hs
├── LimpInterpreter.hs
├── LimpParser.ly
├── LimpScanner.x
└── LimpToken.hs

For Warren Harris and others like him (and myself) that may come along later, other-modules needs to be set to a list of module names that (I guess?) are expected to be built by the tools listed in build-tools.
So, in my case, the relevant sections of my .cabal file ended up looking like this:
build-tools: alex, happy
other-modules: Language.Heidi.Parser,
Language.Heidi.Lexer

Apparently what I was missing was actually the Other-modules: field. Once this was added, cabal happily (pardon the pun) built my interpreter.

Related

cabal new-sdist includes test files as well

I want to create an sdist package for my Haskell project.
For simplicity let's assume the following project structure:
/ root
| src
| MyLib.hs
| test
| MyLibTest.hs
| Changelog.md
| MyProject.cabal
| LICENSE
There are two targets defined in the cabal file
library
exposed-modules: MyLib
hs-source-dirs: src
-- ...
test-suite: MyProject-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: MyLibTest.hs
-- ...
When I execute cabal new-sdist --list-only I get the following list:
./changelog.md
./MyProject.cabal
./LICENSE
./src/MyLib.hs
./test/MyLibTest.hs
My question: is it ok to include the test-related files in the sdist package or shall I remove them (if so - how)?
Well if you try to generate a library-only sdist, you get this error:
$ cabal new-sdist --list-only <library-name>
cabal: The component library cannot be packaged for distribution on its own.
Only entire packages may be packaged for distribution.
So I'd say it's recommended to upload the whole thing.
Hackage does let you preview a library before publishing it, using package candidates. I'd say upload your source tarball as a package candidate, and double check your tests don't show up.

When does cabal recompile a module which contains Template Haskell?

I understand that cabal will recompile a module if the interface of any of its dependencies has changed. It seems that this simple rule does not hold if the module contains Template Haskell. In that case, even just adding a trailing newline character to a file in the module's (transitive) dependencies will cause the cabal to recompile the file.
Minimal example:
file: Foo.hs
module Foo where
foo = "foo"
file: FooTH.hs
{-# LANGUAGE TemplateHaskell #-}
module FooTH where
import Data.Bifunctor.TH
import Foo
data FooPair a b = FooPair a b
$(deriveBifunctor ''FooPair)
file: MCVE.cabal
name: MCVE
version: 0.1.0.0
synopsis: MCVE
license: MIT
license-file: LICENSE
author: tarleb
maintainer: tarleb#example.com
build-type: Simple
extra-source-files: CHANGELOG.md
cabal-version: >=1.10
library
exposed-modules: Foo
, FooTH
build-depends: base >=4.8 && <4.13
, bifunctors
default-language: Haskell2010
Adding a newline to Foo.hs, e.g. by running echo "\n" >> Foo.hs, will cause recompilation of module FooTH. This ceases to happen if the TH line in FooTH is commented out.
What is the reason for this, and is there a way to avoid this unnecessary recompilation?
There's a feature in Template Haskell called addDependentFile, which adds metadata to the .hi file indicating that the source file in question depends on another file as well. To my knowledge, Cabal will always ask GHC to try to build, though it may have more intelligent logic. Stack tries to bypass that process, and has logic to parse the addDependentFile information out.

Set up Haskell Project and run tests

I'm trying to set up a Haskell project (library) with tests that I can use to work through The Haskell Road to Logic, Maths, and Programming. There are three parts that I'd like to have:
The code that comes with the book, in a subdirectory
The code I write for exercises in the book; one file per chapter
The code I write for tests; one file per chapter
I have attempted a project setup here, but am getting the following cabal error:
Resolving dependencies...
Configuring haskell-road-0.1.0.0...
Building haskell-road-0.1.0.0...
Failed to install haskell-road-0.1.0.0
Build log ( /Users/stuart/.cabal/logs/haskell-road-0.1.0.0.log ):
cabal: Entering directory '.'
Configuring haskell-road-0.1.0.0...
Building haskell-road-0.1.0.0...
Preprocessing library haskell-road-0.1.0.0...
src/Chapter1.hs:1:1:
File name does not match module name:
Saw: ‘Main’
Expected: ‘Chapter1’
cabal: Leaving directory '.'
cabal: Error: some packages failed to install:
haskell-road-0.1.0.0 failed during the building phase. The exception was:
ExitFailure 1
I'd like to be able to run $ cabal test and have all of the tests run, and have the import paths work. Any help is appreciated. I think there are probably issues with the test structure, but I've had trouble finding definitive guides on the actual setup.
EDIT: More details
src/
Chapter1.hs
Book/
GS.hs
etc....
test/
Chapter1Test.hs
MainTestSuite.hs
TestHelper.hs
haskell-book.hs:
-- Initial haskell-road.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
-- The name of the package.
name: haskell-road
-- The package version. See the Haskell package versioning policy (PVP)
-- for standards guiding when and how versions should be incremented.
-- https://wiki.haskell.org/Package_versioning_policy
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.1.0.0
-- A short (one-line) description of the package.
-- synopsis:
-- A longer description of the package.
-- description:
-- The license under which the package is released.
license: MIT
-- The file containing the license text.
license-file: LICENSE
-- The package author(s).
author: Stuart Terrett
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: shterrett#gmail.com
-- A copyright notice.
-- copyright:
-- category:
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- README.
extra-source-files: ChangeLog.md
-- Constraint on the version of Cabal needed to build this package.
cabal-version: >=1.10
library
-- Modules exported by the library.
exposed-modules: Chapter1, Book.COR, Book.DB, Book.FAIS, Book.FCT, Book.GS, Book.Hierarchy, Book.IAR, Book.Nats, Book.POL, Book.Polynomials, Book.PowerSeries, Book.Query, Book.REL, Book.SetEq, Book.SetOrd, Book.STAL, Book.TAMO, Book.TUOLP, Book.WWN
-- Modules included in this library but not exported.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
other-extensions: FlexibleInstances
-- Other library packages from which modules are imported.
build-depends: base, random >=1.1 && <1.2, HUnit >=1.3 && <1.4
-- Directories containing source files.
hs-source-dirs: src
-- Base language which the package is written in.
default-language: Haskell2010
test-suite haskell-road-tests
type: exitcode-stdio-1.0
hs-source-dirs: tests, src
main-is: MainTestSuite.hs
build-depends: base,
HUnit,
QuickCheck,
test-framework,
test-framework-hunit,
test-framework-quickcheck2
MainTestSuite.hs
import Chapter1Test
exitProperly :: IO Counts -> IO ()
exitProperly m = do
counts <- m
exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess
allTests::[Test]
allTests = [Chapter1Test.itRuns]
main :: IO ()
main = exitProperly (runTestTT (TestList allTests))
Diff of all changes:
http://lpaste.net/5997592404872396800
Specific changes you need to make:
In Chapter1.hs make sure module Chapter1 appears before the import statement:
module Chapter1 where
import ...
In each of the Book modules you need to add the prefix Book. to
each of the module statements, e.g. in Book/COR.hs:
change: module COR
to: module Book.COR
Also, any import statement will also need the Book. prefix, i.e. in Book/STAL.hs:
change: import DB
to: import Book.DB
(It might easier just to leave the book's modules at the top-level of the module name space.)
To fix this compilation error:
src/Book/IAR.hs:131:7:
No instance for (Foldable t3) arising from a use of ‘foldr’
just add {-# LANGUAGE NoMonomorphismRestriction #-} to the top of Book/IAR.hs (it should be the very first line.)
To fix this compilation error:
src/Book/FAIS.hs:14:4: Parse error in pattern: n + 1
change: f (n+1) = True : f n to f n = True : f (n-1).
This is called an n+k pattern and more info about it (and why it has been deprecated) is available here: What are "n+k patterns" and why are they banned from Haskell 2010?
In the test-suite section you have:
hs-source-dirs: tests, src
To use the code in the src directory you tests should depend on the haskell-road library instead of compiling the source code. That is, use these lines in the test-suite section:
hs-source-dirs: tests
build-depends: base, haskell-road, HUnit, ...
File test/Chapter1Test.hs needs a module statement:
module Chapter1Test where
and also fix this import statement:
-import TestHelper.testCase
+import TestHelper (testCase)
File test/MainTestSuite.hs needs these import statements:
import System.Exit
import Test.HUnit
File test/testHelper.hs needs to be renamed to test/TestHelper.hs
and also needs this import statement:
import Test.HUnit
Cabal has
developing packages link and cabal file content structure is described there.
By looking the error message, it seems that your haskell library source file Chapter1 starts with module Main where. It should contain module Chapter1 where, as the error message says.
Libraries should not contain main while the test-executables should, which is why you state in the cabal file the test executables with main-is.
Hope this helps! (I didn't look at the github sources, just the error message.)

Cabal: Does not exists in Windows 8.1

Today I installed windows 8.1 and haskell on my laptop. I'm trying to build my own haskell library, but I got an error when I try to use cabal sdist. This is the error:
D:\Development\School\AFP\Assignments\Practice\Exercise\Project>cabal sdist
Distribution quality errors:
'license: NONE' is not a recognised license. The known licenses are: GPL,
GPL-2, GPL-3, LGPL, LGPL-2.1, LGPL-3, AGPL, AGPL-3, BSD2, BSD3, MIT, ISC,
MPL-2.0, Apache, Apache-2.0, PublicDomain, AllRightsReserved, OtherLicense
Distribution quality warnings:
No 'category' field.
No 'maintainer' field.
No 'synopsis' field.
A 'license-file' is not specified.
When distributing packages it is encouraged to specify source control
information in the .cabal file using one or more 'source-repository' sections.
See the Cabal user guide for details.
Note: the public hackage server would reject this package.
Warning: Cannot run preprocessors. Run 'configure' command first.
Building source dist for Project-0.1.0.0...
cabal: does not exist
Before I used the "cabal sdist" I used the following commands:
cabal init
cabal sandbox init
cabal install -j
Every command succeed, except for the cabal sdist. The cabal install only gives the following warning:
D:\Development\School\AFP\Assignments\Practice\Exercise\Project>cabal install -j
Resolving dependencies...
In order, the following will be installed:
Project-0.1.0.0 (reinstall)
Warning: Note that reinstalls are always dangerous. Continuing anyway...
Notice: installing into a sandbox located at
D:\Development\School\AFP\Assignments\Practice\Exercise\Project\.cabal-sandbox
Configuring Project-0.1.0.0...
Building Project-0.1.0.0...
Installed Project-0.1.0.0
This is my Project.cabal file:
-- Initial Project.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
-- Initial Project.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
name: Project
version: 0.1.0.0
-- synopsis:
description: Education
license: NONE
-- license-file:
-- author:
-- maintainer:
-- copyright:
-- category:
build-type: Simple
extra-source-files: File6, File5, File4, File3, File2
cabal-version: >=1.10
library
exposed-modules: File1
-- other-modules:
-- other-extensions:
build-depends: base >=4.8 && <4.9, QuickCheck >=2.8 && <2.9
hs-source-dirs: src
default-language: Haskell2010
I tried google, but I can't find a good solution. I use the following versions:
Cabal version: 1.22.4.0
Haskell version: 7.10.2
If you need more information, please ask.
I don't know anything about sdist, but the problem is clear: you've specified 'NONE' as the license in your cabal file, but that is not allowed for the sdist option. configure, build, and init don't care about the specific license, but sdist apparently does.
For more info, I searched google for "cabal sdist" and found this.
This [cabal sdist] has the advantage that Cabal will do a bit more checking, and ensure that the tarball has the structure that HackageDB expects.
HackageDB probably expects a valid license, hence why "NONE" is not allowed.
The problem was that cabal could not find the files in extra-source-files. I thought I didn't had to add the extension of the haskell files, but this is required.
I also had another problem. The extra-source-files wasn't using the hs-source-dirs, so I had to explicitly write "src/" infront of a file.

Automatically List Dependencies For a Project

Given a Haskell project, is there a way to automatically calculate the entire list of dependencies? All the libraries it depends on as well as libraries that have been included but are not required.
As I said in the comments, cabal-install already does this (I'm using cabal-install 0.14.0) by guessing the packages via module lookup (like GHCi). It doesn't have any real intelligence w.r.t. versions so it just sets the version to the match major version of what you have installed.
Below you can see me making a dummy package that imports Data.Vector and cabal-install infers I am using vector 0.9.*.
[tommd#mavlo blah]$ pwd
/tmp/blah
[tommd#mavlo blah]$ cat Data/Blah.hs
module Data.Blah where
import Data.Vector
[tommd#mavlo blah]$ cabal init
Package name? [default: blah]
...SNIP...
What does the package build:
1) Library
2) Executable
Your choice? 1
Include documentation on what each field means (y/n)? [default: n]
Guessing dependencies... <--- SEE, SEE! YAY!
Generating LICENSE...
Warning: unknown license type, you must put a copy in LICENSE yourself.
Generating Setup.hs...
Generating blah.cabal...
You may want to edit the .cabal file and add a Description field.
[tommd#mavlo blah]$ cat blah.cabal
-- Initial blah.cabal generated by cabal init. For further documentation,
-- see http://haskell.org/cabal/users-guide/
name: blah
version: 0.1.0.0
synopsis: Sisponys
-- description:
-- license:
license-file: LICENSE
author: Me
maintainer: No#No.No
-- copyright:
-- category:
build-type: Simple
cabal-version: >=1.8
library
exposed-modules: Data.Blah
-- other-modules:
build-depends: base ==4.5.*, vector ==0.9.* <-- SEE?? SEE! YIPPEE!!

Resources