How do I configure Cabal to understand a C FFI? - haskell

I am trying to create a Haskell library which uses a C FFI. I have 4 files:
MyLibrary.hs
c_dependency.h
c_dependency.c
c_dependency.o
test.hs
All on the same directory. test.hs loads MyLibrary and tests it:
-- test.hs
import qualified MyLibrary as Lib
main = Lib.test
I want to be able to compile test.hs as usual, without linking to c_dependency.o. That is, I want ghc test.hs; ./test to work. How can I init/configure cabal so it builds my library properly, taking care of linking c_dependency.o ?

A series of blog posts on Cabal, the FFI, and c2hs has what you're looking for in the second article, the "Compiling the library with Cabal" section.

Related

Text/Regex/TDFA/NewDFA/Engine.hs:13:33: parse error on input ‘#’

I have been trying to run a simple Haskell program using TDFA. The program is as follows:
import Control.Monad
import Data.Array
import qualified Data.Text as T
import Text.Regex
import Text.Regex.TDFA
import Text.Regex.Base
str = "abbbbaab" :: String
regex = "(a+)(b+)" :: String
main = do
if str (=~) :: regex then putStrLn "matched" else putStrLn "no matches"
when I try to run the above program using the command like: ghc test.hs -o test and then I am getting the following error (test.hs is the Haskell program which contains the above code):
Text/Regex/TDFA/NewDFA/Engine.hs:13:33: parse error on input ‘#’
Note that I have the latest version of TDFA installed on my pc. I did it by following ways:
ghc --make -o setup Setup.hs
Also, I did the following:
user#user-VirtualBox:~/regex-tdfa-master$ sudo cabal install regex-tdfa
[sudo] password for user:
Resolving dependencies...
All the requested packages are already installed:
regex-tdfa-1.2.2
Use --reinstall if you want to reinstall anyway.
I even tried it with the Makefile which I got from TDFA's github repository:
user#user-VirtualBox:~/regex-tdfa-master$ make
ghc -o setup --make ./Setup.hs
./setup clean
cleaning...
./setup configure --prefix=/Users/user/local/devel/trl --enable-library-profiling --user
Configuring regex-tdfa-1.2.2...
./setup build
Building regex-tdfa-1.2.2...
Preprocessing` library regex-tdfa-1.2.2...
[ 1 of 23] Compiling Text.Regex.TDFA.NewDFA.Uncons ( Text/Regex/TDFA/NewDFA/Uncons.hs, dist/build/Text/Regex/TDFA/NewDFA/Uncons.o )
...........(Skipped to make the things short here)..............................
[23 of 23] Compiling Text.Regex.TDFA ( Text/Regex/TDFA.hs, dist/build/Text/Regex/TDFA.o )
Text/Regex/TDFA.hs:60:8:
Could not find module ‘Text.Regex.Base’
Perhaps you haven't installed the profiling libraries for package ‘regex-base-0.93.2#regex_47KXx9dLqeO8MNJeizLKhP’?
Use -v to see a list of the files searched for.
Text/Regex/TDFA/ByteString.hs:24:8:
Could not find module ‘Text.Regex.Base.Impl’
Perhaps you haven't installed the profiling libraries for package ‘regex-base-0.93.2#regex_47KXx9dLqeO8MNJeizLKhP’?
Use -v to see a list of the files searched for.
Text/Regex/TDFA/CorePattern.hs:37:8:
Could not find module ‘Control.Monad.RWS’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1#mtl_Aue4leSeVkpKLsfHIV51E8’?
Use -v to see a list of the files searched for.
Text/Regex/TDFA/ReadRegex.hs:13:8:
`Could not find module ‘Text.ParserCombinators.Parsec’`
Perhaps you haven't installed the profiling libraries for package ‘parsec-3.1.9#parse_EE5NO1mlYLh4J8mgDEshNv’?
Use -v to see a list of the files searched for.
Text/Regex/TDFA/String.hs:23:8:
Could not find module ‘Text.Regex.Base.RegexLike’`
Perhaps you haven't installed the profiling libraries for package ‘regex-base-0.93.2#regex_47KXx9dLqeO8MNJeizLKhP’?
Use -v to see a list of the files searched for.
Text/Regex/TDFA/TDFA.hs:10:8:`
Could not find module ‘Control.Monad.State’
Perhaps you haven't installed the profiling libraries for package ‘mtl-2.2.1#mtl_Aue4leSeVkpKLsfHIV51E8’?
Use -v to see a list of the files searched for.
Makefile:16: recipe for target 'build' failed
make: *** [build] Error 1
user#user-VirtualBox:~/regex-tdfa-master$
However, nothing worked. Hence, any help would be so appreciated...
Text/Regex/TDFA/NewDFA/Engine.hs:13:33: parse error on input ‘#’
On an initial note, this error points to a module of the regex-tdfa package, so you should have gotten it when building the package, rather than when building your test.hs, unless you were trying to build test.hs after putting it within the package source tree. In any case, line 13 of the mentioned file is:
import GHC.Prim(MutableByteArray#,RealWorld,Int#,sizeofMutableByteArray#,unsafeCoerce#)
The # names require the MagicHash GHC extension to be enabled. As there is no {-# LANGUAGE MagicHash #-} pragma at the beginning of the file, one should assume the extension is enabled through the .cabal file of the package, and that is indeed the case. That being so, your problem seems to be that you are attempting use the package modules straight from the source tree, without using an appropriate build tool such as Cabal. (Note that if you did successfully run cabal install regex-tdfa there should be no need of dealing with the source tree: ghc --make -o test test.hs should be enough.)
P.S.: There is an error in your test.hs. The last line should be...
if str =~ regex then putStrLn "matched" else putStrLn "no matches"
(I did manage to run it after this correction.)
It looks like you are compiling your program from within Regex-TDFA source code. I am able to reproduce your problem if I do cabal unpack regex-tdfa && cd regex-tdfa-1.2.2 && ghc --make test.hs.
The error happens because when GHC finds Regex-TDFA source files in the current directory, it just picks them and tries to compile, as if they were ordinary source files belonging to your project. However, Regex-TDFA cannot be built with simple ghc --make: in order to build it, you have to run cabal first. Cabal will read regex-tdfa.cabal file that contains the list of the necessary GHC extensions.
In particular, parse error happens because GHC extension MagicHash is missing (that's where the hash # comes from).
The "fix" is to move your test.hs to some other location: then GHC will use system package for Regex-TDFA.

How to use Text.Parsec in GHC-8.2.2 and Cabal-2.0.0.1

As I know Text.ParserCombinators.Parsec is replaced by Text.Parsec
Here, it is my environment
4.9.73-1-MANJARO
The Glorious Glasgow Haskell Compilation System, version 8.2.2
cabal-install version 2.0.0.1
compiled using version 2.0.1.0 of the Cabal library
The following source code is my main.hs
module Main where
import System.Environment
import Text.Parsec
main :: IO ()
main = do
args <- getArgs
putStrLn (readExpr (args !! 0))
and then I compile it
$ ghc -package parsec -o main main.hs
It occurs the following error messages
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:3:1: error:
Could not find module ‘Text.Parsec’
There are files missing in the ‘parsec-3.1.11’ package,
try running 'ghc-pkg check'.
Use -v to see a list of the files searched for.
|
3 | import Text.Parsec
| ^^^^^^^^^^^^^^^^^^
rm: cannot remove '*.hi': No such file or directory
./run.sh: line 11: ./TestProj: No such file or directory
I make sure I have installed parsec. So I want to ask any mistake I've done?
$ cabal install parsec
Resolving dependencies...
All the requested packages are already installed:
parsec-3.1.11
Use --reinstall if you want to reinstall anyway.
Manjaro might have inherited from Arch's issues with Haskell.
What is going on
Arch installs dynamic libraries, but ghc links statically by default. This is also what the error message "There are files missing in the ... package", indicating that the package exists but does not contain what ghc is looking for.
If I try compiling with the -v verbose flag on, the error message expands to:
ghc -v main.hs
(...)
Locations searched:
Text/Parsec.hs
Text/Parsec.lhs
Text/Parsec.hsig
Text/Parsec.lhsig
/usr/lib/ghc-8.2.2/site-local/parsec-3.1.11/Text/Parsec.hi
(...)
In particular, look into the last reported location, which may be different on your system; if my guess is correct, ghc is looking for a static interface file .hi as the message indicates but there is only a dynamic one .dyn_hi.
Fix
Compile with the -dynamic flag.
ghc -dynamic main.hs
And if that works read this to fix the setup:
https://wiki.archlinux.org/index.php/Haskell
You will have to choose between static and dynamic linking; I don't actually understand the trade-off here.

plugins package unknown symbol when using cabal

I'm messing around with the plugins package however I bumped into a problem.
Here's the code:
Util/Header.hs
module Util.Header(PT(..)) where
data PT a = PT a deriving Show
Plug.hs
module Plug(helloPlugin) where
import Util.Header
helloPlugin :: PT Int
helloPlugin = PT 1
Main.hs
module Main where
import Util.Header
import System.Plugins
main :: IO ()
main = do
mv <- load "Plug.o" ["."] [] "helloPlugin"
case mv of
LoadFailure msg -> print msg
LoadSuccess _ v -> print $ show (v :: PT Int)
This all works fine then compiling with ghc. Building with Cabal works fine as well, but when I run the executable I get this error:
plugintest: /home/kevin/.cabal/lib/plugins-1.5.4.0/ghc-7.6.3/HSplugins-1.5.4.0.o: unknown symbol `ghczm7zi6zi3_ErrUtils_zdsinsertzuzdsgo5_info'
plugintest: user error (resolvedObjs failed.)
My very minimalistic cabal file:
name: plugintest
version: 0.1.0.0
license-file: LICENSE
build-type: Simple
cabal-version: >=1.8
library
hs-source-dirs: src
exposed-modules: Util.Header
build-depends: base ==4.6.*, plugins ==1.5.*
executable plugintest
main-is: Main.hs
build-depends: base ==4.6.*, plugins ==1.5.*, plugintest == 0.1.0.0
hs-source-dirs: src
Now I assume the problem is that it can't find the "ErrUtils" module which is part of the ghc package installed in /usr/lib/ghc-7.x.x.
Since it's using cabal it'll use the $HOME/.cabal/lib/ instead.
Now I obviously wouldn't want to use /usr/lib if I wanted to make it distributable. Sadly I'm not very familiar with how packages are managed nor am I familiar with the plugins package.
I have a feeling this is extremly nooby but I wasn't able to find a solution myself.
So a few questions:
How can I get my dependencies to work in a way to make this distributable?
It seems I'll need to know beforehand what my Plugin.o files will depend on before actually being able to use them (If I understand correctly).
Is there a way to package a .o files that I wouldn't have to worry about this problem? (Sorry if this question is too vague, feel free to ignore)
Thanks in advance!
Ok, so I had the exact same problem.
Here is a workaround I found
Change the load call to
load "Plug.o" [".","dist/build/plugintest/plugintest-tmp"] [] "testplugin"
Make sure you compile the thing with -c or by using the "make" library from plugins.
Quite annoyed by this... The error suggests it is having issues linking against the standard libs, so why does showing it these .o files fix it?
Anyways, this worked for me, and didn't require a ton of mucking around with .cabal files.
You must declare your exported- and other- modules in order for Cabal to package them all together. For instance (from https://github.com/tel/happstack-heroku-test)
name: hktest -- note the name here names
-- the *library* which is a package name
-- in scope when building the executable
...
library
exposed-modules:
HKTest
other-modules:
-- there aren't any, but there could be some
build-depends: base >= 4.6 && <4.7
...
, mtl >= 2.1.2
hs-source-dirs: src
executable server
main-is: Server.hs
other-modules:
-- there might be some use to having these here,
-- but they'll be harder to get into GHCi, so I wouldn't
-- recommend it---just put them in the library part
build-depends: base >=4.6 && <4.7
, hktest -- note that I grab all the hktest
-- modules here
hs-source-dirs: exe
If I leave out one of those modules I'll likely get a build error as Cabal compiles files which expect to be able to find symbols that haven't been packaged.
In your case, since you're building an executable, the common pattern exemplified above is to put all of your code into a library and then have the executable side depend upon that library. For instance, in this example the complete text of exe/Server.hs is
module Main where
import qualified HKTest as HK
main :: IO ()
main = HK.main

cabal FFI dependency

I am making a small Haskell game in Windows, where I would like to respond each time the user presses a key. Because getChar behaves strangely on Windows, I use FFI to get access to getch in conio.h, as described here. The relevant code is:
foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt
This works fine, when I run it in ghci, or compile it with ghc. I also want to try making a cabal package out of it, so extending from this question, I include the following in my cabal file:
...
executable noughts
Includes: conio.h
Extra-libraries conio
...
But when I run cabal configure, it tells me:
cabal: Missing dependency on a foreign library:
* Missing C library: conio
It makes sense, because in my haskell platform directory, under ...\Haskell Platform\2012.4.0.0\mingw there is a conio.h file under the include directory, but no other conio file to provide the object code.
Am I doing this the right way, and if so, how can I find out which library to include in my cabal file?
First off, there is not always a one-to-one mapping between C header files and libraries. In this case, the functions declared in conio.h can be found in various runtime libraries, such as crtdll (deprecated) or msvcrt (preferred, I guess).
With the Haskell Platform on Windows, Cabal will look for these libraries in .\mingw\lib (under your Haskell Platform directory): if you ask for msvcrt, it will look for .\mingw\lib\libmsvcrt.a. This specific library should already be shipped with your Haskell Platform. (If you want to point to other directories with lib*.a files, you can use Cabal's --extra-lib-dirs option.)
A tiny example of this would be as follows; this is Main.hs:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
foreign import ccall unsafe "conio.h _putch" c_putch :: CInt -> IO ()
main :: IO ()
main = do
c_putch . toEnum . fromEnum $ '!'
c_putch . toEnum . fromEnum $ '\n'
And this would be something-awesome.cabal:
name: something-awesome
version: 0.1.0.0
build-type: Simple
cabal-version: >=1.8
executable yay
main-is: Main.hs
build-depends: base ==4.5.*
includes: conio.h
extra-libraries: msvcrt
This should work fine:
c:\tmp\something-awesome> dir /B
Main.hs
something-awesome.cabal
c:\tmp\something-awesome> cabal configure
Resolving dependencies...
Configuring something-awesome-0.1.0.0...
c:\tmp\something-awesome> cabal build
Building something-awesome-0.1.0.0...
Preprocessing executable 'yay' for something-awesome-0.1.0.0...
[1 of 1] Compiling Main ( Main.hs, dist\build\yay\yay-tmp\Main.o )
Linking dist\build\yay\yay.exe ...
c:\tmp\something-awesome> dist\build\yay\yay.exe
!

Install part of program with cabal like library

I have simple program written with haskell, i build it with cabal. For example i my program has next directory structure:
my-prog
* Main.hs
* my-prog.cabal
* SomeDirWithHsFiles
- File1.hs
- File2.hs
I want that when i'll make cabal build and cabal install (maybe something else), SomeDirWithHsFiles with *.hs files, installed like a normal haskell library, and then i'll use File1.hs and File2.hs modules in other programm.
How can i do this?
Thank you.
You need to declare your additional files in a library section, like so:
library
exposed-modules: File1
File2
executable foo
main-is: Main.hs
See for example, xmonad's .cabal file.

Resources