Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  1. How can I get my dependencies to work in a way to make this distributable?
  2. 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!

like image 534
Attic Avatar asked Dec 06 '13 14:12

Attic


2 Answers

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.

like image 116
Joseph Victor Avatar answered Nov 19 '22 18:11

Joseph Victor


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
like image 44
J. Abrahamson Avatar answered Nov 19 '22 19:11

J. Abrahamson