ghc-mod does not use my cabal sandbox. why? - haskell

runghc -package-db=.cabal-sandbox/.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d hellowai.hs
Works perfect for me.
Similarly, with
ghci -package-db=.cabal-sandbox/.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d
I am also able to import my cabal-sandbox-installed Wai package in ghci with no issue at all.
But when I ask ghc-mod to validate my haskell source code, via
ghc-mod check --boundary="" -g -package-db=.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d hellowai.hs
hellowai.hs:4:8:Could not find module ‘Network.Wai.Handler.Warp’Use -v to see a list of the files searched for.
hellowai.hs:3:8:Could not find module ‘Network.HTTP.Types’Perhaps you meant Network.HTTP.Base (from HTTP-4000.2.19) Network.HTTP.Base (needs flag -package HTTP-4000.2.10) Network.HTTP.Headers (needs flag -package HTTP-4000.2.10)Use -v to see a list of the files searched for.
hellowai.hs:2:8:Could not find module ‘Network.Wai’Perhaps you meant Network.BSD (needs flag -package network-2.4.2.3) Network.URI (needs flag -package network-2.4.2.3) Network.TCP (needs flag -package HTTP-4000.2.10)Use -v to see a list of the files searched for.
It is unable to find my cabal sandbox installed module. Why is that so?

Do you have a cabal.sandbox.config file? And are you using a .cabal file for your project?
If you have both of these you should be able to use ghc-mod check ... and it will just work.
Another advantage of using a .cabal file is that you can use cabal repl to invoke ghci and cabal run to invoke runhaskell with the correct command line options.
Update
Here is a recipe you can try out to see when ghc-mod can find your cabal sandbox. Perhaps this can help you determine what's different with your set up.
Start in a clean directory:
$ mkdir foo
$ cd foo
$ cabal sandbox init
$ cabal get split
$ cd split-0.2.2
$ cabal sandbox init --sandbox=../.cabal-sandbox
Edit around line 55 of split.cabal to add heredoc as a dependency.
Edit src/Data/List/Split.hs to use the module Text.Heredoc:
{-# LANGUAGE QuasiQuotes #-}
...
import Text.Heredoc
...
foo :: String
foo = [here|this is a test|]
Make sure heredoc is installed:
$ cabal install --only-dependencies
Finally this should work:
$ ghc-mod check ./src/Data/List/Split.hs
And it will still work if you cd into a sub-directory:
$ cd src
$ ghc-mod check ./Data/List/Split.hs
However, ghc-mod won't work if you move away split.cabal:
(back at the top level directory)
$ mv split.cabal split.cabal-old
$ ghc-mod check ./src/Data/List/Split.hs
In this case I created the sandbox in a parent directory of our working directory, but things should also work if the initial sandbox was created like this:
$ mkdir foo
$ cd foo
$ mkdir sandbox-dir
$ cd sandbox-dir
$ cabal sandbox init
$ cd ..
$ cabal get split
$ cd split-0.2.2
$ cabal sandbox init --sandbox=../sandbox-dir/.cabal-sandbox

Related

Why can't the ghc (Haskell) compiler find the module Data.Vector which I have imported? I get the error: Could not find module 'Data.Vector'

vector module has been installed by "cabal install vector"
bash-3.2$ ghc-pkg list -f $HOME/.cabal/store/ghc-9.2.1/package.db
/Users/gcolpitts/.cabal/store/ghc-9.2.1/package.db
primitive-0.7.3.0
vector-0.12.3.1
but the compiler can't find it:
$ ghc prob214ff.hs
[1 of 1] Compiling Main ( prob214ff.hs, prob214ff.o )
prob214ff.hs:14:1: error:
Could not find module ‘Data.Vector’
Perhaps you meant Data.Functor (from base-4.16.0.0)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
14 | import Data.Vector
Thx #n. 1.8e9-where's-my-share !
ghc -package-db $HOME/.cabal/store/ghc-9.2.1/package.db prob214ff.hs
solves my problem although it is a regression from previous versions of ghc which didn't require the use of the -package-db option.
I'd love to use GHC_PACKAGE_PATH but I can't see how to make that work. Sec 5.9.5 of the ghc users guide is confusing. It states "A package database is where the details about installed packages are stored. It is a directory, usually called package.conf.d." i.e. not the package.db file that I gave with -package-db on the command line. But where is the package.conf.db directory with info on the vector package that I installed with cabal?
"ghc-pkg list" references /usr/local/lib/ghc-9.2.1/lib/package.conf.d but the output of the command doesn't list the vector package I installed.
"ghc-pkg list -f $HOME/.cabal/store/ghc-9.2.1/package.db" does list the vector package in it's output but doesn't tell me a package.conf.d directory that knows about the vector package.
This is a bit fiddly with cabal version 2. Installing packages no longer really makes sense (despite the cabal install still existing...). Instead you will probably find it easiest to create a cabal package instead, for example:
$ mkdir my-package
$ cd my-package
$ cabal init
<Edit my-package.cabal and add vector to the build-depends line>
<Put the contents of prob214ff.hs in app/Main.hs instead>
$ cabal run
This will be fixed in 9.2.2, see https://gitlab.haskell.org/ghc/ghc/-/issues/20660#note_391573

Haskell - could not find module 'Test.QuickCheck'

I'm getting an error that says the module doesn't exist when I try to runhaskell. It's odd because I try to install it first and says its up to date. Any idea how to fix this?
You could try creating the package environment in the local directory that holds your project, like this:
c:\Users\...\ex1haskell> cabal install --lib --package-env . QuickCheck
This should create a file of the form .ghc.environment.xxx in ex1haskell, which hopefully should be picked up by runhaskell/ghci/ghc invocations.
In ghci sessions, a sign that the environment is being picked up is the following message while starting:
Loaded package environment from ...
When the --package-env location is not given explicitly, a default location is used. According to the docs:
By default, it is writing to the global environment in
~/.ghc/$ARCH-$OS-$GHCVER/environments/default. v2-install provides the
--package-env flag to control which of these environments is modified.
But it seems that runhaskell is having problems to find the environment file in that default location.
Note. When creating a package environment, it's possible to specify multiple packages simultaneously, like this:
cabal install --lib --package-env . QuickCheck random aeson transformers
Also, package environments are just text files, so local environments can be deleted and recreated at will. The actual package binaries reside elsewhere and can potentially be reused by cabal.
A Common Environment
It is hard to debug if/when the actual tooling differs so let's first get a unified setup. I'll use docker to get GHC 8 and Cabal 3.x:
docker run --rm -it haskell bash
Understand that this isn't arbitrary or even preemptive. What you have shown - cabal install --lib ... and runhaskell ... does work for sane tool installations. You might have a bad installation or an old version of a tool that has different behavior.
Running a single file with runhaskell
Now we need a project:
root#8a934c302dba:/# mkdir Ex1
root#8a934c302dba:/# cd Ex1
root#8a934c302dba:/Ex1# cat <<EOF >Main.hs
> import Test.QuickCheck
>
> main :: IO ()
> main = print =<< (generate arbitrary :: IO Int)
> EOF
And test failure:
root#8a934c302dba:/Ex1# runhaskell Main.hs
Main.hs:1:1: error:
Could not find module `Test.QuickCheck'
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
1 | import Test.QuickCheck
And install the library:
root#8a934c302dba:/Ex1# cabal update && cabal install --lib QuickCheck
And successful run:
root#8a934c302dba:/Ex1# runhaskell Main.hs
15
So my comment above was wrong - we don't need to explicitly list the package as it is already exposed after installation.

How to work together with cabal-3 and ghc (ghc-pkg, too)?

With the release of cabal-3, the packages from Hackage are installed in a new location that the compiler ghc and ghc-pkg know nothing about.
In other words, packages are installed but not registered for ghc. Ghci, ghc, ghc-pkg cannot work.
For example,
cabal install safe --lib
Create file t1.hs
import Safe
t1 = tailMay [1,2,3]
Let's try:
> ghci t1.hs
GHCi, version 8.10.2: https://www.haskell.org/ghc/:? for help
[1 of 1] Compiling Main (t1.hs, interpreted)
t1.hs: 1: 1: error:
Could not find module `Safe '
Use -v (or `: set -v` in ghci) to see a list of the files searched for.
|
1 | import Safe
| ^^^^^^^^^^^
Failed, no modules loaded.
This bug is described here
https://github.com/haskell/cabal/issues/6262
and here
https://gitlab.haskell.org/ghc/ghc/-/issues/17341
I use as a temporary solution setting a system variable
GHC_PACKAGE_PATH=C:\Users\me\AppData\Roaming\cabal\store\ghc-8.10.2\package.db;
(Windwos 10, haskell-dev by chocolatey)
via
On Windows, packages installed with cabal seem to be unavailable in ghc/ghci
but with updates I will have to manually change this system variable.
Are there any more elegant solutions to this problem?
P.S. Unfortunately, this solution (via GHC's environment variable GHC_PACKAGE_PATH) is incompatible with Cabal :(
https://github.com/haskell/cabal/issues/1944
One way to achieve this is to use the --env flag to make the libraries available to GHC whenever you are in the current directory:
~ $ mkdir /tmp/foo
~ $ cd /tmp/foo
/tmp/foo $ cabal install safe --lib --env .
Resolving dependencies...
Build profile: -w ghc-8.8.3 -O1
In order, the following will be built (use -v for more details):
- safe-0.3.19 (lib) (requires build)
Configuring library for safe-0.3.19..
Preprocessing library for safe-0.3.19..
Building library for safe-0.3.19..
…
> Installing library in /home/jojo/.cabal/store/ghc-8.8.3/incoming/new-4056/home/jojo/.cabal/store/ghc-8.8.3/safe-0.3.19-92fbaef88124b4508ce447f6245bc793f7a1748247ae68d10e449150df1069af/lib
t1.hs
/tmp/foo $ cat > t1.hs
import Safe
t1 = tailMay [1,2,3]
/tmp/foo $ ls -a
. .. .ghc.environment.x86_64-linux-8.8.3 t1.hs
/tmp/foo $ ghci t1.hs
GHCi, version 8.8.3: https://www.haskell.org/ghc/ :? for help
Loaded package environment from /tmp/foo/.ghc.environment.x86_64-linux-8.8.3
[1 of 1] Compiling Main ( t1.hs, interpreted )
Ok, one module loaded.
*Main>
Note that you probably shouldn’t do this in a directory where you actually have a foo.cabal file. See the documentation of cabal v2-install for details.
Working with GHC_ENVIRONMENT is better:
setx GHC_ENVIRONMENT C:\Users\me\.ghc\x86_64-mingw32-8.10.2\environments\default
it helps for ghc and ghci.
After, in C:\Users\me\AppData\Roaming\cabal\config we should add
package-db: C:\Users\me\AppData\Roaming\cabal\store\ghc-8.10.2\package.db
it helps for cabal.
Unfortunately, ghc-pkg still has problem and works with such flag:
ghc-pkg list --user-package-db="C:\Users\me\AppData\Roaming\cabal\store\ghc-8.10.2\package.db"
For Linux the steps are similar.

Cabal install current package into its own .cabal-sandbox/*-packages.conf.d

I have a package named commands. I want to install it into its own sandbox e.g. .cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d/commands-0.0.0-f3f84f48f42ac74a69ee5fd73512bfd0.conf. currently, there is just one .hi interface file for one module Commands, I don't know how it got there.
I tried cabal install commands, by the logic of "that's how the other packages got there I think", but it fails with unknown package.
I also tried stuff with ghc-pkg like ghc-pkg update commands -f .cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d but I'm not using them right. ideally, I'd like to do this with cabal.
the last thing I tried was ghc -idist/build/, but it complained about the package names in the interface files being different, command versus main ("... differs from name found in the interface file ..."). and if I faked the executable's package with ghc -package-name commands-0.0.0, the linker complained that it couldn't find the symbol _ZCMain_main_closure, because every executable needs the function main in the module Main in the package main.
I'm sure there's a better way of doing this.
I followed online examples for my cabal file:
$ cat commands.cabal
name: commands
library
exposed-modules: Commands.Types, Commands.Bits
...
the minimal failing code example is just:
$ cat Main.hs
import Commands.Types
main = return ()
in the root project directory.
Context: I need to build my executable with make (not cabal) because it links to foreign code (Objective-C via language-c-inline). my makefile: https://github.com/sboosali/Haskell-DragonNaturallySpeaking/blob/master/Makefile). thus, I have to compile a script explicitly. I don't know how to compile the executable with cabal, but I want cabal to build and test and manage my library.
By putting my package into the sandbox, I will be able to import its modules from the script, by compiling with cabal exec -- ghc. I will also be able to include the script with extra-source-files at least, and know it will work.
Here's what I'd try:
First unregister any previous commands library. Try
ghc-pkg --global unregister commands
Install new commands to your sandbox.
From your sandbox directory, try this:
cabal --enable-shared --disable-documentation --prefix=./ install /path/to/your/library/source
Note the prefix specification.
I nuked it (rm -fr .cabal-sandbox/), reinstalled everything (cabal install --only-dependencies), added itself as a source (cabal sandbox add-source .), installed it (cabal install command). and then make worked. idk...

cabal-dev install Happstack-server how

here is what I did:
makdir happstack_01
cabal-dev install happstack-server
write the typical helloworld.hs with "import Happstack.Server (nullConf, simpleHTTP, toResponse, ok)"
ghc -threaded HelloWorld.hs -o helloworld
and I got:
Could not find module `Happstack.Server'
This is so obvious wrong. But what I am more surprised is that no tutorial on google for simple thing as this.
Any intuition would be awesome!
This is a set of instructions for a very bare-bones, Cabalized, and sandboxed build.
$ mkdir happstack01 && cd happstack01/
$ cabal init .
$ <CR><CR><CR><CR><CR><CR><CR><CR><CR> 1 <CR><CR><CR>
$ mkdir src
$ touch src/Main.hs
$ vi happstack-01.cabal
In happstack01.cabal
...
library
exposed-modules:
Main
build-depends: base >=4.6 && <4.7
, happstack-server
hs-source-dirs: src
default-language: Haskell2010
Then
$ cabal sandbox init
$ cabal install --only-dependencies
$ vi src/Main.hs
In src/Main.hs
import Happstack.Server
main :: IO ()
main = simpleHTTP nullConf $ return "Hello sandbox!"
Get some coffee while the sandbox builds.
$ cabal repl
> main
After this I usually add an executable entry to the Cabal file and begin to build the server from that.
Since you wanted a small tutorial, I am writing up how I just got it to work. I used cabal instead of cabal-dev though (if you care, let me know and I can play around a bit more)....
> cabal install happstack-server
> mkdir sample
> cd sample
Then I created the file sample.hs
import Happstack.Server
main = simpleHTTP nullConf $ return "hello, world!"
and I compiled it
> ghc sample.hs
(This is where you seem to be having problems finding the library.... You might want to check if ~/.ghc//package.conf.d/happstack-server-7.3.1-.conf and ~/.cabal/packages/hackage.haskell.org/happstack-server/ exist to verify the download)
Then run the server
./sample
and verify that it works using curl
> curl http://127.0.0.1:8000
This should respond with
hello, world!
ok I figured this out. GHC will not regonized local sanboxed libs. at least my GHC --version 7.6.3 does not. So I will have to cabalise my project in order to make sandboxed libs work.

Resources