GHC options in cabal sandboxes - haskell

I'm doing cabal builds in various sandboxes with different combinations of GHC options. The flags I'm interested in are -O2, -O0, -threaded, and -feager-blackholing.
Firstly, for which of these flags does it make sense to apply to all packages in the sandbox, and which should only apply to the final executable package? For example, I believe -threaded only affects linking.
Secondly, how do I tell cabal to apply a flag to all packages? I tried creating a ghc-options: line in the sandbox cabal.config, but it complained. I tried creating a program-default-options stanza in cabal.config (like the one in ~/.cabal/config), but it complained about that too.

Related

How can I run GHCi against a compiled package?

I should really know this by now, but I don't. I'm often working on a Cabal-based package and have just run a successful cabal build. Now I want to try some things out in GHCi. If I run cabal repl, then GHC recompiles the whole package into bytecode and runs it in the interpreter. Not what I want at all! If I were just running GHCi directly, I'd use something like -O -fobject-code, but that won't give me the package context. I just want "Give me a repl with the package as it's been compiled, compiling additional things only as necessary." How do I do it?
I don't know the right way, but I do know a workaround that can sometimes be useful. If the thing you care about is a library component, you can ask for a repl for an executable component.
I believe --repl-options -fobject-code kind of does what you want:
cabal repl --repl-options -fobject-code --repl-options -O --builddir dist-repl
This will give you incremental building of compiled code as you work in GHCi. Caveats:
dist-repl is an alternative directory for the -fobject-code build objects. As of cabal 3.6.2.0 at least, trying to reuse the regular output from cabal build leads to some unnecessary rebuilds and other strange behaviour, as reported at cabal issue #3565. That being so, it's better to compromise and use --builddir to keep a separate set of build objects. Note that cabal clean accepts the --builddir option just fine.
Setting the optimisation level explicitly is necessary, as otherwise the default -O0 from cabal repl will override your package setting.

Cabal install tidal ends with warning

I'm trying install tidal in command line this way:
cabal install tidal
but it ends with this message:
Warning: You asked to install executables, but there are no executables in
target: tidal. Perhaps you want to use --lib to install libraries instead.
Return of:
cabal install tidal --lib
is:
Resolving dependencies...
Up to date
If I check ghk-pkg list, there is no package tidal
...
Have somebody similar problem or what I'm doing wrong?
My environment is:
Windows 10 Education
Haskell 8.4.3
Cabal 3.2.0.0
Ghc 8.10.1
Thank you for help.
Like Stack for a longer time, Cabal-install does now (as of 3.2) not really install libraries anymore – in the sense of, change the computer's state so that GHC can access the library on it†. Both tools only install executables now. It used to do that for libraries too, but that was stopped with the now default Nix-style builds.
Now (and, really, also already before), the way to use a library is instead to just depend on it, and let Cabal figure out behind the scenes if it needs to be installed. I.e., you add a .cabal file to your .hs source file with build-depends: tidal in it. Then when you say cabal install ., it will first download and install the library before then using it for building your own executable.
†Of course both Stack and Cabal do technically speaking install libraries, just they don't globally register them. I.e., cabal knows where it has installed the library, but you're not really supposed to know about that. It's in the spirit of continuous integration: if your code builds now with the particular state of libraries you happen to have installed, that's not very reliable. If it builds with just those libraries that are explicitly listed in a project file, the chances are much better that future-you (or somebody else) will still be able to use your code on another computer without hours of figuring out what libraries to install first.
cabal install --lib tidal doesn't install the library binaries in a location managed by ghc-pkg. The binaries remain in the Cabal "store".
What it does is to create a plaintext GHC package environment file that is picked up by standalone invocations of ghc and ghci and tells them where to look for the extra libraries.
By default (as mentioned in the docs) this package environment file will be created at ~/.ghc/$ARCH-$OS-$GHCVER/environments/default and will be picked by ghc and ghci invocations made anywhere.
We can also supply an extra --package-env parameter to create the environment file in a local folder, which will only affect ghc and ghci invocations made in that folder. For example:
cabal install --lib --package-env . tidal
cabal projects themselves ignore environment files, as their package environments are constructed from the build-depends section of the cabal file for the sake of reproducibility. But environment files are useful for not having to create a cabal project in the first place, if you only need it for playing with the library in ghci, or if you are compiling simple programs using ghc only.

Global configuration for GHC build flags

Is there a place I can configure some default flags for GHC to use? I'd like, i.e., GHC to always assume I want the -fwarn-incomplete-patterns flag. This page gives a list of useful flags and indicates that some of them are on by default, but again, I'd like to change the defaults for my system.
I'm currently working on OS X, but I use Debian, Arch Linux, and Windows 8.1 at home, so a solution for any platform will help.
Apart from aliasing the shell command ghc to ghc -fwarn-incomplete-patterns, I don't think there's a way to do it globally or whether it would be advisable to do globally since it would probably generate an enormous amount of warnings when compiling external libraries with cabal. Probably best to do this one project at a time or just with GHCi:
There's a ghc-options section in any cabal file for a project.
library
...
ghc-options:
-fwarn-tabs
-fwarn-missing-local-sigs
-fwarn-incomplete-patterns
-fwarn-incomplete-uni-patterns
For global GHCi, you can add the following line to your ~/.ghc/ghci.conf
:set -fwarn-incomplete-uni-patterns
Add ghc-options: -fwarn-incomplete-patterns to the program-default-options section of your ~/.cabal/config:
[...]
program-default-options
...
ghc-options: -fwarn-incomplete-patterns
...
This only works with Cabalised projects (i.e. when you use cabal build/install/[...] instead of running ghc --make SomeFile.hs manually) and requires a fairly recent cabal-install (>= 1.18).
Just because this will be useful for people who come here:
On Gentoo, you can set options for all Cabal packages, (which is pretty much all of them) globally, in /etc/portage/make.conf, with the variable CABAL_EXTRA_BUILD_FLAGS. So in your case, that would be
CABAL_EXTRA_BUILD_FLAGS="--ghc-option=-fwarn-incomplete-patterns"
, and here is a more advanced example
CABAL_EXTRA_BUILD_FLAGS="--ghc-option=+RTS --ghc-option=-M1G --ghc-option=-RTS"
to limit memory usage to 1GB (and exit otherwise).
I think there’s a similar solution for Arch and Debian, but since OS X is a consumer OS, I don’t know.

How can I specify which LLVM binaries GHC should use?

I have successfully built PortFusion with the brand new 64-bit GHC 7.6.1 Release Candidate 1 for Windows.
Using freshly downloaded native 64-bit mingw binaries from http://www.drangon.org/mingw, the network package was as easy to install (after a bunch of non-relevant small fixes) as a simple
CC=mingw64/bin/gcc cabal install
There is also an LLVM toolchain package on the same website.
Now I wonder how I could tell GHC to use specific LLVM binaries during compilation.
Would it be something as simple and similar to above as:
#v??v
LLVM=????????? ghc -W -O2 -fllvm -optlo-O3 --make src/Main.hs
LLVM=????????? cabal install PortFusion -f llvm #¹
#^??^
¹ relevant line in PortFusion.cabal defining the llvm flag
or completely different?
For the record, the answer to the question in the title is
ghc -pgmlo opt_cmd -pgmlc llc_cmd -fllvm ...
opt_cmd and llc_cmd can be either command names (that will be looked up in PATH) or full pathnames.
You may be able to get GHC to use certain binaries by altering where they are defined in the PATH environment variable. Earlier takes precedence. Presumably, System PATH is also higher precedence than User PATH.

How can configuration tools like sdl-config be used with a cabalized project?

I have a working SDL/Haskell application that I would like to build using Cabal instead of the current Makefile (because that is the "Haskell way"). The Makefile is itself very simple, and I was hoping that the default cabal build process could allow me to reconstruct a build command specified in my Makefile. The problem is that it makes use of "sdl-config", a utility that gives you all the necessary cc- compiler options:
wrapper.o: SDLWrapper_stub.h
ghc -no-hs-main `sdl-config --cflags` -Wall wrapper.c -c
Cabal does not seem to expand that into a shell call when calling GHC. How can I specify that sdl-config's options should be fed into GHC when compiling wrapper.o?
Using the configure style in Cabal, you can write a little configure script that substitutes a variable for the output of the sdl-config command. The values will then be replaced in a $foo.buildinfo.in file, yielding a $foo.buildinfo file, that Cabal will include in the build process.
General solution: the configure script
#!/bin/sh
SDLFLAGS=`sdl-config --cflags`
echo Found "$SDLFLAGS"
sed 's,#SDLFLAGS#,'"$SDLFLAGS"',' z.buildinfo.in > z.buildinfo
The $foo.builinfo.in file
cc-options: #SDLFLAGS#
The .cabal file
Build-type: Configure
When you run "cabal configure" the "cc-options" field in z.buildinfo will be created to hold:
cc-options: -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
which cabal will include in the build.
Done.
Specific solution for pkg-config tools
For tools that support the pkg-config-style of configuration, such as sdl or cairo and others, Cabal has specific support already:
pkgconfig-depends: package list
A list of pkg-config packages, needed to build this package. They can be annotated with versions, e.g. gtk+-2.0 >= 2.10, cairo >= 1.0. If no version constraint is specified, any version is assumed to be acceptable. Cabal uses pkg-config to find if the packages are available on the system and to find the extra compilation and linker options needed to use the packages.
If you need to bind to a C library that supports pkg-config (use pkg-config --list-all to find out if it is supported) then it is much preferable to use this field rather than hard code options into the other fields.
So for sdl you just need:
pkgconfig-depends: sdl
Use the Configure build type in your $PROJ_NAME.cabal file and generate a $PROJ_NAME.buidinfo file from a $PROJ_NAME.buildinfo.in template with a configure script. Look at the source of the SDL library on Hackage for an example. This section of the Cabal user guide provides more details.
One tip: do not forget to mention $PROJ_NAME.buildinfo.in and configure in the extra-source-files field.

Resources