Generate cabal file with dependencies on foreign libs - haskell

Is it possible to automatically generate cabal file for a given haskell project, that will create appropriate Build-depends dependencies for all the libs that the project uses?

Yes! In fact, the 'cabal init' command does this in the HEAD version of cabal-install. It's true that it's not possible to get it exactly right in all cases, but it just makes the best guesses it can and then lets you fix the generated build-depends list as necessary.

No, because some modules are provided by more than one package and it isn't practical (or even possible, really) for cabal to decide which one you want to use.
You can search for which package is provided by which module, or just run cabal-install several times until you've covered all the deps.

Related

How does the workflow with Haskell Stack work?

I don't get the point about Stack.
I used to write my Haskell code in my favourite environment, ran or compiled using GHC(i), and if necessary, installed packages using Cabal. Now, that apparently is not the way to go any more, but I don't understand how to work with Stack. So far, I have only understood that I need to write stack exec ghci instead ghci to start a repl.
Apart from that, the docs always talk about 'projects' for which I have to write some yaml files. But I probably don't have any project -- I just want to launch a GHCi repl and experiment a bit with my ideas. At the moment, this fails with the unability to get the packages that I want to work with installed.
How is working with Stack meant? Is there any explanation of their use cases? Where do I find my use case in there?
Edit. My confusion comes from the fact that I want to work with some software (IHaskell) whose installation guide explains the installation via stack. Assuming I already have a GHCi installed whose package base I maintain e.g. using Cabal. How would I have to set up stack.yaml to make stack use my global GHCi for that project?
First, notice that stack will use its own package base independent from cabal. AFAIK they can't be shared... hence, if you run stack build it'll download packages (including the compiler) on its own package database.
Nevertheless stack allows to use a system compiler (but not other libraries). To do so, in the stack.yaml you must have the following two lines
resolver: lts-XX.XX -- keep reading below
system-ghc: True
The version of the stackage snapshot can be found in: https://www.stackage.org/. Each snapshot works with a different version of the compiler. Be sure to use a snapshot with the same compiler version you have in you system. If it happens your system ghc is greater than any lts, then you can set allow-newer: true in stack.yaml.
Now, if getting a different database from stack feels wrong to you, notice that you can build the project with cabal too, since stack at the end of the day spits out a cabal file. Probably, It wont work out of the box if you build with cabal. You can modify the cabal file to match exactly the version of the packages of the snapshot you are using
In summary:
You can use your system-wide ghc
you can not share libraries installed with cabal.
you can use cabal to build the project, probably modifying the ihaskell.cabal file to match versions of the stackage's snapshot.

Cabal + Stack: specifying the packages version in the cabal file

Normally when adding a new dependency to a .cabal file I specify the version of the new library I'm depending on. However stack works with a curated set of libraries, and I'm wondering whether it makes sense to specify the package versions in the .cabal file. My guess would be that specifying the lts version in the stack.yaml is enough.
I'm wondering whether it makes sense to specify the package versions in the .cabal file.
That depends completely upon you. If you specify a package version
which is not in that particular stackage resolver, then Stack will
throw an error saying you to adjust the versioning.
My guess would be that specifying the lts version in the stack.yaml is enough.
For private packages, it doesn't matter and I prefer not putting any version bounds there. But if it's something I ultimately plan to publish on Hackage, I usually use a CI system like Travis and get the bounds right for it with some testing. In fact, I think the Stack guide recommends something like that.

How to use two different compilers for different targets in a .cabal file?

When I run cabal build it uses some Haskell compiler to build the executables and/or test-suites in my .cabal file.
Can I control which compiler is used for the different targets? Ideally, I would like to have separate build targets that use ghc and ghcjs in the same .cabal file. It seems to me that someone might want to use ghc and hugs or two version of ghc in the same project. Is this currently possible?
Also, how does cabal decide what compiler to use when running cabal build? I saw there is a compiler option in my ~/.cabal/config file but changing it from ghc to ghcjs and uncommenting it, did not seem to change what cabal build does.
The compiler to use is determined during the configure step (or during an install step's implicit configure step, which does not share configuration options with a previous configure step). It is also determined by the entity building the package and cannot be influenced by the person writing the package. Probably what happened to you is that a previous cabal build implicitly invoked the configure step and chose a compiler; future builds will keep a previous choice of compiler over one stuck in your global configuration file. You can countermand that by simply manually running cabal configure again.
It is possible to cause a build to fail with the wrong implementation, e.g.
library
if impl(ghc)
buildable: False
will prevent cabal from trying to build the package using GHC. However, this isn't really useful for building separate parts of a package with separate compilers, as cabal will refuse to install a package unless it can build the whole thing with a single compiler.
Probably the best way forward is to make separate packages for things that should be built by separate compilers.

Building with c2hs and cabal

I have a problem where cabal will not do dependency resolution on .chs files,
that is, if A.chs depends on B.chs (or really B.chi) then cabal will not
figure it out and call c2hs on the files in the correct order. I know that gtk2hs
uses a custom buildscript, however it is rather complicated and specialized for
gtk2hs. Is there an easier way of manually/automatically doing .chs dependency
resolution (by, for instance, listing out the files in the correct order)?
As it turns out, cabal will process exposed-modules by
the order they are listed, I guess only if there are
no dependencies to consider or maybe this behavior is
specific to .chs files. In order to manually resolve dependencies
one can simply order the modules correctly in the cabal file.

Is it possible to install more than one ghc and change each installation's binary name?

Suppose I want to use different versions of GHC, each of them with a different binary name.
Question 1. Can I use ./configure --prefix=ghc-some-version-dir for each of the installations and create symbolic links ghc-7.4.1, ghc-7.6.2, ghc-head without problems?
That is, after the installation and creation of binaries from source code. Using virtual environments would still be needed for building projects and its dependencies.
Question 2. What prevents us from uploading ghc to Hackage with a package name ghc-version having a binary name that depends on its version? e.g. one could cabal install ghc-version-7.6.2 and get a binary ghc-7.6.2 in ~/.cabal/bin
You don't need to do anything special. GHC already installs all of its executables with versioned names and links from the non-versioned name to the most recently installed version, e.g. a link from "ghc" to "ghc-7.6.1" or whatever you installed last. When you build from the repository, the version number is quite long and includes the date you built it.
I don't know for sure why GHC isn't on Hackage, but I presume it's because the build system is very complicated, and that cabal-izing it (and maintaining the cabalization) would be more work than it's worth.
There are several soluttions
Just use chroot
Use a package manager that handles multiple versions of the same library/software such as nix
There are scripts which have been written to handle this such as https://github.com/spl/multi-ghc
Use gnu stow as described in Brent Yorgey blog post.
Ben Millwood has a solution where he just uses the -w flag, read his comment at:https://plus.google.com/u/0/100165496075034135269/posts/VU9FupRvRbU

Resources