How to make GHC generate dynamically linked binaries by default? - haskell

Is it possible to change cabal or GHC settings so that cabal install generates dynamic binaries and libraries by default?
I'm using GHC 8.2.2, installed using apt-get in Ubuntu (16.04) without Haskell Platform or stack. Searching around, I found the SO question Why can't cabal build mighttpd2 dynamically? . The answers/comments there said something about adding --enable-shared --enable-executable-dynamic when cabal install. And this can be done manually for all dependency libraries (which would be a pain).
In Small Haskell program compiled with GHC into huge binary, the accepted answer says that one needs to:
cabal install some_package --enable-shared --reinstall
The option -dynamic is also mentioned.
My question is:
Is it possible to change the options in the cabal configuration file (~/.cabal/config) from the very beginning so that all binaries and their dependency libraries use dynamic linkage (i.e. with --enable-shared --enable-executable-dynamic or -dynamic by default)?

Indeed, you can alter your ~/.cabal/config file to have the following lines:
shared: True
executable-dynamic: True

Related

Compiling haskell source as dynamic library

I'm trying to compile a Haskell source package as a dynamic library to be used with OCaml code. I tried using the --enable-shared option with cabal install on the .cabal file of the source, I got a Perhaps you haven't installed the "dyn" libraries for package 'zeromq4-haskell-0.6.5' error. After a little googling, I realised that the dependencies must also be compiled as dynamic libraries. I downloaded the source package for zeromq and tried installing the zeromq package with the --enable-shared option. This time I got a similar error with one of zeromq's dependencies. I tried doing this 4-5 times and get an error with a different dependency at each level.
Am I making a mistake here? How can I get all of the dependencies to install as dynamic libraries?
Thanks!
If you generally want to have shared libraries, you can permanently enable it in your .cabal/config:
shared: True
However, it will only affect libraries installed after that, so you may want to purge all libraries and start over again.
If this is just a one-shot, you may create a cabal sandbox just for that purpose:
cd yourlib
cabal sandbox init
cabal install --enable-shared
The result will be in the directory .cabal-sandbox.

Cabal can't find foreign libraries

Recently I was trying to install llvm-general-3.5.1.0 package.. for about a week. Basically I am getting this error: link. My situation is identical. Windows 10, ghc 7.10.2, cabal 1.22.4.0. I installed llvm 3.5.2 from sources with cmake and everything went fine. In llvm/lib directory I have *.lib files (eg. LLVMAnalysis.lib).
But somehow cabal can't see those libraries and gives this frustrating error:
Configuring llvm-general-3.5.1.0...
setup.exe: Missing dependencies on foreign libraries:
* Missing C libraries: LLVMLTO, LLVMObjCARCOpts, LLVMLinker, LLVMipo,
LLVMVectorize, LLVMBitWriter, LLVMCppBackendCodeGen, LLVMCppBackendInfo,
LLVMTableGen, LLVMDebugInfo, LLVMOption, LLVMX86Disassembler,
LLVMX86AsmParser, LLVMX86CodeGen, LLVMSelectionDAG, LLVMAsmPrinter,
LLVMX86Desc, LLVMX86Info, LLVMX86AsmPrinter, LLVMX86Utils, LLVMJIT,
LLVMIRReader, LLVMAsmParser, LLVMLineEditor, LLVMMCAnalysis,
LLVMMCDisassembler, LLVMInstrumentation, LLVMInterpreter, LLVMCodeGen,
LLVMScalarOpts, LLVMInstCombine, LLVMTransformUtils, LLVMipa, LLVMAnalysis,
LLVMProfileData, LLVMMCJIT, LLVMTarget, LLVMRuntimeDyld, LLVMObject,
LLVMMCParser, LLVMBitReader, LLVMExecutionEngine, LLVMMC, LLVMCore,
LLVMSupport
This problem can usually be solved by installing the system packages that
provide these libraries (you may need the "-dev" versions). If the libraries
are already installed but in a non-standard location then you can use the
flags --extra-include-dirs= and --extra-lib-dirs= to specify where they are.
I really want to use this package on my Windows, but nothing seems to work (I tried everything like --extra-lib-dirs and compiled also with MinGW and VS - the same problem).
I can't accept the fact that it won't install. I mean, there must be some way to fix Setup.hs from this cabal package or something. Does anyone have an idea what can be wrong with cabal in this case and how can I try to workaround this? I don't know how exactly cabal works, maybe someone with this knowledge will have an idea? Or maybe there is a way to do this without cabal?
Ok, i've managed to build it and, i think, found the root of the issue.
First, steps to build:
Get the MinGW. My installation of MinGW has gcc 4.8.
Get 32-bit MinGHC.
Compile LLVM 3.5 with MinGW's gcc and install it somewhere.
Copy contents of MinGW installation directory into MinGHC Install
Dir\ghc-7.10.2\mingw, replacing conflict files.
In the command line set your PATH so it has haskell toolset from
MinGHC (i recommend using switch .bat scripts) and llvm-config.exe.
Get the llvm-general package source either using cabal fetch or
downloading via browser from hackage.
Replace cc-options: -std=c++11 line of llvm-general.cabal with
cc-options: -std=gnu++11.
Finally, cabal configure and cabal build should work.
I have been changing my build environment many times, so if this doesn't work for you let me know, i probably forgot something.
Now let's go into details.
What we thought is a bug of cabal is not, actually. The problem is that both stack and MinGHC (and Haskell Platform, i guess) use quite old gcc - 4.6. This gcc has even two defects:
It doesn't support -std=c++11 and LLVM 3.5 can't be built using it.
As a consequence, this gcc can't be used by ghc when compiling
llvm-general, because it can't parse LLVM headers properly.
Even if it could, its linker can't link against LLVM libs compiled by
MinGW using gcc 4.8. This is why cabal was telling you it
couldn't find LLVM libs. I've hacked Setup.hs so that it wouldn't
look for these libs, but pass -lLLVMSomething to linker via -pgml
ghc option. This lead to clear error message:
ld.exe: ignoring libLLVMSupport.a ...
ld.exe: can't find -lLLVMSupport
So, the cabal was actually finding these libs, but was dropping them because they couldn't be linked to.
Ideally, the solution would be to update mingw distribution used by stack/MinGHC. But as a workaround you can just replace old gcc with new one.
Finally, -std=gnu++11 is used because current MinGW release is affected by this bug, which prevents compilation of c++ bits of the package. Whew, that was a long way.

What does "shared" mean in ~/.cabal/config?

I guess that "shared" will make cabal install faster, right ? The default value of shared is False. Should we use True or False for shared ?
thanks!
It means "also build dynamically-linked (aka shared) versions of libraries that are installed with cabal install".
$ cabal help install | grep shared
--enable-shared Enable Shared library
--disable-shared Disable Shared library
By default, only statically-linked versions are built. So it won't make cabal install libfoo faster - on the contrary, building libfoo will take more time.

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