Cabal Multiple Executables - haskell

I'm working on a website using Yesod I have the normal build running but I can't seem to populate my database reliably. I have a second haskell program that populates the database and I've added it to my cabal file like this:
executable program
if flag(library-only)
Buildable: False
main-is: ../main.hs
hs-source-dirs: dist
build-depends: base
, myproject
, yesod-default
executable init
if flag(library-only)
Buildable: False
main-is: init.hs
hs-source-dirs: Init
build-depends: base
, directory
, persistent
, persistent-sqlite
, text
, myproject
, yesod-default
The problem is that when I run 'cabal build' it does not rebuild init when init.hs changes. What do I have to do to make this happen?
Here's an example terminal session (after editing init.hs):
$ cabal build
Building myproject-0.0.0...
Preprocessing library myproject-0.0.0...
Registering myproject-0.0.0...
$ rm -rf dist/build/myproject/init
$ cabal build
Building myproject-0.0.0...
Preprocessing library myproject-0.0.0...
Registering myproject-0.0.0...
Thank you.

You can manage multiple executables by passing them as arguments to cabal build and cabal run. For example, cabal build init. The first executable is the default if no target name is given.

Related

How can I configure Cabal to build two executables?

I'm trying to build a Haskell project using Cabal. I have a file src/Main.hs which contains the module Main and a function main. That file runs the web interface of my app. And I have another file, src/CLI.hs which contains the module CLI and a function main. I can run it just fine with runhaskell CLI ..., but I can't seem to compile it using cabal.
The thing is, even if I specify CLI.hs as the main file (main-is: CLI.hs), it still compiles the project with the main from src/Main.hs, thereby giving me the web app instead of the CLI.
I want to be able to compile two executables, one which is the web app, and one which is the CLI, specifying the entry points of each as main in CLI.hs and main in Main.hs, respectively.
Here's the segment of the .cabal file I'm using at the moment:
executable color-word-analyzer-cli
main-is: CLI.hs
other-modules: AnnotateColors
, CategorizeColor
, ColorMaps
, FindColors
, PlotColors
, Types
, Main
build-depends: base
, lucid
...
, wai-middleware-static
hs-source-dirs: src/
default-language: Haskell2010
executable color-word-analyzer-web
main-is: Main.hs
other-modules: AnnotateColors
, CategorizeColor
, ColorMaps
, FindColors
, PlotColors
, Types
, CLI
build-depends: base
, lucid
...
, wai-middleware-static
hs-source-dirs: src/
default-language: Haskell2010
Which throws the error (among others):
Building executable 'color-word-analyzer-cli' for color-word-analyzer-0.1.0.0..
Warning: Enabling workaround for Main module 'Main' listed in 'other-modules'
illegally!
<no location info>: warning: [-Wmissing-home-modules]
These modules are needed for compilation but not listed in your .cabal file's other-modules:
Main
which is funny, since Main is clearly listed there in other-modules.
I'm using cabal version 3.0.0.0, and ghc version 8.8.2.
The fully explicit form of a compilation unit is <package>:<category>:<ident> where in the case the packages is color-word-analyzer, category is exe and ident is the executables. So for your case you can call:
cabal build color-word-analyzer:exe:color-word-analyzer-cli color-word-analyzer:exe:color-word-analyzer-web
Now you don't actually need to specify all of that. When the executable is unique the fact that it is an executable (and not, say, a test from some other package or another package name itself) and the fact that it is from color-word-analyzer is clear in this context. You can therefore call:
cabal build color-word-analyzer-cli color-word-analyzer-web
EDIT: because your link didn't have a stanza for -web I used one of my own creation which didn't include the CLI module. Notice your CLI file is module Main so that explains the error you see - you can't include a module Main as a library module.

Why is `stack build` altering my .cabal file?

I am attempting to build a project which uses Euterpea.
Running stack build I get the following error, suggesting that I need to add Euterpea to the build-depends section of my .cabal file.
$ sb
composition-0.1.0.0: build (lib + exe)
Preprocessing library composition-0.1.0.0...
[2 of 2] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-linux-nix/Cabal-1.24.2.0/build/Lib.o )
/home/matthew/backup/composition/composition/src/Lib.hs:5:1: error:
Failed to load interface for ‘Euterpea’
It is a member of the hidden package ‘Euterpea-2.0.4’.
Perhaps you need to add ‘Euterpea’ to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
-- While building package composition-0.1.0.0 using:
/home/matthew/.stack/setup-exe-cache/x86_64-linux-nix/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux-nix/Cabal-1.24.2.0 build lib:composition exe:composition-exe --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
I add Euterpea there, and the library section of my .cabal file then is the following.
library
hs-source-dirs:
src
build-depends: base >= 4.7 && < 5
, Euterpea
exposed-modules:
Lib
other-modules:
Paths_composition
default-language: Haskell2010
However, when I then run stack build again, it gives the same error -- and changes my .cabal file back to what it was originally, with the library section then looking like
library
hs-source-dirs:
src
build-depends:
base >= 4.7 && < 5
exposed-modules:
Lib
other-modules:
Paths_composition
default-language: Haskell2010
Why is stack build altering my cabal file? I have never seen that occurring before.
Side note:
Not sure if it is related, but the .cabal file's format appears to be different than it normally does. Here as with previous projects I auto-initialized by running stack new <project-name>. I don't know what I might have done different from previous projects to cause this unexpected behavior of stack build.
Make sure package.yaml exists in the root of your project directory.
package.yaml is a new file format to improve the syntax of cabal, converted by hpack.
Stack supports hpack as strongly as the stack build command automatically converts package.yaml into a cabal file with hpack command.
So, delete package.yaml or edit package.yaml to add Euterpea package.
Editing it would not be so difficult as its format is YAML.
I want to add to the YAMAMOTO Yuji's answer. The solution is absolutely right. But I just wanted to add few things, it is not hard to edit the package.yaml.
Step 1 : The trickiest part is finding the correct package name.
Use Hoogle or Stackage to find the package where the module
resides. Read more about how to find package name in this post.
Step 2 : Now you have to open the package.yaml file and add the package name. In your case add 'Euterpea' package in the list of dependencies.
dependencies:
...
- your-package-name
Please note that Euterpea package has to be added in a different way. Please read this
post for better understanding.
Step 3 : Open project-name.cabal in project root and add required package name under build-depends:
library
hs-source-dirs:
src
build-depends:
base >= 4.7 && < 5
, your-package-name
exposed-modules:
Lib
Step 4 :Issue stack build to download and build dependencies
(or stack ghci if you plan to use it in the REPL)
Hope this works! Happy coding! :)

How do I check what version of a package is installed with stack?

Within my project's .cabal file I've got the following under the executable section:
executable ArchPkgstatsScraper
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, ArchPkgStatsScraper
, text
, conduit
, html-conduit
, http-conduit
, xml-conduit
, resourcet
, transformers
After I've successfully installed / built the above with stack, how could I check which version of xml-conduit is installed?
The command
stack ls dependencies
or for older version of stack:
stack list-dependencies
will list every dependency installed for the current project, along with its version.
The new command is going to be
stack ls dependencies
which is replacement of stack list-dependencies
You can read more about it here

How to use stack with nix to build wxHaskell project?

I'm trying to set up a build environment for wxHaskell using Nix and Stack.
I've installed wxWidgets-3.0.2 through nix. This is the relevant portion from by .cabal file
executable hellowx-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, hellowx
, wx
, wxc
, wxcore
, wxdirect
and the stack.yaml file
resolver: lts-5.0
extra-deps:
- wx-0.92.2.0
- wxc-0.92.2.0
- wxcore-0.92.2.0
- wxdirect-0.92.2.0
I tried adding
nix:
enable: true
packages: [wxwidgets]
but that wasn't the right way apparently.
So I got rid of the nix part in the .yaml file and tried the command $ stack --nix build which resulted in failure. The log file said
[1 of 1] Compiling Main ( /run/user/1000/stack8847/wxc-0.92.2.0/Setup.hs, /run/user/1000/stack8847/wxc-0.92.2.0/.stack-work/dist/x86_64-linux-nix/Cabal-1.22.5.0/setup/Main.o )
Linking /run/user/1000/stack8847/wxc-0.92.2.0/.stack-work/dist/x86_64-linux-nix/Cabal-1.22.5.0/setup/setup ...
Error: wx-config not found, please install wx-config before installing wxc
However I do have wx-config and wxwidgets installed through nix. The build process can't find it for some reason. What can I do to set up this build environment? Is there a way to direct the build process to look in the directory containing wx-config? I can't figure out why it can't find it. Its in the PATH.
Ok, I figured it out. I was adding the wrong "attribute name". Here is the correct stack.yaml file
# at this point in time nix supports lts-5.0
resolver: lts-5.0
packages:
-'.'
extra-deps:
- wx-0.92.2.0
- wxc-0.92.2.0
- wxcore-0.92.2.0
- wxdirect-0.92.2.0
# wxwidgets-3.0.2 has the attribute name wxGTK30
# you also need zlib, mesa_noglu and x11
nix:
enable: true
packages: [zlib, wxGTK30, mesa_noglu, x11]
That seems to build everything properly, and I was able to build a minimal window from here (minimal.hs)

How to make a Haskell cabal project with library+executables that still run with runhaskell/ghci?

If you declare a library + executable sections in a cabal file while avoiding double compilation of the library by putting the library into a hs-source-dirs directory, you cannot usually run your project with ghci and runhaskell anymore, especially if the executables have helper modules themselves.
What is a recommended project layout that
only builds what is needed once
allows using runhaskell
has a clean structure without hacks?
Let's assume you have a mylib library, and mylib-commandline and mylib-server executables.
You use hs-source-dirs for the library and each executable so that each has their own project root, avoiding double compilation:
mylib/ # Project root
mylib.cabal
src/ # Root for the library
tests/
mylib-commandline/ # Root for the command line utility + helper modules
mylib-server/ # Root for the web service + helper modules
Full directory layout:
mylib/ # Project root
mylib.cabal
src/ # Root for the library
Web/
Mylib.hs # Main library module
Mylib/
ModuleA # Mylib.ModuleA
ModuleB # Mylib.ModuleB
tests/
...
mylib-commandline/ # Root for the command line utility
Main.hs # "module Main where" stub with "main = Web.Mylib.Commandline.Main.main"
Web/
Mylib/
Commandline/
Main.hs # CLI entry point
Arguments.hs # Programm command line arguments parser
mylib-server/ # Root for the web service
Server.hs # "module Main where" stub with "main = Web.Mylib.Server.Main.main"
Web/
Mylib/
Server/
Main.hs # Server entry point
Arguments.hs # Server command line arguments parser
The stub-like entry point file mylib-commandline/Main.hs looks like this:
module Main where
import qualified Web.Mylib.Server.Main as MylibServer
main :: IO ()
main = MylibServer.main
You need them because an executable must start on a module simply called Main.
Your mylib.cabal looks like this:
library
hs-source-dirs: src
exposed-modules:
Web.Mylib
Web.Mylib.ModuleA
Web.Mylib.ModuleB
build-depends:
base >= 4 && <= 5
, [other dependencies of the library]
executable mylib-commandline
hs-source-dirs: mylib-commandline
main-is: Main.hs
other-modules:
Web.Mylib.Commandline.Main
Web.Mylib.Commandline.Arguments
build-depends:
base >= 4 && <= 5
, mylib
, [other depencencies for the CLI]
executable mylib-server
hs-source-dirs: mylib-server
main-is: Server.hs
other-modules:
Web.Mylib.Server.Main
build-depends:
base >= 4 && <= 5
, mylib
, warp >= X.X
, [other dependencies for the server]
cabal build will build the library and the two executables without double compilation of the library, because each is in their own hs-source-dirs and the executables depend on the library.
You can still run the executables with runghc from your project root, using the -i switch to tell where it shall look for modules (using : as separator):
runhaskell -isrc:mylib-commandline mylib-commandline/Main.hs
runhaskell -isrc:mylib-server mylib-server/Server.hs
This way, you can have a clean layout, executables with helper modules, and everything still works with runhaskell/runghc and ghci. To avoid typing this flag repeatedly, you can add something similar to
:set -isrc:mylib-commandline:mylib-server
to your .ghci file.
Note that sometimes should split your code into separate packages, e.g. mylib, mylib-commandline and mylib-server.
You can use cabal repl to start ghci with the configuration from the cabal file and cabal run to compile and run the executables. Unlike runhaskell and ghci, using cabal repl and cabal run also picks up dependencies from cabal sandboxes correctly.

Resources