How can I configure Cabal to build two executables? - haskell

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.

Related

How to import Control.Lens in Haskell?

I am new to Haskell. I want to use Control.Lens package. I've read this and applied what it says but I get an error that says:
Resolving dependencies...
cabal-3.6.2.0.exe: Cannot build the executables in the package lens because it
does not contain any executables. Check the .cabal file for the package and
make sure that it properly declares the components that you expect.
when I try to run cabal install lens in the project folder.(I opened terminal in the project folder.)
Any help would be appreciated.
Solution: I've learned that I need to add 'lens' into build-depends part of .cabal file.Then I need to import Control.Lens inside Main.hs . I give my .cabal file as an example:
executable Prelude3
main-is: Main.hs
-- Modules included in this executable, other than Main.
--other-modules: Basic
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
build-depends: containers,lens,microlens,microlens-platform,base ^>=4.14.3.0
hs-source-dirs: app
default-language: Haskell2010
On the top of the Main.hs I write import Control.Lens. Finally after I run 'cabal build' and cabal run in the terminal necessary packages successfully downlaoaded.

How to fix a "could not find module" error in Cabal, when it seems correctly specified?

I'm currently not using stack at all on this project (just Cabal), and all was going well when everything was in Main.hs. I decided to split up code, moving my dhall dep and related code from my executable deps to my library deps, and now seem to have this strange error when running cabal new-build:
Building executable 'FarmDataServer.exe' for FarmDataServer-0.1.0.0..
<no location info>: warning: [-Wmissing-home-modules]
These modules are needed for compilation but not listed in your .cabal file's other-modules: FDS
FDS.Config.Core
FDS.Config.DhallConf
[2 of 4] Compiling FDS.Config.DhallConf ( src/FDS/Config/DhallConf.hs, /home/brandon/workspace/CIDA/FarmDataServer/dist-newstyle/buil
d/x86_64-linux/ghc-8.4.4/FarmDataServer-0.1.0.0/x/FarmDataServer.exe/build/FarmDataServer.exe/FarmDataServer.exe-tmp/FDS/Config/Dhall
Conf.o )
src/FDS/Config/DhallConf.hs:7:1: error:
Could not find module `Dhall'
Use -v to see a list of the files searched for.
|
7 | import Dhall
| ^^^^^^^^^^^^^^^^^^^^^^
Certainly I'm also a bit confused by the Wmissing-home-modules message since I seem to have added those in my cabal file.
Relevant bits of my .cabal file:
cabal-version: 2.4
name: FarmDataServer
version: 0.1.0.0
library
exposed-modules:
FDS
other-modules:
FDS.Config.Core
, FDS.Config.DhallConf
build-depends: base ^>=4.11.1.0
, conduit ^>=1.3.1
, csv-conduit ^>=0.7.0.0
, dhall ^>=1.20.0
, text ^>=1.2.3.1
hs-source-dirs: src
executable FarmDataServer.exe
main-is: Main.hs
build-depends: base ^>=4.11.1.0
, conduit ^>=1.3.1
, csv-conduit ^>=0.7.0.0
, scotty ^>=0.11.3
, text ^>=1.2.3.1
, FarmDataServer ^>=0.1.0.0
My src folder:
$ pwd
/home/brandon/workspace/CIDA/FarmDataServer/src
$ du -a
4 ./FDS/Config/DhallConf.hs
4 ./FDS/Config/Core.hs
12 ./FDS/Config
16 ./FDS
4 ./FDS.hs
4 ./Main.hs
28 .
For the missing modules, sink your program executable into a directory such that the module hierarchy for yoru library isn't visible:
mkdir program ; mv src/Main.hs program/
and in cabal for the executable
hs-source-dirs: program
For your missing module Dhall, add the dhall build dependency to your executable stanza in the cabal file.

Haskell Stack + Cabal ignore 'main-is' option and fail to build app [duplicate]

This question already has answers here:
Cabal output is redirected but not generated
(3 answers)
Closed 6 years ago.
Q: How to adjust cabal(stack?) settings so that app/LogAnalysis.hs is treated as main log after all?
Here is how I got myself this error:
Created new project with stack new xyz
Renamed app/Main.hs to app/LogAnalysis.hs
Adjusted main-is option in xyz.cabal file
Problem is I either entered that data somehow incorrectly or cabal ignores that new value. Here is error I get:
Preprocessing executable 'WeekTwo-exe' for WeekTwo-0.1.0.0...
<no location info>: error:
output was redirected with -o, but no output will be generated
because there is no Main module.
Here is relevant entry in xyz.cabal
executable WeekTwo-exe
hs-source-dirs: app
main-is: LogAnalysis.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, WeekTwo
default-language: Haskell2010
And module in question is:
module LogAnalysis where
import Log
main :: IO ()
main = print (parseMessage "I 29 la la")
Versions:
Stack - Version 1.3.2
GHC - 7.15
Cabal - 1.24.0.0
PS if it's of any interest I'm doin 2nd week of Haskel course CIS 194.
Is it possible you changed module Main where to module LogAnalysis where? If you did, you would get exactly this error.
Main-is just says check for the Main module inside this file, but it must still be the Main module, not the LogAnalysis module. This makes it clear that the main function in this file should be run, rather than some main functions that might happen to exist in some other modules.

plugins package unknown symbol when using cabal

I'm messing around with the plugins package however I bumped into a problem.
Here's the code:
Util/Header.hs
module Util.Header(PT(..)) where
data PT a = PT a deriving Show
Plug.hs
module Plug(helloPlugin) where
import Util.Header
helloPlugin :: PT Int
helloPlugin = PT 1
Main.hs
module Main where
import Util.Header
import System.Plugins
main :: IO ()
main = do
mv <- load "Plug.o" ["."] [] "helloPlugin"
case mv of
LoadFailure msg -> print msg
LoadSuccess _ v -> print $ show (v :: PT Int)
This all works fine then compiling with ghc. Building with Cabal works fine as well, but when I run the executable I get this error:
plugintest: /home/kevin/.cabal/lib/plugins-1.5.4.0/ghc-7.6.3/HSplugins-1.5.4.0.o: unknown symbol `ghczm7zi6zi3_ErrUtils_zdsinsertzuzdsgo5_info'
plugintest: user error (resolvedObjs failed.)
My very minimalistic cabal file:
name: plugintest
version: 0.1.0.0
license-file: LICENSE
build-type: Simple
cabal-version: >=1.8
library
hs-source-dirs: src
exposed-modules: Util.Header
build-depends: base ==4.6.*, plugins ==1.5.*
executable plugintest
main-is: Main.hs
build-depends: base ==4.6.*, plugins ==1.5.*, plugintest == 0.1.0.0
hs-source-dirs: src
Now I assume the problem is that it can't find the "ErrUtils" module which is part of the ghc package installed in /usr/lib/ghc-7.x.x.
Since it's using cabal it'll use the $HOME/.cabal/lib/ instead.
Now I obviously wouldn't want to use /usr/lib if I wanted to make it distributable. Sadly I'm not very familiar with how packages are managed nor am I familiar with the plugins package.
I have a feeling this is extremly nooby but I wasn't able to find a solution myself.
So a few questions:
How can I get my dependencies to work in a way to make this distributable?
It seems I'll need to know beforehand what my Plugin.o files will depend on before actually being able to use them (If I understand correctly).
Is there a way to package a .o files that I wouldn't have to worry about this problem? (Sorry if this question is too vague, feel free to ignore)
Thanks in advance!
Ok, so I had the exact same problem.
Here is a workaround I found
Change the load call to
load "Plug.o" [".","dist/build/plugintest/plugintest-tmp"] [] "testplugin"
Make sure you compile the thing with -c or by using the "make" library from plugins.
Quite annoyed by this... The error suggests it is having issues linking against the standard libs, so why does showing it these .o files fix it?
Anyways, this worked for me, and didn't require a ton of mucking around with .cabal files.
You must declare your exported- and other- modules in order for Cabal to package them all together. For instance (from https://github.com/tel/happstack-heroku-test)
name: hktest -- note the name here names
-- the *library* which is a package name
-- in scope when building the executable
...
library
exposed-modules:
HKTest
other-modules:
-- there aren't any, but there could be some
build-depends: base >= 4.6 && <4.7
...
, mtl >= 2.1.2
hs-source-dirs: src
executable server
main-is: Server.hs
other-modules:
-- there might be some use to having these here,
-- but they'll be harder to get into GHCi, so I wouldn't
-- recommend it---just put them in the library part
build-depends: base >=4.6 && <4.7
, hktest -- note that I grab all the hktest
-- modules here
hs-source-dirs: exe
If I leave out one of those modules I'll likely get a build error as Cabal compiles files which expect to be able to find symbols that haven't been packaged.
In your case, since you're building an executable, the common pattern exemplified above is to put all of your code into a library and then have the executable side depend upon that library. For instance, in this example the complete text of exe/Server.hs is
module Main where
import qualified HKTest as HK
main :: IO ()
main = HK.main

How to configure build-dependencies in haskell+cabal?

I have to build some app that depends on OS. For example I'm searching over directory, and if I see some item is symbolic link (in linux), I just skip them and go over. To check this I use function System.Posix.Files.isSymbolicLink that ships by "unix" package. The problem is that this package would not build on Windows, and I have to bypass this limitation somehow when app builds on Windows. I've tried this trick:
1) Created additional file: ./System/Posix/Files.hs, where exposed function isSymbolicLink which always returns False.
2) Updated .cabal file with following:
if os(windows)
other-modules: System.Posix.Files
else
build-depends: unix
But, despite my configuration, cabal build always builds my /System/Posix/Files.hs since I have import System.Posix.Files in my main.hs:
Preprocessing executables for test-1.1.1...
Building test-1.1.1...
[1 of 2] Compiling System.Posix.Files ( System/Posix/Files.hs, dist/build/test/test-tmp/System/Posix/Files.o )
[2 of 2] Compiling Main ( main.hs, dist/build/test/test-tmp/Main.o )
Linking dist/build/test/test ...
So even I build on linux, application gets my blank isSymbolicLink function instead those provided by "unix" package. How can I tell to cabal do not include this file, and use module provided by "unix" package when I build on linux? Or maybe there is some another approach to solve such problems?
This can be solved using the CPP preprocessor.
In your .cabal file, add
if os(windows)
Cpp-options: -DWINDOWS
else
Build-depends: unix
Then add a module which will conditionally export isSymbolicLink from the unix package, or a dummy one for Windows.
{-# LANGUAGE CPP #-}
module Compatibility (isSymbolicLink) where
#ifndef WINDOWS
import System.Posix.Files
#else
isSymbolicLink _ = return False
#endif
Now just import this module whereever you need to use this function, and you should be good to go.
Another option is to stick with your initial approach, but move your System/Posix/Files.hs into a subdirectory which you conditionally add to Hs-Source-Dirs.
if os(windows)
Other-modules: System.Posix.Files
-- Assuming you moved it to windows/System/Posix/Files.hs
Hs-source-dirs: .,windows
else
Build-depends: unix
Hs-Source-Dirs: .

Resources