haskellcabal-sandbox

How can I use GHC with a cabal sandbox that's not in the current working directory?


If I create a cabal sandbox with cabal sandbox init, I can use cabal repl or cabal exec ghc(i) to work with those packages without creating a project:

$ mkdir /tmp/example && cd /tmp/example
$ cabal sandbox init
$ cabal install QuickCheck
$ cabal exec ghci
Prelude> :m Test.QuickCheck
Prelude Test.QuickCheck>

However, if I change the path to something else, even to a subdirectory, I cannot access the packages anymore:

$ mkdir -p /tmp/example/sub && cd /tmp/example/sub
$ cabal exec ghci
Prelude> :m Test.QuickCheck
<no location info>:
    Could not find module ‘Test.QuickCheck’
    It is not a module in the current program, or in any known package.

Is there any way to use the contents from the sandbox, without copying its content?


Solution

  • The problem is that cabal will only respect sandboxes in the current working directory. However, there are several options where you can specify a sandbox location for cabal or the package databse for GHC.

    Using cabal features

    You can use cabal's --sandbox-config-file option to specify a sandbox configuration, e.g.

    $ cabal --sandbox-config-file=/tmp/example/cabal.sandbox.config exec ghci
    Prelude> :m Test.QuickCheck
    Prelude Test.QuickCheck>   
    

    This also enables you to change the sandbox from other places, which comes in handy if you just want to install random stuff into a temporary place:

    $ cabal --sandbox-config-file=/tmp/example/cabal.sandbox.config install lens
    $ cabal --sandbox-config-file=/tmp/example/cabal.sandbox.config repl
    Prelude> :m Control.Lens
    Prelude Control.Lens> :m Test.QuickCheck
    Prelude Control.Lens Test.QuickCheck>
    

    Since this gets cumbersome after a while, you should probably add an alias

    $ alias sandboxed-cabal="cabal --sandbox-config-file=/tmp/example/cabal.sandbox.config"
    $ sandboxed-cabal repl
    Prelude>
    

    Using ghc -package-db

    Alternatively, you can directly specify the package database when you use GHC with -package-db:

    $ ghci -package-db /tmp/example/.cabal-sandbox/<ARCH>-packages.conf.d
    Prelude> :m Test.QuickCheck
    Prelude Test.QuickCheck>
    

    The <ARCH> depends on your system and the used GHC, e.g. on a 64bit Linux and GHC 7.10.3 it's x86_64-linux-ghc-7.10.3-packages.conf.d. You can then use all packages in that database:

    $ ghci -package-db /tmp/example/.cabal-sandbox/<ARCH>-packages.conf.d
    Prelude> :m Control.Lens
    Prelude Control.Lens> 
    

    Again, an alias should come in handy.

    Using GHC_PACKAGE_PATH

    Last, but not least, you can adjust an environment variable. However, if the environment variable GHC_PACKAGE_PATH exists, it will overwrite GHC's usual package databases, so you either need to check ghc-pkg list and add them too

    $ GHC_PACKAGE_PATH=/opt/ghc/7.10.3/lib/ghc-7.10.3/package.conf.d/:/tmp/example/.cabal-sandbox/x86_64-linux-ghc-7.10.3-packages.conf.d ghci
    

    or use -global-package-db and -user-package-db to reenable them:

    $ GHC_PACKAGE_PATH=/tmp/example/.cabal-sandbox/x86_64-linux-ghc-7.10.3-packages.conf.d ghci -global-package-db -user-package-db