I have been trying to use the dynamic loader package which I found from this question. I am very new to Haskell so excuse me if I am making some incredibly rookie mistakes. My problem is that when I attempt to use the resolveFunctions function I get the following error:
DyanmicLoad-exe: /home/ubuntu/DynamicLoadTest/Plugin.o: unknown symbol `ghczmprim_GHCziCString_unpackCStringzh_closure'
DyanmicLoad-exe: user error (Unable to resolve functions!)
I would love it if someone could tell me possibly where I am going wrong here.
Here is my code (I am using the basic stack new structure):
app/Main.hs
Just the main function.
module Main where
import Lib
main :: IO ()
main = libMain
src/Lib.hs
The module is loaded in here.
module Lib
( libMain
) where
import System.Plugins.DynamicLoader
import System.Directory
import Interface
libMain :: IO ()
libMain = do currentDir <- System.Directory.getCurrentDirectory
loadModuleFromPath (currentDir ++ "/Interface.o") Nothing
putStrLn "Loaded Interface"
loadedModule <- loadModuleFromPath (currentDir ++ "/Plugin.o") (Just currentDir)
putStrLn "Loaded Plugin Module!"
resolveFunctions
putStrLn "Resolved Functions"
plugin <- (loadFunction loadedModule "getPlugin") :: IO (JobInterface)
putStrLn "Loaded Plugin"
putStrLn (jobName plugin)
src/Interface.hs
This file is the "plugin interface"
module Interface (
JobInterface (..)
) where
data JobInterface =
JobInterface { jobName :: String
, runJob :: Int -> Int
}
src/Plugin.hs
An example plugin.
module Plugin (
getPlugin
) where
import Interface
getPlugin :: JobInterface
getPlugin = JobInterface "Hello" $ \x -> 1 * x
I am building with stack build followed by stack ghc src/Plugin.hs src/Interface.hs. I am running with stack exec DyanmicLoad-exe.
GHC version is 8.0.1
Full output:
$ stack exec DyanmicLoad-exe
Loaded Interface
Loaded Plugin Module!
DyanmicLoad-exe: /home/ubuntu/DynamicLoadTest/Plugin.o: unknown symbol `ghczmprim_GHCziCString_unpackCStringzh_closure'
DyanmicLoad-exe: user error (Unable to resolve functions!)
Edit 1:
Error with the -dynamic flag on build.
$ stack exec DyanmicLoad-exe
Loaded Interface
Loaded Plugin Module!
DyanmicLoad-exe: /home/ubuntu/DynamicLoadTest/Plugin.o: unhandled ELF relocation(RelA) type 42
DyanmicLoad-exe: user error (Unable to resolve functions!)
Edit 2 .cabal file
name: DyanmicLoad
version: 0.1.0.0
synopsis: Initial project template from stack
description: Please see README.md
homepage: https://github.com/githubuser/DyanmicLoad#readme
license: BSD3
license-file: LICENSE
author: Author name here
maintainer: example#example.com
copyright: 2017 Author name here
category: Web
build-type: Simple
extra-source-files: README.md
cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: Lib
, Interface
build-depends: base >= 4.7 && < 5
, dynamic-loader
, directory
default-language: Haskell2010
executable DyanmicLoad-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -dynamic -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, DyanmicLoad
default-language: Haskell2010
test-suite DyanmicLoad-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, DyanmicLoad
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
source-repository head
type: git
location: https://github.com/githubuser/DyanmicLoad
I need a library to encode data in cp1251 to work with an api which use it.
I found only 2 libs for this purpose. The encoding lib and text-icu lib. The first one looks better just because it can be statically linked to my program.
But I can't even compile it! I am using stack so I add encoding to build-deps in my .cabal file, and then stack solver update my stack yaml file with encoding-0.8 in extra-deps.
but after running stack build I a got an error
Data/Encoding/Preprocessor/XMLMapping.hs:11:8:
Could not find module ‘Text.XML.HaXml.Types’
Use -v to see a list of the files searched for.
Data/Encoding/Preprocessor/XMLMappingBuilder.hs:15:8:
Could not find module ‘Text.XML.HaXml.OneOfN’
Use -v to see a list of the files searched for.
Data/Encoding/Preprocessor/XMLMappingBuilder.hs:16:8:
Could not find module ‘Text.XML.HaXml.XmlContent’
Use -v to see a list of the files searched for.
I tried to use older version of HaXml and encoding but got the same error.
For example I tried to use encoding-0.6.7 with HaXml-1.22.3, after reading changelog https://hackage.haskell.org/package/encoding-0.7.0.2/changelog but got the same error.
In hackage documentation all this modules which encoding can't import exists.
How can I compile this lib? I am using stack 1.0.4, lts-5.6 and ghc-7.10.3 on linux mint x64
stack.yaml
flags: {}
extra-package-dbs: []
packages:
- '.'
extra-deps:
- encoding-0.8
- text-1.2.2.0
resolver: lts-5.6
cabal:
name: hapidry
version: 0.1.1.0
synopsis: Initial project template from stack
description: Please see README.md
homepage: -
license: GPL-2
license-file: LICENSE
author: -
maintainer: -
copyright: GPL
category: network
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: Lib
build-depends: base >= 4.7 && < 5
default-language: Haskell2010
executable hapidry-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, hapidry
, wreq
, ConfigFile
, aeson
, lens
, cryptohash
, binary
, mtl
, base16-bytestring
, bytestring
, containers
, text
, lens-aeson
, data-default
, optparse-applicative
, encoding
default-language: Haskell2010
test-suite hapidry-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, hapidry
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
source-repository head
type: git
location: -
Finally I wrote my own funtion for encoding. It looks like acceptable workaround. And functions for another one-byte encodings can be implemented in the same way.
toCP1251 :: Text -> B.ByteString
toCP1251 = B.pack . T.unpack . T.map replace where
replace l = case (Map.lookup l table) of
(Just x) -> x
(Nothing) -> l
table = Map.fromList $ zip rus cpCodes
cpCodes = map toEnum (168:184:[192 .. 255]) :: [Char]
rus = ['Ё', 'ё', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М',
'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы',
'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к',
'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ',
'ъ', 'ы', 'ь', 'э', 'ю', 'я'] :: [Char]
UPDATE After I added the haskeline dependency, the tests passed.
It appears that cabal test cannot find my test cases even though cabal build runs fine. Below is the output of cabal test (which fails), and then the output of running the test executable's main in GHCI (which passes).
cabal test
Running 1 test suites...
Test suite test-one: RUNNING...
test-one: <stdin>: hGetLine: end of file
Test suite test-one: FAIL
Test suite logged to: dist/test/one-0.1.0.0-test-one.log
0 of 1 test suites (0 of 1 test cases) passed.
main
Cases: 3 Tried: 3 Errors: 0 Failures: 0
Counts {cases = 3, tried = 3, errors = 0, failures = 0}
Here's the test code that produces these outputs:
module Tests (
main
) where
import Data.Char
import Control.Monad
import System.IO
import System.Directory
import Test.HUnit
import Test.QuickCheck
import Main (four)
test1 = TestCase $ assertEqual "test upCase" "FOO" (map toUpper "foo")
test2 = TestCase $ assertEqual "testing that the result is 4" 4 4
test3 = TestCase $ assertEqual "testing that 4 is 4" four 4
tests = TestList [TestLabel "test1" test1, TestLabel "test2" test2, TestLabel "test3" test3]
main = runTestTT $ tests
What should I change to please cabal?
My .cabal file contains:
executable one
main-is: Main.hs
other-modules: Utils
build-depends: base ==4.6.*, mongoDB ==1.4.*, mtl ==2.1.*, directory ==1.2.*, text ==0.11.*, HUnit ==1.2.*, QuickCheck ==2.6.*
hs-source-dirs: src, tests
Test-Suite test-one
type: exitcode-stdio-1.0
main-is: Tests.hs
hs-source-dirs: src, tests
build-depends: base ==4.6.*, mongoDB ==1.4.*, mtl ==2.1.*, directory ==1.2.*, text ==0.11.*, HUnit ==1.2.*, QuickCheck ==2.6.*
You should rename the module Tests to Main, otherwise the test executable won't be built. Quoting the Haskell Report:
A Haskell program is a collection of modules, one of which, by
convention, must be called Main and must export the value main.
Otherwise I don't see anything obviously wrong. Here's a working example based on your code: https://gist.github.com/23Skidoo/8019225
Perhaps you're using an old version of cabal? Consider upgrading to 1.18.
I've implemented a custom preprocessor which creates *.hs files form *.tpl files. It is specified in Setup.hs by using a Build-Type: Custom. Everything works fine, but I can't create tar.gz package from it (using cabal sdist).
Cabal complains, that it can not find the exposed modules which are generated by the preprocessor. The error message is
cabal: Error: Could not find module with any
suffix: ["gc","chs","hsc","x","y","ly","cpphs","hs","lhs"]
How can I make Cabal aware of the fact that the module is not missing, or maybe add tpl to the known file extensions, or something?
This is a known issue with cabal sdist. Use ./dist/setup/setup sdist instead.
Here's an example:
$ cat preprocessor-test.cabal
name: preprocessor-test
version: 0.1.0.0
build-type: Custom
cabal-version: >=1.10
extra-source-files: PreprocessorTest/*.prepro
library
exposed-modules: PreprocessorTest.PreprocessorTest
build-depends: base ==4.5.*
-- hs-source-dirs:
default-language: Haskell2010
$ cat Setup.hs
#!/usr/bin/env runhaskell
import Distribution.Simple
import Distribution.Simple.PreProcess
import Distribution.Simple.Utils
import Distribution.PackageDescription
import Distribution.Simple.LocalBuildInfo
import System.Cmd (rawSystem)
import System.FilePath ((</>))
main = let hooks = simpleUserHooks
dummy = ("prepro", dummyPreprocessor)
in defaultMainWithHooks hooks
{ hookedPreProcessors = dummy:knownSuffixHandlers }
dummyPreprocessor :: BuildInfo -> LocalBuildInfo -> PreProcessor
dummyPreprocessor build local = PreProcessor {
platformIndependent = True,
runPreProcessor =
mkSimplePreProcessor $ \inFile outFile verbosity -> do
notice verbosity (inFile ++ " is being preprocessed to " ++ outFile)
rawSystem "cp" [inFile, outFile]
return ()
}
$ cat PreprocessorTest/PreprocessorTest.prepro
module PreprocessorTest.PreprocessorTest
where
preprocessorTest :: Int
preprocessorTest = 1
$ cabal configure
Resolving dependencies...
[1 of 1] Compiling Main ( Setup.hs, dist/setup/Main.o )
Linking ./dist/setup/setup ...
Configuring preprocessor-test-0.1.0.0...
$ cabal build
Building preprocessor-test-0.1.0.0...
Preprocessing library preprocessor-test-0.1.0.0...
PreprocessorTest/PreprocessorTest.prepro is being preprocessed to
dist/build/PreprocessorTest/PreprocessorTest.hs
[1 of 1] Compiling PreprocessorTest.PreprocessorTest ( dist/build/PreprocessorTest/PreprocessorTest.hs, dist/build/PreprocessorTest/PreprocessorTest.o )
Registering preprocessor-test-0.1.0.0...
$ ./dist/setup/setup sdist
Distribution quality errors:
No 'synopsis' or 'description' field.
The 'license' field is missing or specified as AllRightsReserved.
Distribution quality warnings:
No 'category' field.
No 'maintainer' field.
Note: the public hackage server would reject this package.
Building source dist for preprocessor-test-0.1.0.0...
Preprocessing library preprocessor-test-0.1.0.0...
PreprocessorTest/PreprocessorTest.prepro is being preprocessed to
dist/src/sdist.-6767/preprocessor-test-0.1.0.0/dist/build/PreprocessorTest/PreprocessorTest.hs
Source tarball created: dist/preprocessor-test-0.1.0.0.tar.gz
$ tar tzf dist/preprocessor-test-0.1.0.0.tar.gz
preprocessor-test-0.1.0.0/
preprocessor-test-0.1.0.0/dist/
preprocessor-test-0.1.0.0/dist/build/
preprocessor-test-0.1.0.0/dist/build/PreprocessorTest/
preprocessor-test-0.1.0.0/dist/build/PreprocessorTest/PreprocessorTest.hs
preprocessor-test-0.1.0.0/Setup.hs
preprocessor-test-0.1.0.0/PreprocessorTest/
preprocessor-test-0.1.0.0/PreprocessorTest/PreprocessorTest.prepro
preprocessor-test-0.1.0.0/preprocessor-test.cabal
I'm trying to get cabal test to run my HUnit test, without much luck. The problem is that it can't find one of my test modules — how do I fix this?
cabal configure --enable-tests && cabal build && cabal test fails with
tests/HUnit/Test.hs:4:18:
Could not find module `AmazonTest'
/tests/HUnit
AmazonTest.hs
module AmazonTest where
import Test.HUnit
import Lib.Amazon
tests = TestList [ "test sayHello" ~: "Hell!" ~=? sayHello ]
Test.hs
module Main where
import Test.HUnit
import qualified AmazonTest as Amazon
main = runTestTT Amazon.tests
\Lib\Amazon.hs
module Lib.Amazon where
sayHello :: String
sayHello = "Hello!"
test part of my .cabal file
test-suite test
type: exitcode-stdio-1.0
main-is: tests/HUnit/Test.hs
hs-source-dirs: .
ghc-options: -Wall
build-depends: base
, myapp
, yesod-test >= 0.3 && < 0.4
, yesod-default
, yesod-core
, persistent
, persistent-postgresql
, resourcet
, monad-logger
, HUnit
, text
Add tests/HUnit to hs-source-dirs. hs-source-dirs are not searched recursively.