Executable within a library and while using the same library in cabal - haskell

This is my first try at an open source project, but I still can't get the right way to set up my .cabal file.
I have have library, an executable and a (soon to come) test config.
I want to use the library and within the executable, so the both of them can be used when it gets downloaded.
I followed this guide, but I'm still struggling with the cabal-config as I only get it to work while importing everything again.
My current directory
- src/
- Main.hs
- Format/
- C.hs
- Converter.hs
- Raw.hs
- RGB565.hs
- tests/...
- dist/...
- UTFTConverter.cabal
The executable Main.hs header looks like this.
module Main where
import Format.C
import Format.Converter
The library files in Format/ look like this.
module Format.{filename} where
...
This is what the cabal file looks like.
name: UTFTConverter
...
cabal-version: >=1.10
library
exposed-modules: Format.C
, Format.Converter
, Format.Raw
, Format.RGB565
build-depends: base >=4.7 && <4.8
, filepath >=1.3 && <1.4
, directory >=1.2 && <1.3
, time >=1.4 && <1.5
, bytestring >=0.10 && <0.11
, JuicyPixels >=3.2 && <3.3
hs-source-dirs: src
...
executable UTFTConverter
main-is: Main.hs
build-depends: base >=4.7 && <4.8
, filepath >=1.3 && <1.4
, directory >=1.2 && <1.3
, time >=1.4 && <1.5
, bytestring >=0.10 && <0.11
, JuicyPixels >=3.2 && <3.3
--, UTFTConverter ==0.1 <-- this does not work
hs-source-dirs: src
...
test-suite tests:
...
Without the comment this error comes up when I cabal build.
...
cabal: At least the following dependencies are missing:
UTFTConverter ==0.1
...
It works right now, but in the tutorial the executable was using the library in the same cabal file.
executable bassbull
main-is: Main.hs
ghc-options: -rtsopts -O2
build-depends: base,
bassbull, -- <-- this is the name of the library
bytestring,
cassava
hs-source-dirs: src
default-language: Haskell2010
I know this is currently working, but I would rather use it the right way from the start. Is this the "right" way?

That's due to your library version being 0.1.0.0, not 0.1. They don't match up exactly, thus cabal doesn't recognize your library as a candidate. Instead, use 0.1.* or 0.1.0.0 depending on your version policy:
executable UTFTConverter
main-is: Main.hs
build-depends: base >=4.7 && <4.8
, filepath >=1.3 && <1.4
, directory >=1.2 && <1.3
, time >=1.4 && <1.5
, bytestring >=0.10 && <0.11
, JuicyPixels >=3.2 && <3.3
, UTFTConverter ==0.1.0.0
hs-source-dirs: src
References
Cabal User Guide, section "Build Information".

Related

C directory in Haskell .cabal file

I have this .cabal file:
...
main-is: Main.hs
other-extensions: ForeignFunctionInterface
build-depends: base >=4.9 && <4.10
hs-source-dirs: src/haskell
c-sources: src/c/main.c ...
default-language: Haskell2010
I have a lots of c source files, all in one directory(src/c), is there a way to add them all without specifying each one? something like a regex:
-- I know this won't work
c-sources: src/c/**
Or just including the whole directory:
-- I know this won't work
c-source-dirs: src/c
?
Try: c-sources: src/c/*.c
** wildcards were added in Cabal 2.4
Wildcard examples from here: https://www.haskell.org/cabal/users-guide/developing-packages.html?highlight=c%20source#pkg-field-data-files

How do I import a text file in a cabal project?

In app/Main.hs, I want to open a text file, "foo.txt". I know how to open a text file in a plain Haskell program. In my cabal project,
import System.IO
Main = do
contents <- readFile "foo.txt"
print $ Main.lex contents
return contents
type Keyword = String
lex :: String -> [Keyword]
lex "" = []
lex x = words x
gives the error
openFile: does not exist (No such file or directory)
What do I need to change in my cabal file, or the file path or location to be able to open the file? I've tried putting it next to the output binary, and that doesn't work either.
This is my cabal file:
-- This file has been generated from package.yaml by hpack version 0.28.2.
--
-- see: https://github.com/sol/hpack
--
-- hash: baf2fc7e230f4b4937dfd918a13fefb55b66c7a4468b24d0e3e90cad675b26d5
name: CCompiler
version: 0.1.0.0
description: Please see the README on GitHub at <https://github.com/githubuser/CCompiler#readme>
homepage: https://github.com/githubuser/CCompiler#readme
bug-reports: https://github.com/githubuser/CCompiler/issues
author: Author name here
maintainer: example#example.com
copyright: 2018 Author name here
license: BSD3
license-file: LICENSE
build-type: Simple
cabal-version: >= 1.10
extra-source-files:
ChangeLog.md
README.md
source-repository head
type: git
location: https://github.com/githubuser/CCompiler
library
exposed-modules:
Lib
other-modules:
Paths_CCompiler
hs-source-dirs:
src
build-depends:
base >=4.7 && <5
default-language: Haskell2010
executable CCompiler-exe
main-is: Main.hs
other-modules:
Paths_CCompiler
hs-source-dirs:
app
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
CCompiler
, base >=4.7 && <5
default-language: Haskell2010
test-suite CCompiler-test
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
Paths_CCompiler
hs-source-dirs:
test
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
CCompiler
, base >=4.7 && <5
default-language: Haskell2010
add
data-dir: data
in the top section of the cabal file.
create the directory 'data' next to src and app, and put all files in there.
Make sure your cabal file also has this line
other-modules:
Paths_CCompiler
with your project's name instead of CCompiler.
My main function is now this
module Main where
import Lib
import System.IO
import Paths_CCompiler
main = do
filepath <- getDataFileName "return_2.c"
contents <- readFile filepath
print $ Lib.lex contents
return contents
Thanks to this blog post.
I understand your question to be about finding files at runtime, which you want to process and aren't packaged with your package.
Where are severals ways, how you could find files at runtime, which aren't packaged.
Either add an command line flag and call your executable with the absolute path of the file you want to process.
Or implement a file chooser dialog, with e.g. gi-gtk.
Or hard coding relative paths which isn't advisable, as they are interpreted relative to the current working directory of your process, which can be different, depending on how the program did get started.
If you want to determine, which current working directory your program runs in, if started with cabal run, just do a litte test project with the following cabal file:
name: test2
build-type: Simple
cabal-version: >= 1.10
version: 0.0.0.1
executable test2
hs-source-dirs: .
main-is: test2.hs
build-depends:
base
, directory
and the following test2.hs:
module Main where
import System.Directory
main :: IO ()
main = do
cwd <- getCurrentDirectory
putStrLn cwd

How to make Stack only build one executable? stack build :exe1 doesn't work?

I have multiple executables in one of my Stack projects:
executable m1
hs-source-dirs: src
main-is: Main1.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
executable m2
hs-source-dirs: src
main-is: Main2.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
I would like to build only one of them at a time. From the documentation and this other question, it would seem that the following command should work:
stack build :m2
but what actually happens is that both executables, m1 and m2, are always built regardless of whether I include the package name, the package type, etc.
What could be causing this?
It's not possible at the moment. See https://github.com/commercialhaskell/stack/issues/1406

Haskell stack not building test executable

Background
I'm building a logfile parser in Haskell. I'm using stack to build it. Running the stack build command works happily and my project compiles. Running stack test, however, produces the following error:
parser-test: executable not found
I see the the following warning above the error message but I don't know how to avoid the redirect to which it refers.
Warning: output was redirected with -o, but no output will be generated because there is no Main module.
Relevant files
I haven't written any tests yet so the test file is as it was created by stack new. My cabal file looks like this:
...
category: Executable
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: LogParser
build-depends: base >= 4.7 && < 5
, attoparsec
, bytestring
, old-locale
, time
default-language: Haskell2010
executable parser-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, attoparsec
, bytestring
, old-locale
, time
, parser
default-language: Haskell2010
test-suite parser-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, attoparsec
, bytestring
, hspec
, hspec-attoparsec
, old-locale
, time
, parser
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
source-repository head
type: git
...
I presume I'm missing something but I can't find where what I'm missing is documented.
Desired behaviour
I should see the Test suite not yet implemented message outlined in the stack documentation.
The content of the test/Spec.hs file from the template is:
main :: IO ()
main = putStrLn "Test suite not yet implemented"
You can see this content at commercialhaskell/stack-templates in new-template.hsfiles.
I'm not sure where the module ParserSpec where line comes from (as brought up in the Github issue), but it's not part of the template. On my system, stack new bar && cd bar && stack test succeeds.
As to the reason behind the Main module requirement: it comes from the Cabal library, and as I understand it was added due to limitations in other compilers Cabal supports. In other words, GHC could technically allow this code to compile, but Cabal does not pass in those arguments to remain compatible with other compilers.

Can you have an executable and library in the same cabal package

I'm new using cabal and I need my package to include a small executable as well as the whole library.
Is it possible to do so (to export an executable AND a library) or does a cabal package have a type (executable OR binary).
Is it also possible to export many executable in the same packagke ?
Yes you can. For example, here is the corresponding excerpt of the HaskellStarter project, that I highly recommend:
-- configuration for building a library
library
hs-source-dirs: src
exposed-modules:
HaskellStarter.CommitPrinter
other-modules:
HaskellStarter.Util
build-depends:
base >= 4 && < 5,
github >= 0.7.4 && < 0.8
-- configuration for an executable
executable githubCommitPrinter
hs-source-dirs: executables
main-is: Main.hs
build-depends:
base >= 4 && < 5,
haskell-starter
Notice how the library is reused in the executable dependencies.

Resources